зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to Places.
This commit is contained in:
Коммит
bf23f7fcc4
|
@ -172,7 +172,7 @@ EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID)
|
|||
endif
|
||||
|
||||
SYMBOL_INDEX_NAME = \
|
||||
$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_ARCH)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
|
||||
$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
|
||||
|
||||
buildsymbols:
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
|
|
|
@ -140,27 +140,19 @@ public:
|
|||
virtual void RemoveNativeRootAccessible(nsAccessible* aRootAccessible) = 0;
|
||||
|
||||
/**
|
||||
* Used to describe sort of changes leading to accessible tree invalidation.
|
||||
* Notification used to update the accessible tree when new content is
|
||||
* inserted.
|
||||
*/
|
||||
enum {
|
||||
NODE_APPEND = 0x01,
|
||||
NODE_REMOVE = 0x02,
|
||||
NODE_SIGNIFICANT_CHANGE = 0x03,
|
||||
FRAME_SHOW = 0x04,
|
||||
FRAME_HIDE = 0x05,
|
||||
FRAME_SIGNIFICANT_CHANGE = 0x06
|
||||
};
|
||||
virtual void ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild) = 0;
|
||||
|
||||
/**
|
||||
* Invalidate the accessible tree when DOM tree or frame tree is changed.
|
||||
*
|
||||
* @param aPresShell [in] the presShell where changes occurred
|
||||
* @param aContent [in] the affected DOM content
|
||||
* @param aChangeType [in] the change type (see constants declared above)
|
||||
* Notification used to update the accessible tree when content is removed.
|
||||
*/
|
||||
virtual nsresult InvalidateSubtreeFor(nsIPresShell *aPresShell,
|
||||
nsIContent *aContent,
|
||||
PRUint32 aChangeType) = 0;
|
||||
virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
|
||||
nsIContent* aChild) = 0;
|
||||
|
||||
/**
|
||||
* Notify accessibility that anchor jump has been accomplished to the given
|
||||
|
@ -174,6 +166,12 @@ public:
|
|||
*/
|
||||
virtual void PresShellDestroyed(nsIPresShell *aPresShell) = 0;
|
||||
|
||||
/**
|
||||
* Recreate an accessible for the given content node in the presshell.
|
||||
*/
|
||||
virtual void RecreateAccessible(nsIPresShell* aPresShell,
|
||||
nsIContent* aContent) = 0;
|
||||
|
||||
/**
|
||||
* Fire accessible event of the given type for the given target.
|
||||
*
|
||||
|
|
|
@ -64,19 +64,15 @@
|
|||
// AccEvent constructors
|
||||
|
||||
AccEvent::AccEvent(PRUint32 aEventType, nsAccessible* aAccessible,
|
||||
PRBool aIsAsync, EIsFromUserInput aIsFromUserInput,
|
||||
EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync),
|
||||
mAccessible(aAccessible)
|
||||
EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mAccessible(aAccessible)
|
||||
{
|
||||
CaptureIsFromUserInput(aIsFromUserInput);
|
||||
}
|
||||
|
||||
AccEvent::AccEvent(PRUint32 aEventType, nsINode* aNode,
|
||||
PRBool aIsAsync, EIsFromUserInput aIsFromUserInput,
|
||||
EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync),
|
||||
mNode(aNode)
|
||||
EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mNode(aNode)
|
||||
{
|
||||
CaptureIsFromUserInput(aIsFromUserInput);
|
||||
}
|
||||
|
@ -217,36 +213,6 @@ AccEvent::CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput)
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccReorderEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccReorderEvent::
|
||||
AccReorderEvent(nsAccessible* aAccTarget, PRBool aIsAsynch,
|
||||
PRBool aIsUnconditional, nsINode* aReasonNode) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aAccTarget,
|
||||
aIsAsynch, eAutoDetect, AccEvent::eCoalesceFromSameSubtree),
|
||||
mUnconditionalEvent(aIsUnconditional), mReasonNode(aReasonNode)
|
||||
{
|
||||
}
|
||||
|
||||
PRBool
|
||||
AccReorderEvent::IsUnconditionalEvent()
|
||||
{
|
||||
return mUnconditionalEvent;
|
||||
}
|
||||
|
||||
PRBool
|
||||
AccReorderEvent::HasAccessibleInReasonSubtree()
|
||||
{
|
||||
if (!mReasonNode)
|
||||
return PR_FALSE;
|
||||
|
||||
nsAccessible *accessible = GetAccService()->GetAccessible(mReasonNode);
|
||||
return accessible || nsAccUtils::HasAccessibleChildren(mReasonNode);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccStateChangeEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -257,9 +223,8 @@ AccReorderEvent::HasAccessibleInReasonSubtree()
|
|||
AccStateChangeEvent::
|
||||
AccStateChangeEvent(nsAccessible* aAccessible,
|
||||
PRUint32 aState, PRBool aIsExtraState,
|
||||
PRBool aIsEnabled, PRBool aIsAsynch,
|
||||
EIsFromUserInput aIsFromUserInput):
|
||||
AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, aIsAsynch,
|
||||
PRBool aIsEnabled, EIsFromUserInput aIsFromUserInput):
|
||||
AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
|
||||
aIsFromUserInput, eAllowDupes),
|
||||
mState(aState), mIsExtraState(aIsExtraState), mIsEnabled(aIsEnabled)
|
||||
{
|
||||
|
@ -315,11 +280,11 @@ AccStateChangeEvent::CreateXPCOMObject()
|
|||
AccTextChangeEvent::
|
||||
AccTextChangeEvent(nsAccessible* aAccessible, PRInt32 aStart,
|
||||
nsAString& aModifiedText, PRBool aIsInserted,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput)
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
: AccEvent(aIsInserted ?
|
||||
static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_INSERTED) :
|
||||
static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_REMOVED),
|
||||
aAccessible, aIsAsynch, aIsFromUserInput, eAllowDupes)
|
||||
aAccessible, aIsFromUserInput, eAllowDupes)
|
||||
, mStart(aStart)
|
||||
, mIsInserted(aIsInserted)
|
||||
, mModifiedText(aModifiedText)
|
||||
|
@ -335,37 +300,62 @@ AccTextChangeEvent::CreateXPCOMObject()
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccMutationEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccMutationEvent::
|
||||
AccMutationEvent(PRUint32 aEventType, nsAccessible* aTarget,
|
||||
nsINode* aTargetNode, EIsFromUserInput aIsFromUserInput) :
|
||||
AccEvent(aEventType, aTarget, aIsFromUserInput, eCoalesceFromSameSubtree)
|
||||
{
|
||||
mNode = aTargetNode;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccHideEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccHideEvent::
|
||||
AccHideEvent(nsAccessible* aTarget, nsINode* aTargetNode,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput) :
|
||||
AccEvent(nsIAccessibleEvent::EVENT_HIDE, aTarget, aIsAsynch,
|
||||
aIsFromUserInput, eCoalesceFromSameSubtree)
|
||||
EIsFromUserInput aIsFromUserInput) :
|
||||
AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode,
|
||||
aIsFromUserInput)
|
||||
{
|
||||
mNode = aTargetNode;
|
||||
mParent = mAccessible->GetCachedParent();
|
||||
mNextSibling = mAccessible->GetCachedNextSibling();
|
||||
mPrevSibling = mAccessible->GetCachedPrevSibling();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccShowEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccShowEvent::
|
||||
AccShowEvent(nsAccessible* aTarget, nsINode* aTargetNode,
|
||||
EIsFromUserInput aIsFromUserInput) :
|
||||
AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget, aTargetNode,
|
||||
aIsFromUserInput)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccCaretMoveEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccCaretMoveEvent::
|
||||
AccCaretMoveEvent(nsAccessible* aAccessible, PRInt32 aCaretOffset) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible, PR_TRUE), // Currently always asynch
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible),
|
||||
mCaretOffset(aCaretOffset)
|
||||
{
|
||||
}
|
||||
|
||||
AccCaretMoveEvent::
|
||||
AccCaretMoveEvent(nsINode* aNode) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode, PR_TRUE), // Currently always asynch
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode),
|
||||
mCaretOffset(-1)
|
||||
{
|
||||
}
|
||||
|
@ -385,9 +375,8 @@ AccCaretMoveEvent::CreateXPCOMObject()
|
|||
|
||||
AccTableChangeEvent::
|
||||
AccTableChangeEvent(nsAccessible* aAccessible, PRUint32 aEventType,
|
||||
PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols,
|
||||
PRBool aIsAsynch) :
|
||||
AccEvent(aEventType, aAccessible, aIsAsynch),
|
||||
PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols) :
|
||||
AccEvent(aEventType, aAccessible),
|
||||
mRowOrColIndex(aRowOrColIndex), mNumRowsOrCols(aNumRowsOrCols)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#ifndef _AccEvent_H_
|
||||
#define _AccEvent_H_
|
||||
|
||||
#include "nsIAccessibleEvent.h"
|
||||
|
||||
#include "nsAccessible.h"
|
||||
|
||||
class nsAccEvent;
|
||||
|
@ -90,11 +92,10 @@ public:
|
|||
|
||||
// Initialize with an nsIAccessible
|
||||
AccEvent(PRUint32 aEventType, nsAccessible* aAccessible,
|
||||
PRBool aIsAsynch = PR_FALSE,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect,
|
||||
EEventRule aEventRule = eRemoveDupes);
|
||||
// Initialize with an nsIDOMNode
|
||||
AccEvent(PRUint32 aEventType, nsINode* aNode, PRBool aIsAsynch = PR_FALSE,
|
||||
AccEvent(PRUint32 aEventType, nsINode* aNode,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect,
|
||||
EEventRule aEventRule = eRemoveDupes);
|
||||
virtual ~AccEvent() {}
|
||||
|
@ -102,7 +103,6 @@ public:
|
|||
// AccEvent
|
||||
PRUint32 GetEventType() const { return mEventType; }
|
||||
EEventRule GetEventRule() const { return mEventRule; }
|
||||
PRBool IsAsync() const { return mIsAsync; }
|
||||
PRBool IsFromUserInput() const { return mIsFromUserInput; }
|
||||
|
||||
nsAccessible *GetAccessible();
|
||||
|
@ -119,10 +119,11 @@ public:
|
|||
*/
|
||||
enum EventGroup {
|
||||
eGenericEvent,
|
||||
eReorderEvent,
|
||||
eStateChangeEvent,
|
||||
eTextChangeEvent,
|
||||
eMutationEvent,
|
||||
eHideEvent,
|
||||
eShowEvent,
|
||||
eCaretMoveEvent,
|
||||
eTableChangeEvent
|
||||
};
|
||||
|
@ -154,7 +155,6 @@ protected:
|
|||
PRBool mIsFromUserInput;
|
||||
PRUint32 mEventType;
|
||||
EEventRule mEventRule;
|
||||
PRPackedBool mIsAsync;
|
||||
nsRefPtr<nsAccessible> mAccessible;
|
||||
nsCOMPtr<nsINode> mNode;
|
||||
|
||||
|
@ -162,39 +162,6 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible reorder event.
|
||||
*/
|
||||
class AccReorderEvent : public AccEvent
|
||||
{
|
||||
public:
|
||||
AccReorderEvent(nsAccessible* aAccTarget, PRBool aIsAsynch,
|
||||
PRBool aIsUnconditional, nsINode* aReasonNode);
|
||||
|
||||
// AccEvent
|
||||
static const EventGroup kEventGroup = eReorderEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccEvent::GetEventGroups() | (1U << eReorderEvent);
|
||||
}
|
||||
|
||||
// AccReorderEvent
|
||||
/**
|
||||
* Return true if event is unconditional, i.e. must be fired.
|
||||
*/
|
||||
PRBool IsUnconditionalEvent();
|
||||
|
||||
/**
|
||||
* Return true if changed DOM node has accessible in its tree.
|
||||
*/
|
||||
PRBool HasAccessibleInReasonSubtree();
|
||||
|
||||
private:
|
||||
PRBool mUnconditionalEvent;
|
||||
nsCOMPtr<nsINode> mReasonNode;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible state change event.
|
||||
*/
|
||||
|
@ -203,7 +170,7 @@ class AccStateChangeEvent: public AccEvent
|
|||
public:
|
||||
AccStateChangeEvent(nsAccessible* aAccessible,
|
||||
PRUint32 aState, PRBool aIsExtraState,
|
||||
PRBool aIsEnabled, PRBool aIsAsynch = PR_FALSE,
|
||||
PRBool aIsEnabled,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
AccStateChangeEvent(nsINode* aNode, PRUint32 aState, PRBool aIsExtraState,
|
||||
|
@ -239,8 +206,7 @@ class AccTextChangeEvent: public AccEvent
|
|||
{
|
||||
public:
|
||||
AccTextChangeEvent(nsAccessible* aAccessible, PRInt32 aStart,
|
||||
nsAString& aModifiedText,
|
||||
PRBool aIsInserted, PRBool aIsAsynch = PR_FALSE,
|
||||
nsAString& aModifiedText, PRBool aIsInserted,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
// AccEvent
|
||||
|
@ -269,31 +235,75 @@ private:
|
|||
|
||||
|
||||
/**
|
||||
* Accessible hide events.
|
||||
* Base class for show and hide accessible events.
|
||||
*/
|
||||
class AccHideEvent : public AccEvent
|
||||
class AccMutationEvent: public AccEvent
|
||||
{
|
||||
public:
|
||||
AccMutationEvent(PRUint32 aEventType, nsAccessible* aTarget,
|
||||
nsINode* aTargetNode, EIsFromUserInput aIsFromUserInput);
|
||||
|
||||
// Event
|
||||
static const EventGroup kEventGroup = eMutationEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccEvent::GetEventGroups() | (1U << eMutationEvent);
|
||||
}
|
||||
|
||||
// MutationEvent
|
||||
bool IsShow() const { return mEventType == nsIAccessibleEvent::EVENT_SHOW; }
|
||||
bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; }
|
||||
|
||||
protected:
|
||||
nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
|
||||
|
||||
friend class nsAccEventQueue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible hide event.
|
||||
*/
|
||||
class AccHideEvent: public AccMutationEvent
|
||||
{
|
||||
public:
|
||||
AccHideEvent(nsAccessible* aTarget, nsINode* aTargetNode,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput);
|
||||
EIsFromUserInput aIsFromUserInput);
|
||||
|
||||
// Event
|
||||
static const EventGroup kEventGroup = eHideEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccEvent::GetEventGroups() | (1U << eHideEvent);
|
||||
return AccMutationEvent::GetEventGroups() | (1U << eHideEvent);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsRefPtr<nsAccessible> mParent;
|
||||
nsRefPtr<nsAccessible> mNextSibling;
|
||||
nsRefPtr<nsAccessible> mPrevSibling;
|
||||
nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
|
||||
|
||||
friend class nsAccEventQueue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible show event.
|
||||
*/
|
||||
class AccShowEvent: public AccMutationEvent
|
||||
{
|
||||
public:
|
||||
AccShowEvent(nsAccessible* aTarget, nsINode* aTargetNode,
|
||||
EIsFromUserInput aIsFromUserInput);
|
||||
|
||||
// Event
|
||||
static const EventGroup kEventGroup = eShowEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccMutationEvent::GetEventGroups() | (1U << eShowEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible caret move event.
|
||||
*/
|
||||
|
@ -327,8 +337,7 @@ class AccTableChangeEvent : public AccEvent
|
|||
{
|
||||
public:
|
||||
AccTableChangeEvent(nsAccessible* aAccessible, PRUint32 aEventType,
|
||||
PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols,
|
||||
PRBool aIsAsynch);
|
||||
PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols);
|
||||
|
||||
// AccEvent
|
||||
virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
|
||||
|
|
|
@ -72,8 +72,7 @@ nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
|
|||
// Ensure CacheChildren is called before we query cache.
|
||||
nsAccessNode::GetApplicationAccessible()->EnsureChildren();
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
|
||||
nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
|
||||
if (docAcc)
|
||||
return docAcc;
|
||||
|
||||
|
@ -81,10 +80,10 @@ nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
|
|||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccDocManager::FindAccessibleInCache(void *aUniqueID) const
|
||||
nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
|
||||
{
|
||||
nsSearchAccessibleInCacheArg arg;
|
||||
arg.mUniqueID = aUniqueID;
|
||||
arg.mNode = aNode;
|
||||
|
||||
mDocAccessibleCache.EnumerateRead(SearchAccessibleInDocCache,
|
||||
static_cast<void*>(&arg));
|
||||
|
@ -136,8 +135,7 @@ nsAccDocManager::Shutdown()
|
|||
void
|
||||
nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument)
|
||||
{
|
||||
nsDocAccessible* docAccessible =
|
||||
mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
|
||||
nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(aDocument);
|
||||
if (!docAccessible)
|
||||
return;
|
||||
|
||||
|
@ -146,7 +144,7 @@ nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument)
|
|||
// are removed automatically when chrome event target goes away.
|
||||
|
||||
docAccessible->Shutdown();
|
||||
mDocAccessibleCache.Remove(static_cast<void*>(aDocument));
|
||||
mDocAccessibleCache.Remove(aDocument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -215,8 +213,7 @@ nsAccDocManager::OnStateChange(nsIWebProgress *aWebProgress,
|
|||
if (!IsEventTargetDocument(document))
|
||||
return NS_OK;
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
mDocAccessibleCache.GetWeak(static_cast<void*>(document));
|
||||
nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(document);
|
||||
if (!docAcc)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -346,9 +343,7 @@ nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
|
|||
{
|
||||
// Document accessible can be created before we were notified the DOM document
|
||||
// was loaded completely. However if it's not created yet then create it.
|
||||
nsDocAccessible *docAcc =
|
||||
mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
|
||||
|
||||
nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
|
||||
if (!docAcc) {
|
||||
docAcc = CreateDocOrRootAccessible(aDocument);
|
||||
NS_ASSERTION(docAcc, "Can't create document accessible!");
|
||||
|
@ -365,16 +360,8 @@ nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
|
|||
// documents
|
||||
// b) document load event on sub documents causes screen readers to act is if
|
||||
// entire page is reloaded.
|
||||
if (!IsEventTargetDocument(aDocument)) {
|
||||
// XXX: AT doesn't update their virtual buffer once frame is loaded and it
|
||||
// has dynamic content added after frame load. There's something wrong how
|
||||
// we handle this changes.
|
||||
if (!nsCoreUtils::IsRootDocument(aDocument)) {
|
||||
docAcc->InvalidateCacheSubtree(nsnull,
|
||||
nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE);
|
||||
}
|
||||
if (!IsEventTargetDocument(aDocument))
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire complete/load stopped if the load event type is given.
|
||||
if (aLoadEventType) {
|
||||
|
@ -493,7 +480,7 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
|||
return nsnull;
|
||||
|
||||
// Cache and addref document accessible.
|
||||
if (!mDocAccessibleCache.Put(static_cast<void*>(aDocument), docAcc)) {
|
||||
if (!mDocAccessibleCache.Put(aDocument, docAcc)) {
|
||||
delete docAcc;
|
||||
return nsnull;
|
||||
}
|
||||
|
@ -503,7 +490,7 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
|||
// while initialized.
|
||||
if (!outerDocAcc->AppendChild(docAcc) ||
|
||||
!GetAccService()->InitAccessible(docAcc, nsAccUtils::GetRoleMapEntry(aDocument))) {
|
||||
mDocAccessibleCache.Remove(static_cast<void*>(aDocument));
|
||||
mDocAccessibleCache.Remove(aDocument);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
@ -546,7 +533,7 @@ nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
|
|||
// nsAccDocManager static
|
||||
|
||||
PLDHashOperator
|
||||
nsAccDocManager::ClearDocCacheEntry(const void* aKey,
|
||||
nsAccDocManager::ClearDocCacheEntry(const nsIDocument* aKey,
|
||||
nsRefPtr<nsDocAccessible>& aDocAccessible,
|
||||
void* aUserArg)
|
||||
{
|
||||
|
@ -560,7 +547,7 @@ nsAccDocManager::ClearDocCacheEntry(const void* aKey,
|
|||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsAccDocManager::SearchAccessibleInDocCache(const void* aKey,
|
||||
nsAccDocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
|
||||
nsDocAccessible* aDocAccessible,
|
||||
void* aUserArg)
|
||||
{
|
||||
|
@ -570,7 +557,7 @@ nsAccDocManager::SearchAccessibleInDocCache(const void* aKey,
|
|||
if (aDocAccessible) {
|
||||
nsSearchAccessibleInCacheArg* arg =
|
||||
static_cast<nsSearchAccessibleInCacheArg*>(aUserArg);
|
||||
arg->mAccessible = aDocAccessible->GetCachedAccessible(arg->mUniqueID);
|
||||
arg->mAccessible = aDocAccessible->GetCachedAccessible(arg->mNode);
|
||||
if (arg->mAccessible)
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
* Search through all document accessibles for an accessible with the given
|
||||
* unique id.
|
||||
*/
|
||||
nsAccessible *FindAccessibleInCache(void *aUniqueID) const;
|
||||
nsAccessible* FindAccessibleInCache(nsINode* aNode) const;
|
||||
|
||||
/**
|
||||
* Shutdown document accessibles in the tree starting from the given one.
|
||||
|
@ -87,7 +87,7 @@ public:
|
|||
*/
|
||||
inline nsDocAccessible* GetDocAccessibleFromCache(nsIDocument* aDocument) const
|
||||
{
|
||||
return mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
|
||||
return mDocAccessibleCache.GetWeak(aDocument);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -162,14 +162,14 @@ private:
|
|||
void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
|
||||
nsIDocument *aDocument);
|
||||
|
||||
typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible>
|
||||
typedef nsRefPtrHashtable<nsPtrHashKey<const nsIDocument>, nsDocAccessible>
|
||||
nsDocAccessibleHashtable;
|
||||
|
||||
/**
|
||||
* Shutdown and remove the document accessible from cache.
|
||||
*/
|
||||
static PLDHashOperator
|
||||
ClearDocCacheEntry(const void* aKey,
|
||||
ClearDocCacheEntry(const nsIDocument* aKey,
|
||||
nsRefPtr<nsDocAccessible>& aDocAccessible,
|
||||
void* aUserArg);
|
||||
|
||||
|
@ -184,11 +184,11 @@ private:
|
|||
struct nsSearchAccessibleInCacheArg
|
||||
{
|
||||
nsAccessible *mAccessible;
|
||||
void *mUniqueID;
|
||||
nsINode* mNode;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
SearchAccessibleInDocCache(const void* aKey,
|
||||
SearchAccessibleInDocCache(const nsIDocument* aKey,
|
||||
nsDocAccessible* aDocAccessible,
|
||||
void* aUserArg);
|
||||
|
||||
|
|
|
@ -152,9 +152,12 @@ nsAccessNode::Shutdown()
|
|||
}
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHODIMP nsAccessNode::GetUniqueID(void **aUniqueID)
|
||||
NS_IMETHODIMP
|
||||
nsAccessNode::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
*aUniqueID = static_cast<void*>(GetNode());
|
||||
NS_ENSURE_ARG_POINTER(aUniqueID);
|
||||
|
||||
*aUniqueID = UniqueID();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -310,6 +313,12 @@ nsAccessNode::GetFrame()
|
|||
return mContent ? mContent->GetPrimaryFrame() : nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsAccessNode::IsPrimaryForNode() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAccessNode
|
||||
|
||||
|
|
|
@ -181,6 +181,20 @@ public:
|
|||
*/
|
||||
nsIWeakReference* GetWeakShell() const { return mWeakShell; }
|
||||
|
||||
/**
|
||||
* Return the unique identifier of the accessible.
|
||||
*/
|
||||
void* UniqueID() { return static_cast<void*>(this); }
|
||||
|
||||
/**
|
||||
* Return true if the accessible is primary accessible for the given DOM node.
|
||||
*
|
||||
* Accessible hierarchy may be complex for single DOM node, in this case
|
||||
* these accessibles share the same DOM node. The primary accessible "owns"
|
||||
* that DOM node in terms it gets stored in the accessible to node map.
|
||||
*/
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
protected:
|
||||
nsPresContext* GetPresContext();
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#include "nsRootAccessibleWrap.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULAlertAccessible.h"
|
||||
|
@ -470,6 +471,62 @@ nsAccessibilityService::CreateHTMLCaptionAccessible(nsIContent* aContent,
|
|||
return accessible;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild)
|
||||
{
|
||||
#ifdef DEBUG_A11Y
|
||||
nsAutoString tag;
|
||||
aStartChild->Tag()->ToString(tag);
|
||||
nsIAtom* id = aStartChild->GetID();
|
||||
nsCAutoString strid;
|
||||
if (id)
|
||||
id->ToUTF8String(strid);
|
||||
nsAutoString ctag;
|
||||
aContainer->Tag()->ToString(ctag);
|
||||
nsIAtom* cid = aContainer->GetID();
|
||||
nsCAutoString strcid;
|
||||
if (cid)
|
||||
cid->ToUTF8String(strcid);
|
||||
printf("\ncontent inserted: %s@id='%s', container: %s@id='%s', end node: %p\n\n",
|
||||
NS_ConvertUTF16toUTF8(tag).get(), strid.get(),
|
||||
NS_ConvertUTF16toUTF8(ctag).get(), strcid.get(), aEndChild);
|
||||
#endif
|
||||
|
||||
// XXX: bug 606082. aContainer is null when root element is inserted into
|
||||
// document, we need to handle this and update the tree, also we need to
|
||||
// update a content node of the document accessible.
|
||||
if (aContainer) {
|
||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->UpdateTree(aContainer, aStartChild, aEndChild, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild)
|
||||
{
|
||||
#ifdef DEBUG_A11Y
|
||||
nsAutoString id;
|
||||
aChild->Tag()->ToString(id);
|
||||
printf("\ncontent removed: %s\n", NS_ConvertUTF16toUTF8(id).get());
|
||||
#endif
|
||||
|
||||
// XXX: bug 606082. aContainer is null when root element is inserted into
|
||||
// document, we need to handle this and update the tree, perhaps destroy
|
||||
// the document accessible.
|
||||
if (aContainer) {
|
||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->UpdateTree(aContainer, aChild, aChild->GetNextSibling(),
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
||||
{
|
||||
|
@ -489,14 +546,22 @@ nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
|||
ShutdownDocAccessible(doc);
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
|
||||
nsIContent* aContent)
|
||||
{
|
||||
nsDocAccessible* document = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (document)
|
||||
document->RecreateAccessible(aContent);
|
||||
}
|
||||
|
||||
// nsAccessibilityService protected
|
||||
nsAccessible *
|
||||
nsAccessibilityService::GetCachedAccessible(nsINode *aNode,
|
||||
nsIWeakReference *aWeakShell)
|
||||
{
|
||||
nsDocAccessible *docAccessible = GetDocAccessible(aNode->GetOwnerDoc());
|
||||
return docAccessible ?
|
||||
docAccessible->GetCachedAccessible(static_cast<void*>(aNode)) : nsnull;
|
||||
return docAccessible ? docAccessible->GetCachedAccessible(aNode) : nsnull;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -694,7 +759,7 @@ nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
|
|||
// "unofficially" shutdown document (i.e. not from nsAccDocManager) can still
|
||||
// exist in the document cache.
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
|
||||
nsAccessible* accessible = FindAccessibleInCache(static_cast<void*>(node));
|
||||
nsAccessible* accessible = FindAccessibleInCache(node);
|
||||
if (!accessible) {
|
||||
nsCOMPtr<nsIDocument> document(do_QueryInterface(node));
|
||||
if (document)
|
||||
|
@ -732,7 +797,7 @@ nsAccessibilityService::GetAccessible(nsINode* aNode)
|
|||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccessibilityService::GetCachedContainerAccessible(nsINode* aNode)
|
||||
nsAccessibilityService::GetCachedAccessibleOrContainer(nsINode* aNode)
|
||||
{
|
||||
if (!aNode)
|
||||
return nsnull;
|
||||
|
@ -749,8 +814,8 @@ nsAccessibilityService::GetCachedContainerAccessible(nsINode* aNode)
|
|||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
||||
|
||||
nsAccessible *accessible = nsnull;
|
||||
while ((currNode = currNode->GetNodeParent()) &&
|
||||
!(accessible = GetCachedAccessible(currNode, weakShell)));
|
||||
while (!(accessible = GetCachedAccessible(currNode, weakShell)) &&
|
||||
(currNode = currNode->GetNodeParent()));
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
@ -857,8 +922,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
|||
nsWeakFrame weakFrame = content->GetPrimaryFrame();
|
||||
|
||||
// Check frame to see if it is hidden.
|
||||
if (!weakFrame.GetFrame() ||
|
||||
!weakFrame.GetFrame()->GetStyleVisibility()->IsVisible()) {
|
||||
if (!weakFrame.GetFrame()) {
|
||||
if (aIsHidden)
|
||||
*aIsHidden = PR_TRUE;
|
||||
|
||||
|
@ -1195,23 +1259,24 @@ nsAccessibilityService::GetAccessibleByRule(nsINode* aNode,
|
|||
if (!aNode || !aWeakShell)
|
||||
return nsnull;
|
||||
|
||||
nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell);
|
||||
if (cachedAcc) {
|
||||
if (aWhatToGet & eGetAccForNode)
|
||||
if (aWhatToGet & eGetAccForNode) {
|
||||
nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell);
|
||||
if (cachedAcc && cachedAcc->IsBoundToParent())
|
||||
return cachedAcc;
|
||||
|
||||
// XXX: while nsAccessible::GetParent() tries to repair broken tree and
|
||||
// may not return cached parent then we use GetAccessibleOrContainer().
|
||||
return GetAccessibleByRule(aNode->GetNodeParent(), aWeakShell,
|
||||
eGetAccForNodeOrContainer);
|
||||
}
|
||||
|
||||
// Go up looking for the nearest accessible container stored in cache.
|
||||
// Go up looking for the nearest accessible container having cached children.
|
||||
nsTArray<nsINode*> nodes;
|
||||
|
||||
nsINode* node = aNode;
|
||||
while ((node = node->GetNodeParent()) &&
|
||||
!(cachedAcc = GetCachedAccessible(node, aWeakShell)))
|
||||
nsAccessible* cachedAcc = nsnull;
|
||||
while ((node = node->GetNodeParent())) {
|
||||
cachedAcc = GetCachedAccessible(node, aWeakShell);
|
||||
if (cachedAcc && cachedAcc->IsBoundToParent())
|
||||
break;
|
||||
|
||||
nodes.AppendElement(node);
|
||||
}
|
||||
|
||||
// Node is not in accessible document.
|
||||
if (!cachedAcc)
|
||||
|
@ -1713,29 +1778,6 @@ nsAccessibilityService::RemoveNativeRootAccessible(nsAccessible* aAccessible)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Called from layout when the frame tree owned by a node changes significantly
|
||||
nsresult
|
||||
nsAccessibilityService::InvalidateSubtreeFor(nsIPresShell *aShell,
|
||||
nsIContent *aChangeContent,
|
||||
PRUint32 aChangeType)
|
||||
{
|
||||
NS_ASSERTION(aChangeType == nsIAccessibilityService::FRAME_SIGNIFICANT_CHANGE ||
|
||||
aChangeType == nsIAccessibilityService::FRAME_SHOW ||
|
||||
aChangeType == nsIAccessibilityService::FRAME_HIDE ||
|
||||
aChangeType == nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE ||
|
||||
aChangeType == nsIAccessibilityService::NODE_APPEND ||
|
||||
aChangeType == nsIAccessibilityService::NODE_REMOVE,
|
||||
"Incorrect aEvent passed in");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aShell);
|
||||
|
||||
nsDocAccessible *docAccessible = GetDocAccessible(aShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->InvalidateCacheSubtree(aChangeContent, aChangeType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NS_GetAccessibilityService
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -110,14 +110,21 @@ public:
|
|||
virtual nsAccessible* AddNativeRootAccessible(void* aAtkAccessible);
|
||||
virtual void RemoveNativeRootAccessible(nsAccessible* aRootAccessible);
|
||||
|
||||
virtual nsresult InvalidateSubtreeFor(nsIPresShell *aPresShell,
|
||||
nsIContent *aContent,
|
||||
PRUint32 aChangeType);
|
||||
virtual void ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild);
|
||||
|
||||
virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
|
||||
nsIContent* aChild);
|
||||
|
||||
virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
|
||||
|
||||
virtual void PresShellDestroyed(nsIPresShell* aPresShell);
|
||||
|
||||
virtual void RecreateAccessible(nsIPresShell* aPresShell,
|
||||
nsIContent* aContent);
|
||||
|
||||
virtual void FireAccessibleEvent(PRUint32 aEvent, nsAccessible* aTarget);
|
||||
|
||||
// nsAccessibiltiyService
|
||||
|
@ -178,12 +185,22 @@ public:
|
|||
return GetAccessibleByRule(aNode, aWeakShell, eGetAccForContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return cached accessible for the given DOM node or cached container
|
||||
* accessible if there's no cached accessible for the given node.
|
||||
*/
|
||||
nsAccessible* GetCachedAccessibleOrContainer(nsINode* aNode);
|
||||
|
||||
/**
|
||||
* Return the first cached accessible parent of a DOM node.
|
||||
*
|
||||
* @param aDOMNode [in] the DOM node to get an accessible for
|
||||
*/
|
||||
nsAccessible* GetCachedContainerAccessible(nsINode *aNode);
|
||||
inline nsAccessible* GetCachedContainerAccessible(nsINode *aNode)
|
||||
{
|
||||
return aNode ?
|
||||
GetCachedAccessibleOrContainer(aNode->GetNodeParent()) : nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an accessible and cache it. The method should be called for
|
||||
|
|
|
@ -2629,16 +2629,11 @@ nsAccessible::Init()
|
|||
if (!nsAccessNodeWrap::Init())
|
||||
return PR_FALSE;
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
nsDocAccessible* document =
|
||||
GetAccService()->GetDocAccessible(mContent->GetOwnerDoc());
|
||||
NS_ASSERTION(docAcc, "Cannot cache new nsAccessible!");
|
||||
if (!docAcc)
|
||||
return PR_FALSE;
|
||||
NS_ASSERTION(document, "Cannot cache new nsAccessible!");
|
||||
|
||||
void *uniqueID = nsnull;
|
||||
GetUniqueID(&uniqueID);
|
||||
|
||||
return docAcc->CacheAccessible(uniqueID, this);
|
||||
return document ? document->CacheAccessible(this) : PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2647,10 +2642,8 @@ nsAccessible::Shutdown()
|
|||
// Invalidate the child count and pointers to other accessibles, also make
|
||||
// sure none of its children point to this parent
|
||||
InvalidateChildren();
|
||||
if (mParent) {
|
||||
mParent->InvalidateChildren();
|
||||
UnbindFromParent();
|
||||
}
|
||||
if (mParent)
|
||||
mParent->RemoveChild(this);
|
||||
|
||||
nsAccessNodeWrap::Shutdown();
|
||||
}
|
||||
|
@ -2699,14 +2692,14 @@ nsAccessible::BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent)
|
|||
{
|
||||
NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
|
||||
|
||||
if (mParent && mParent != aParent) {
|
||||
// Adopt a child -- we allow this now. the new parent
|
||||
// may be a dom node which wasn't previously accessible but now is.
|
||||
// The old parent's children now need to be invalidated, since
|
||||
// it no longer owns the child, the new parent does
|
||||
NS_ASSERTION(PR_FALSE, "Adopting child!");
|
||||
if (mParent)
|
||||
if (mParent) {
|
||||
if (mParent != aParent) {
|
||||
NS_ERROR("Adopting child!");
|
||||
mParent->InvalidateChildren();
|
||||
} else {
|
||||
NS_ERROR("Binding to the same parent!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mParent = aParent;
|
||||
|
@ -2773,6 +2766,13 @@ nsAccessible::RemoveChild(nsAccessible* aChild)
|
|||
if (aChild->mParent != this || aChild->mIndexInParent == -1)
|
||||
return PR_FALSE;
|
||||
|
||||
if (aChild->mIndexInParent >= mChildren.Length() ||
|
||||
mChildren[aChild->mIndexInParent] != aChild) {
|
||||
NS_ERROR("Child is bound to parent but parent hasn't this child at its index!");
|
||||
aChild->UnbindFromParent();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
for (PRUint32 idx = aChild->mIndexInParent + 1; idx < mChildren.Length(); idx++)
|
||||
mChildren[idx]->mIndexInParent--;
|
||||
|
||||
|
@ -2907,13 +2907,10 @@ nsAccessible::IsInCache()
|
|||
{
|
||||
nsDocAccessible *docAccessible =
|
||||
GetAccService()->GetDocAccessible(mContent->GetOwnerDoc());
|
||||
if (!docAccessible)
|
||||
return nsnull;
|
||||
if (docAccessible)
|
||||
return docAccessible->GetCachedAccessibleByUniqueID(UniqueID()) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
void *uniqueID = nsnull;
|
||||
GetUniqueID(&uniqueID);
|
||||
|
||||
return docAccessible->GetCachedAccessible(uniqueID) ? PR_TRUE : PR_FALSE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class AccGroupInfo;
|
||||
class EmbeddedObjCollector;
|
||||
|
@ -66,6 +67,8 @@ class nsIView;
|
|||
|
||||
typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsAccessible>
|
||||
nsAccessibleHashtable;
|
||||
typedef nsDataHashtable<nsPtrHashKey<const nsINode>, nsAccessible*>
|
||||
NodeToAccessibleMap;
|
||||
|
||||
// see nsAccessible::GetAttrValue
|
||||
#define NS_OK_NO_ARIA_VALUE \
|
||||
|
@ -206,6 +209,7 @@ public:
|
|||
* nsnull if none.
|
||||
*/
|
||||
virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry);
|
||||
const nsRoleMapEntry* GetRoleMapEntry() const { return mRoleMapEntry; }
|
||||
|
||||
/**
|
||||
* Cache children if necessary. Return true if the accessible is defunct.
|
||||
|
@ -290,7 +294,9 @@ public:
|
|||
mParent->mChildren.SafeElementAt(mIndexInParent - 1, nsnull).get() : nsnull;
|
||||
}
|
||||
PRUint32 GetCachedChildCount() const { return mChildren.Length(); }
|
||||
nsAccessible* GetCachedChildAt(PRUint32 aIndex) const { return mChildren.ElementAt(aIndex); }
|
||||
PRBool AreChildrenCached() const { return mChildrenFlags != eChildrenUninitialized; }
|
||||
bool IsBoundToParent() const { return mParent; }
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
|
|
|
@ -363,6 +363,12 @@ nsApplicationAccessible::Shutdown()
|
|||
mAppInfo = nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsApplicationAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible public methods
|
||||
|
||||
|
@ -470,7 +476,7 @@ nsApplicationAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAccessNode
|
||||
// nsIAccessNode and nsAccessNode
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetDOMNode(nsIDOMNode **aDOMNode)
|
||||
|
@ -524,14 +530,6 @@ nsApplicationAccessible::GetOwnerWindow(void **aOwnerWindow)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUniqueID);
|
||||
*aUniqueID = static_cast<void *>(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetComputedStyleValue(const nsAString &aPseudoElt,
|
||||
const nsAString &aPropertyName,
|
||||
|
@ -556,3 +554,4 @@ nsApplicationAccessible::GetLanguage(nsAString &aLanguage)
|
|||
aLanguage.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,20 @@ public:
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessNode
|
||||
NS_DECL_NSIACCESSNODE
|
||||
NS_SCRIPTABLE NS_IMETHOD GetDOMNode(nsIDOMNode** aDOMNode);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetDocument(nsIAccessibleDocument** aDocument);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRootDocument(nsIAccessibleDocument** aRootDocument);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
|
||||
NS_SCRIPTABLE NS_IMETHOD ScrollTo(PRUint32 aScrollType);
|
||||
NS_SCRIPTABLE NS_IMETHOD ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY);
|
||||
NS_IMETHOD GetOwnerWindow(void **aOwnerWindow);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetComputedStyleValue(const nsAString& aPseudoElt,
|
||||
const nsAString& aPropertyName,
|
||||
nsAString& aValue NS_OUTPARAM);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetComputedStyleCSSValue(const nsAString& aPseudoElt,
|
||||
const nsAString& aPropertyName,
|
||||
nsIDOMCSSPrimitiveValue** aValue NS_OUTPARAM);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetLanguage(nsAString& aLanguage);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetParent(nsIAccessible **aParent);
|
||||
|
@ -109,6 +122,7 @@ public:
|
|||
virtual PRBool IsDefunct();
|
||||
virtual PRBool Init();
|
||||
virtual void Shutdown();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
|
|
@ -285,8 +285,7 @@ nsCaretAccessible::SpellcheckSelectionChanged(nsIDOMDocument *aDoc,
|
|||
NS_ENSURE_STATE(textAcc);
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
|
||||
textAcc, nsnull);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, textAcc);
|
||||
|
||||
nsEventShell::FireEvent(event);
|
||||
return NS_OK;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -170,12 +170,9 @@ public:
|
|||
* @param aEventType [in] the nsIAccessibleEvent event type
|
||||
* @param aDOMNode [in] DOM node the accesible event should be fired for
|
||||
* @param aAllowDupes [in] rule to process an event (see EEventRule constants)
|
||||
* @param aIsAsynch [in] set to PR_TRUE if this is not being called from
|
||||
* code synchronous with a DOM event
|
||||
*/
|
||||
nsresult FireDelayedAccessibleEvent(PRUint32 aEventType, nsINode *aNode,
|
||||
AccEvent::EEventRule aAllowDupes = AccEvent::eRemoveDupes,
|
||||
PRBool aIsAsynch = PR_FALSE,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
|
@ -186,51 +183,45 @@ public:
|
|||
nsresult FireDelayedAccessibleEvent(AccEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Find the accessible object in the accessibility cache that corresponds to
|
||||
* the given node or the first ancestor of it that has an accessible object
|
||||
* associated with it. Clear that accessible object's parent's cache of
|
||||
* accessible children and remove the accessible object and any descendants
|
||||
* from the accessible cache. Fires proper events. New accessible objects will
|
||||
* be created and cached again on demand.
|
||||
*
|
||||
* @param aContent [in] the child that is changing
|
||||
* @param aEvent [in] the event from nsIAccessibleEvent that caused
|
||||
* the change.
|
||||
*/
|
||||
void InvalidateCacheSubtree(nsIContent *aContent, PRUint32 aEvent);
|
||||
|
||||
/**
|
||||
* Return the cached accessible by the given unique ID if it's in subtree of
|
||||
* Return the cached accessible by the given DOM node if it's in subtree of
|
||||
* this document accessible or the document accessible itself, otherwise null.
|
||||
*
|
||||
* @note the unique ID matches with the uniqueID attribute on nsIAccessNode
|
||||
*
|
||||
* @param aUniqueID [in] the unique ID used to cache the node.
|
||||
*
|
||||
* @return the accessible object
|
||||
*/
|
||||
nsAccessible* GetCachedAccessible(void *aUniqueID);
|
||||
nsAccessible* GetCachedAccessible(nsINode* aNode);
|
||||
|
||||
/**
|
||||
* Return the cached accessible by the given unique ID within this document.
|
||||
*
|
||||
* @note the unique ID matches with the uniqueID() of nsAccessNode
|
||||
*
|
||||
* @param aUniqueID [in] the unique ID used to cache the node.
|
||||
*/
|
||||
nsAccessible* GetCachedAccessibleByUniqueID(void* aUniqueID)
|
||||
{
|
||||
return UniqueID() == aUniqueID ?
|
||||
this : mAccessibleCache.GetWeak(aUniqueID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cached accessible by the given unique ID looking through
|
||||
* this and nested documents.
|
||||
*/
|
||||
nsAccessible* GetCachedAccessibleInSubtree(void* aUniqueID);
|
||||
nsAccessible* GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID);
|
||||
|
||||
/**
|
||||
* Cache the accessible.
|
||||
*
|
||||
* @param aUniquID [in] the unique identifier of accessible
|
||||
* @param aAccessible [in] accessible to cache
|
||||
*
|
||||
* @return true if accessible being cached, otherwise false
|
||||
*/
|
||||
PRBool CacheAccessible(void *aUniqueID, nsAccessible *aAccessible);
|
||||
PRBool CacheAccessible(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Remove the given accessible from document cache.
|
||||
* Shutdown the accessible and remove it from document cache.
|
||||
*/
|
||||
void RemoveAccessNodeFromCache(nsAccessible *aAccessible);
|
||||
void ShutdownAccessible(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Process the event when the queue of pending events is untwisted. Fire
|
||||
|
@ -238,6 +229,17 @@ public:
|
|||
*/
|
||||
void ProcessPendingEvent(AccEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Update the accessible tree.
|
||||
*/
|
||||
void UpdateTree(nsIContent* aContainerNode, nsIContent* aStartChildNode,
|
||||
nsIContent* aEndChildNode, PRBool aIsInsert);
|
||||
|
||||
/**
|
||||
* Recreate an accessible, results in hide/show events pair.
|
||||
*/
|
||||
void RecreateAccessible(nsINode* aNode);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
||||
|
@ -264,20 +266,6 @@ protected:
|
|||
mChildDocuments.RemoveElement(aChildDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate parent-child relations for any cached accessible in the DOM
|
||||
* subtree. Accessible objects aren't destroyed.
|
||||
*
|
||||
* @param aStartNode [in] the root of the subrtee to invalidate accessible
|
||||
* child/parent refs in
|
||||
*/
|
||||
void InvalidateChildrenInSubtree(nsINode *aStartNode);
|
||||
|
||||
/**
|
||||
* Traverse through DOM tree and shutdown accessible objects.
|
||||
*/
|
||||
void RefreshNodes(nsINode *aStartNode);
|
||||
|
||||
static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
|
||||
/**
|
||||
|
@ -310,27 +298,6 @@ protected:
|
|||
CharacterDataChangeInfo* aInfo,
|
||||
PRBool aIsInserted);
|
||||
|
||||
/**
|
||||
* Create a text change event for a changed node.
|
||||
*
|
||||
* @param aContainerAccessible [in] the parent accessible for the node
|
||||
* @param aChangeNode [in] the node that is being inserted or
|
||||
* removed, or shown/hidden
|
||||
* @param aAccessible [in] the accessible for that node, or nsnull
|
||||
* if none exists
|
||||
* @param aIsInserting [in] is aChangeNode being created or shown
|
||||
* (vs. removed or hidden)
|
||||
* @param aIsAsync [in] whether casual change is async
|
||||
* @param aIsFromUserInput [in] the event is known to be from user input
|
||||
*/
|
||||
already_AddRefed<AccEvent>
|
||||
CreateTextChangeEventForNode(nsAccessible *aContainerAccessible,
|
||||
nsIContent *aChangeNode,
|
||||
nsAccessible *aAccessible,
|
||||
PRBool aIsInserting,
|
||||
PRBool aIsAsynch,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
* Used to define should the event be fired on a delay.
|
||||
*/
|
||||
|
@ -339,34 +306,47 @@ protected:
|
|||
eDelayedEvent
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire show/hide events for either the current node if it has an accessible,
|
||||
* or the first-line accessible descendants of the given node.
|
||||
*
|
||||
* @param aDOMNode [in] the given node
|
||||
* @param aAvoidOnThisNode [in] call with PR_TRUE the first time to
|
||||
* prevent event firing on root node for change
|
||||
* @param aEventType [in] event type to fire an event
|
||||
* @param aDelayedOrNormal [in] whether to fire the event on a delay
|
||||
* @param aIsAsyncChange [in] whether casual change is async
|
||||
* @param aIsFromUserInput [in] the event is known to be from user input
|
||||
*/
|
||||
nsresult FireShowHideEvents(nsINode *aDOMNode, PRBool aAvoidOnThisNode,
|
||||
PRUint32 aEventType,
|
||||
EEventFiringType aDelayedOrNormal,
|
||||
PRBool aIsAsyncChange,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
* Fire a value change event for the the given accessible if it is a text
|
||||
* field (has a ROLE_ENTRY).
|
||||
*/
|
||||
void FireValueChangeForTextFields(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Helper for UpdateTree() method. Go down to DOM subtree and updates
|
||||
* accessible tree. Return one of these flags.
|
||||
*/
|
||||
enum EUpdateTreeFlags {
|
||||
eNoAccessible = 0,
|
||||
eAccessible = 1,
|
||||
eAlertAccessible = 2
|
||||
};
|
||||
|
||||
PRUint32 UpdateTreeInternal(nsAccessible* aContainer,
|
||||
nsIContent* aStartNode,
|
||||
nsIContent* aEndNode,
|
||||
PRBool aIsInsert,
|
||||
PRBool aFireEvents,
|
||||
EIsFromUserInput aFromUserInput);
|
||||
|
||||
/**
|
||||
* Remove accessibles in subtree from node to accessible map.
|
||||
*/
|
||||
void UncacheChildrenInSubtree(nsAccessible* aRoot);
|
||||
|
||||
/**
|
||||
* Shutdown any cached accessible in the subtree.
|
||||
*
|
||||
* @param aAccessible [in] the root of the subrtee to invalidate accessible
|
||||
* child/parent refs in
|
||||
*/
|
||||
void ShutdownChildrenInSubtree(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Cache of accessibles within this document accessible.
|
||||
*/
|
||||
nsAccessibleHashtable mAccessibleCache;
|
||||
NodeToAccessibleMap mNodeToAccessibleMap;
|
||||
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<nsITimer> mScrollWatchTimer;
|
||||
|
|
|
@ -68,12 +68,12 @@ nsEventShell::FireEvent(AccEvent* aEvent)
|
|||
|
||||
void
|
||||
nsEventShell::FireEvent(PRUint32 aEventType, nsAccessible *aAccessible,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput)
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
{
|
||||
NS_ENSURE_TRUE(aAccessible,);
|
||||
|
||||
nsRefPtr<AccEvent> event = new AccEvent(aEventType, aAccessible,
|
||||
aIsAsynch, aIsFromUserInput);
|
||||
aIsFromUserInput);
|
||||
|
||||
FireEvent(event);
|
||||
}
|
||||
|
@ -147,9 +147,9 @@ nsAccEventQueue::Push(AccEvent* aEvent)
|
|||
|
||||
// Associate text change with hide event if it wasn't stolen from hiding
|
||||
// siblings during coalescence.
|
||||
AccHideEvent* hideEvent = downcast_accEvent(aEvent);
|
||||
if (hideEvent && !hideEvent->mTextChangeEvent)
|
||||
CreateTextChangeEventFor(hideEvent);
|
||||
AccMutationEvent* showOrHideEvent = downcast_accEvent(aEvent);
|
||||
if (showOrHideEvent && !showOrHideEvent->mTextChangeEvent)
|
||||
CreateTextChangeEventFor(showOrHideEvent);
|
||||
|
||||
// Process events.
|
||||
PrepareFlush();
|
||||
|
@ -209,10 +209,10 @@ nsAccEventQueue::WillRefresh(mozilla::TimeStamp aTime)
|
|||
if (accEvent->mEventRule != AccEvent::eDoNotEmit) {
|
||||
mDocument->ProcessPendingEvent(accEvent);
|
||||
|
||||
AccHideEvent* hideEvent = downcast_accEvent(accEvent);
|
||||
if (hideEvent) {
|
||||
if (hideEvent->mTextChangeEvent)
|
||||
mDocument->ProcessPendingEvent(hideEvent->mTextChangeEvent);
|
||||
AccMutationEvent* showOrhideEvent = downcast_accEvent(accEvent);
|
||||
if (showOrhideEvent) {
|
||||
if (showOrhideEvent->mTextChangeEvent)
|
||||
mDocument->ProcessPendingEvent(showOrhideEvent->mTextChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,7 @@ nsAccEventQueue::CoalesceEvents()
|
|||
// accessibles can't be created at this point because of lazy frame
|
||||
// construction (bug 570275).
|
||||
|
||||
// Coalesce hide events for sibling targets.
|
||||
// Coalesce hide and show events for sibling targets.
|
||||
if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
AccHideEvent* tailHideEvent = downcast_accEvent(tailEvent);
|
||||
AccHideEvent* thisHideEvent = downcast_accEvent(thisEvent);
|
||||
|
@ -278,6 +278,20 @@ nsAccEventQueue::CoalesceEvents()
|
|||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
CoalesceTextChangeEventsFor(tailHideEvent, thisHideEvent);
|
||||
|
||||
return;
|
||||
}
|
||||
} else if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_SHOW) {
|
||||
if (thisEvent->mAccessible->GetParent() ==
|
||||
tailEvent->mAccessible->GetParent()) {
|
||||
tailEvent->mEventRule = thisEvent->mEventRule;
|
||||
|
||||
// Coalesce text change events for show events.
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit) {
|
||||
AccShowEvent* tailShowEvent = downcast_accEvent(tailEvent);
|
||||
AccShowEvent* thisShowEvent = downcast_accEvent(thisEvent);
|
||||
CoalesceTextChangeEventsFor(tailShowEvent, thisShowEvent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -286,70 +300,22 @@ nsAccEventQueue::CoalesceEvents()
|
|||
if (!thisEvent->mNode->IsInDoc())
|
||||
continue;
|
||||
|
||||
// Coalesce show and reorder events by sibling targets.
|
||||
// Coalesce earlier event for the same target.
|
||||
if (thisEvent->mNode == tailEvent->mNode) {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Coalesce events by sibling targets (this is a case for reorder
|
||||
// events).
|
||||
if (thisEvent->mNode->GetNodeParent() ==
|
||||
tailEvent->mNode->GetNodeParent()) {
|
||||
tailEvent->mEventRule = thisEvent->mEventRule;
|
||||
return;
|
||||
}
|
||||
|
||||
// Specifies if this event target can be descendant of tail node.
|
||||
PRBool thisCanBeDescendantOfTail = PR_FALSE;
|
||||
|
||||
// Coalesce depending on whether this event was coalesced or not.
|
||||
if (thisEvent->mEventRule == AccEvent::eDoNotEmit) {
|
||||
// If this event was coalesced then do not emit tail event iff tail
|
||||
// event has the same target or its target is contained by this event
|
||||
// target. Note, we don't need to check whether tail event target
|
||||
// contains this event target since this event was coalesced already.
|
||||
|
||||
// As well we don't need to apply the calculated rule for siblings of
|
||||
// tail node because tail event rule was applied to possible tail
|
||||
// node siblings while this event was coalesced.
|
||||
|
||||
if (thisEvent->mNode == tailEvent->mNode) {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// If this event wasn't coalesced already then try to coalesce it or
|
||||
// tail event. If this event is coalesced by tail event then continue
|
||||
// search through events other events that can be coalesced by tail
|
||||
// event.
|
||||
|
||||
// If tail and this events have the same target then coalesce tail
|
||||
// event because more early event we should fire early and then stop
|
||||
// processing.
|
||||
if (thisEvent->mNode == tailEvent->mNode) {
|
||||
// Coalesce reorder events by special way since reorder events can
|
||||
// be conditional events (be or not be fired in the end).
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameSource(thisEvent, tailEvent);
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
tailEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// This and tail events can be anywhere in the tree, make assumptions
|
||||
// for mutation events.
|
||||
|
||||
// More older show event target (thisNode) can't be contained by
|
||||
// recent.
|
||||
// show event target (tailNode), i.e be a descendant of tailNode.
|
||||
// XXX: target of older show event caused by DOM node appending can be
|
||||
// contained by target of recent show event caused by style change.
|
||||
// XXX: target of older show event caused by style change can be
|
||||
// contained by target of recent show event caused by style change.
|
||||
thisCanBeDescendantOfTail =
|
||||
tailEvent->mEventType != nsIAccessibleEvent::EVENT_SHOW ||
|
||||
tailEvent->mIsAsync;
|
||||
}
|
||||
// This and tail events can be anywhere in the tree, make assumptions
|
||||
// for mutation events.
|
||||
|
||||
// Coalesce tail event if tail node is descendant of this node. Stop
|
||||
// processing if tail event is coalesced since all possible descendants
|
||||
|
@ -359,54 +325,20 @@ nsAccEventQueue::CoalesceEvents()
|
|||
// this check for hide events.
|
||||
if (tailEvent->mEventType != nsIAccessibleEvent::EVENT_HIDE &&
|
||||
nsCoreUtils::IsAncestorOf(thisEvent->mNode, tailEvent->mNode)) {
|
||||
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameTree(thisEvent, tailEvent);
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
continue;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tailEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_HIDE &&
|
||||
nsCoreUtils::IsAncestorOf(thisEvent->mNode, tailEvent->mNode)) {
|
||||
NS_NOTREACHED("More older hide event target is an ancestor of recent hide event target!");
|
||||
}
|
||||
#endif
|
||||
|
||||
// If this node is a descendant of tail node then coalesce this event,
|
||||
// check other events in the queue.
|
||||
if (thisCanBeDescendantOfTail &&
|
||||
nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
|
||||
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameTree(tailEvent, thisEvent);
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
continue;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit thisEvent, also apply this result to sibling nodes of
|
||||
// thisNode.
|
||||
// check other events in the queue. Do not emit thisEvent, also apply
|
||||
// this result to sibling nodes of thisNode.
|
||||
if (nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
ApplyToSiblings(0, index, thisEvent->mEventType,
|
||||
thisEvent->mNode, AccEvent::eDoNotEmit);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!thisCanBeDescendantOfTail &&
|
||||
nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
|
||||
NS_NOTREACHED("Older event target is a descendant of recent event target!");
|
||||
}
|
||||
#endif
|
||||
|
||||
} // for (index)
|
||||
|
||||
} break; // case eCoalesceFromSameSubtree
|
||||
|
@ -462,41 +394,6 @@ nsAccEventQueue::ApplyToSiblings(PRUint32 aStart, PRUint32 aEnd,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CoalesceReorderEventsFromSameSource(AccEvent* aAccEvent1,
|
||||
AccEvent* aAccEvent2)
|
||||
{
|
||||
// Do not emit event2 if event1 is unconditional.
|
||||
AccReorderEvent* reorderEvent1 = downcast_accEvent(aAccEvent1);
|
||||
if (reorderEvent1->IsUnconditionalEvent()) {
|
||||
aAccEvent2->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit event1 if event2 is unconditional.
|
||||
AccReorderEvent* reorderEvent2 = downcast_accEvent(aAccEvent2);
|
||||
if (reorderEvent2->IsUnconditionalEvent()) {
|
||||
aAccEvent1->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit event2 if event1 is valid, otherwise do not emit event1.
|
||||
if (reorderEvent1->HasAccessibleInReasonSubtree())
|
||||
aAccEvent2->mEventRule = AccEvent::eDoNotEmit;
|
||||
else
|
||||
aAccEvent1->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CoalesceReorderEventsFromSameTree(AccEvent* aAccEvent,
|
||||
AccEvent* aDescendantAccEvent)
|
||||
{
|
||||
// Do not emit descendant event if this event is unconditional.
|
||||
AccReorderEvent* reorderEvent = downcast_accEvent(aAccEvent);
|
||||
if (reorderEvent->IsUnconditionalEvent())
|
||||
aDescendantAccEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
|
||||
AccHideEvent* aThisEvent)
|
||||
|
@ -523,7 +420,35 @@ nsAccEventQueue::CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
|
|||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CreateTextChangeEventFor(AccHideEvent* aEvent)
|
||||
nsAccEventQueue::CoalesceTextChangeEventsFor(AccShowEvent* aTailEvent,
|
||||
AccShowEvent* aThisEvent)
|
||||
{
|
||||
AccTextChangeEvent* textEvent = aThisEvent->mTextChangeEvent;
|
||||
if (!textEvent)
|
||||
return;
|
||||
|
||||
if (aTailEvent->mAccessible->GetIndexInParent() ==
|
||||
aThisEvent->mAccessible->GetIndexInParent() + 1) {
|
||||
// If tail target was inserted after this target, i.e. tail target is next
|
||||
// sibling of this target.
|
||||
aTailEvent->mAccessible->AppendTextTo(textEvent->mModifiedText,
|
||||
0, PR_UINT32_MAX);
|
||||
|
||||
} else if (aTailEvent->mAccessible->GetIndexInParent() ==
|
||||
aThisEvent->mAccessible->GetIndexInParent() -1) {
|
||||
// If tail target was inserted before this target, i.e. tail target is
|
||||
// previous sibling of this target.
|
||||
nsAutoString startText;
|
||||
aTailEvent->mAccessible->AppendTextTo(startText, 0, PR_UINT32_MAX);
|
||||
textEvent->mModifiedText = startText + textEvent->mModifiedText;
|
||||
textEvent->mStart -= startText.Length();
|
||||
}
|
||||
|
||||
aTailEvent->mTextChangeEvent.swap(aThisEvent->mTextChangeEvent);
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CreateTextChangeEventFor(AccMutationEvent* aEvent)
|
||||
{
|
||||
nsRefPtr<nsHyperTextAccessible> textAccessible = do_QueryObject(
|
||||
GetAccService()->GetContainerAccessible(aEvent->mNode,
|
||||
|
@ -551,7 +476,6 @@ nsAccEventQueue::CreateTextChangeEventFor(AccHideEvent* aEvent)
|
|||
return;
|
||||
|
||||
aEvent->mTextChangeEvent =
|
||||
new AccTextChangeEvent(textAccessible, offset, text, PR_FALSE,
|
||||
aEvent->mIsAsync,
|
||||
new AccTextChangeEvent(textAccessible, offset, text, aEvent->IsShow(),
|
||||
aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
|
||||
}
|
||||
|
|
|
@ -66,11 +66,8 @@ public:
|
|||
*
|
||||
* @param aEventType [in] the event type
|
||||
* @param aAccessible [in] the event target
|
||||
* @param aIsAsync [in, optional] specifies whether the origin change
|
||||
* this event is fired owing to is async.
|
||||
*/
|
||||
static void FireEvent(PRUint32 aEventType, nsAccessible *aAccessible,
|
||||
PRBool aIsAsynch = PR_FALSE,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
|
@ -144,12 +141,6 @@ private:
|
|||
PRUint32 aEventType, nsINode* aNode,
|
||||
AccEvent::EEventRule aEventRule);
|
||||
|
||||
/**
|
||||
* Do not emit one of two given reorder events fired for the same DOM node.
|
||||
*/
|
||||
void CoalesceReorderEventsFromSameSource(AccEvent* aAccEvent1,
|
||||
AccEvent* aAccEvent2);
|
||||
|
||||
/**
|
||||
* Do not emit one of two given reorder events fired for DOM nodes in the case
|
||||
* when one DOM node is in parent chain of second one.
|
||||
|
@ -162,14 +153,15 @@ private:
|
|||
*/
|
||||
void CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
|
||||
AccHideEvent* aThisEvent);
|
||||
void CoalesceTextChangeEventsFor(AccShowEvent* aTailEvent,
|
||||
AccShowEvent* aThisEvent);
|
||||
|
||||
/**
|
||||
* Create text change event caused by hide event. When a node is hidden or
|
||||
* removed, the text in an ancestor hyper text will lose characters. Create
|
||||
* text change event unless the node is being removed or frame is being
|
||||
* destroyed.
|
||||
* Create text change event caused by hide or show event. When a node is
|
||||
* hidden/removed or shown/appended, the text in an ancestor hyper text will
|
||||
* lose or get new characters.
|
||||
*/
|
||||
void CreateTextChangeEventFor(AccHideEvent* aEvent);
|
||||
void CreateTextChangeEventFor(AccMutationEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Indicates whether we're waiting on a refresh notification from our
|
||||
|
|
|
@ -319,7 +319,6 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
|
|||
nsINode *aNode,
|
||||
nsIDOMEvent *aFocusEvent,
|
||||
PRBool aForceEvent,
|
||||
PRBool aIsAsynch,
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
{
|
||||
// Implementors: only fire delayed/async events from this method.
|
||||
|
@ -398,7 +397,7 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
|
|||
if (mCurrentARIAMenubar) {
|
||||
nsRefPtr<AccEvent> menuStartEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENU_START,
|
||||
menuBarAccessible, PR_FALSE, aIsFromUserInput,
|
||||
menuBarAccessible, aIsFromUserInput,
|
||||
AccEvent::eAllowDupes);
|
||||
if (menuStartEvent) {
|
||||
FireDelayedAccessibleEvent(menuStartEvent);
|
||||
|
@ -411,7 +410,7 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
|
|||
else if (mCurrentARIAMenubar) {
|
||||
nsRefPtr<AccEvent> menuEndEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar,
|
||||
PR_FALSE, aIsFromUserInput, AccEvent::eAllowDupes);
|
||||
aIsFromUserInput, AccEvent::eAllowDupes);
|
||||
if (menuEndEvent) {
|
||||
FireDelayedAccessibleEvent(menuEndEvent);
|
||||
}
|
||||
|
@ -434,13 +433,11 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
|
|||
gLastFocusedNode = finalFocusNode;
|
||||
NS_IF_ADDREF(gLastFocusedNode);
|
||||
|
||||
gLastFocusedFrameType = (focusFrame && focusFrame->GetStyleVisibility()->IsVisible()) ? focusFrame->GetType() : 0;
|
||||
|
||||
// Coalesce focus events from the same document, because DOM focus event might
|
||||
// be fired for the document node and then for the focused DOM element.
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS,
|
||||
finalFocusNode, AccEvent::eCoalesceFromSameDocument,
|
||||
aIsAsynch, aIsFromUserInput);
|
||||
aIsFromUserInput);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -663,7 +660,6 @@ nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
|
|||
}
|
||||
else if (eventType.EqualsLiteral("blur")) {
|
||||
NS_IF_RELEASE(gLastFocusedNode);
|
||||
gLastFocusedFrameType = nsnull;
|
||||
gLastFocusedAccessiblesState = 0;
|
||||
}
|
||||
else if (eventType.EqualsLiteral("AlertActive")) {
|
||||
|
@ -732,16 +728,16 @@ nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
|
|||
if (fireFocus) {
|
||||
// Always asynch, always from user input.
|
||||
FireAccessibleFocusEvent(accessible, targetNode, aEvent, PR_TRUE,
|
||||
PR_TRUE, eFromUserInput);
|
||||
eFromUserInput);
|
||||
}
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always asynch, always from user input
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always from user input
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_START,
|
||||
accessible, PR_TRUE, eFromUserInput);
|
||||
accessible, eFromUserInput);
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always asynch, always from user input
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always from user input
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_END,
|
||||
accessible, PR_TRUE, eFromUserInput);
|
||||
accessible, eFromUserInput);
|
||||
FireCurrentFocusEvent();
|
||||
}
|
||||
else if (eventType.EqualsLiteral("ValueChange")) {
|
||||
|
|
|
@ -106,7 +106,6 @@ public:
|
|||
nsINode *aFocusNode,
|
||||
nsIDOMEvent *aFocusEvent,
|
||||
PRBool aForceEvent = PR_FALSE,
|
||||
PRBool aIsAsynch = PR_FALSE,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
|
|
|
@ -237,6 +237,11 @@ nsresult
|
|||
nsTextEquivUtils::AppendFromAccessible(nsAccessible *aAccessible,
|
||||
nsAString *aString)
|
||||
{
|
||||
// Ignore hidden accessible for name computation.
|
||||
nsIFrame* frame = aAccessible->GetFrame();
|
||||
if (!frame || !frame->GetStyleVisibility()->IsVisible())
|
||||
return NS_OK;
|
||||
|
||||
//XXX: is it necessary to care the accessible is not a document?
|
||||
if (aAccessible->IsContent()) {
|
||||
nsresult rv = AppendTextEquivFromTextContent(aAccessible->GetContent(),
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include "nsCoreUtils.h"
|
||||
|
||||
#include "nsILink.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLLinkAccessible
|
||||
|
@ -82,20 +82,22 @@ nsHTMLLinkAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
|||
*aState |= nsIAccessibleStates::STATE_SELECTABLE;
|
||||
}
|
||||
|
||||
nsLinkState linkState = mContent->GetLinkState();
|
||||
if (linkState == eLinkState_NotLink || linkState == eLinkState_Unknown) {
|
||||
// This is a either named anchor (a link with also a name attribute) or
|
||||
// it doesn't have any attributes. Check if 'click' event handler is
|
||||
// registered, otherwise bail out.
|
||||
PRBool isOnclick = nsCoreUtils::HasClickListener(mContent);
|
||||
if (!isOnclick)
|
||||
return NS_OK;
|
||||
nsEventStates state = mContent->IntrinsicState();
|
||||
if (state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
|
||||
NS_EVENT_STATE_UNVISITED)) {
|
||||
*aState |= nsIAccessibleStates::STATE_LINKED;
|
||||
|
||||
if (state.HasState(NS_EVENT_STATE_VISITED))
|
||||
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aState |= nsIAccessibleStates::STATE_LINKED;
|
||||
|
||||
if (linkState == eLinkState_Visited)
|
||||
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
|
||||
// This is a either named anchor (a link with also a name attribute) or
|
||||
// it doesn't have any attributes. Check if 'click' event handler is
|
||||
// registered, otherwise bail out.
|
||||
if (nsCoreUtils::HasClickListener(mContent))
|
||||
*aState |= nsIAccessibleStates::STATE_LINKED;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -186,6 +188,7 @@ nsHTMLLinkAccessible::IsLinked()
|
|||
if (IsDefunct())
|
||||
return PR_FALSE;
|
||||
|
||||
nsLinkState linkState = mContent->GetLinkState();
|
||||
return linkState != eLinkState_NotLink && linkState != eLinkState_Unknown;
|
||||
nsEventStates state = mContent->IntrinsicState();
|
||||
return state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
|
||||
NS_EVENT_STATE_UNVISITED);
|
||||
}
|
||||
|
|
|
@ -665,6 +665,9 @@ nsHTMLComboboxAccessible::
|
|||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLComboboxAccessible: nsAccessible
|
||||
|
||||
PRUint32
|
||||
nsHTMLComboboxAccessible::NativeRole()
|
||||
{
|
||||
|
@ -859,6 +862,9 @@ nsHTMLComboboxListAccessible::
|
|||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLComboboxAccessible: nsAccessNode
|
||||
|
||||
nsIFrame*
|
||||
nsHTMLComboboxListAccessible::GetFrame()
|
||||
{
|
||||
|
@ -874,6 +880,15 @@ nsHTMLComboboxListAccessible::GetFrame()
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLComboboxListAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLComboboxAccessible: nsAccessible
|
||||
|
||||
/**
|
||||
* As a nsHTMLComboboxListAccessible we can have the following states:
|
||||
* STATE_FOCUSED
|
||||
|
@ -899,14 +914,6 @@ nsHTMLComboboxListAccessible::GetStateInternal(PRUint32 *aState,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLComboboxListAccessible::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
// Since mContent is same for all tree item, use |this| pointer as the unique
|
||||
// Id.
|
||||
*aUniqueID = static_cast<void*>(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bounds for the areaFrame.
|
||||
* Walks the Frame tree and checks for proper frames.
|
||||
|
|
|
@ -226,11 +226,9 @@ public:
|
|||
nsIWeakReference* aShell);
|
||||
virtual ~nsHTMLComboboxListAccessible() {}
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
|
||||
// nsAccessNode
|
||||
virtual nsIFrame* GetFrame();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
|
|
@ -335,14 +335,8 @@ nsHTMLListBulletAccessible::
|
|||
mBulletText += ' '; // Otherwise bullets are jammed up against list text
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLListBulletAccessible::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
// Since mContent is same as for list item, use |this| pointer as the unique
|
||||
// id.
|
||||
*aUniqueID = static_cast<void*>(this);
|
||||
return NS_OK;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListBulletAccessible: nsAccessNode
|
||||
|
||||
void
|
||||
nsHTMLListBulletAccessible::Shutdown()
|
||||
|
@ -351,6 +345,15 @@ nsHTMLListBulletAccessible::Shutdown()
|
|||
nsLeafAccessible::Shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLListBulletAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListBulletAccessible: nsAccessible
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLListBulletAccessible::GetName(nsAString &aName)
|
||||
{
|
||||
|
|
|
@ -132,14 +132,12 @@ class nsHTMLListBulletAccessible : public nsLeafAccessible
|
|||
public:
|
||||
nsHTMLListBulletAccessible(nsIContent* aContent, nsIWeakReference* aShell);
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetName(nsAString& aName);
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual PRUint32 NativeRole();
|
||||
|
|
|
@ -1538,7 +1538,7 @@ nsHyperTextAccessible::SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos)
|
|||
// XXX I'm not sure this can do synchronous scrolling. If the last param is
|
||||
// set to true, this calling might flush the pending reflow. See bug 418470.
|
||||
selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION, PR_FALSE);
|
||||
nsISelectionController::SELECTION_FOCUS_REGION, 0);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -257,9 +257,7 @@ __try{
|
|||
// accessibility application can compare this to the childID we
|
||||
// return for events such as focus events, to correlate back to
|
||||
// data nodes in their internal object model.
|
||||
void *uniqueID;
|
||||
GetUniqueID(&uniqueID);
|
||||
*aUniqueID = - NS_PTR_TO_INT32(uniqueID);
|
||||
*aUniqueID = - NS_PTR_TO_INT32(UniqueID());
|
||||
|
||||
*aNumChildren = GetNode()->GetChildCount();
|
||||
|
||||
|
|
|
@ -1354,12 +1354,7 @@ STDMETHODIMP
|
|||
nsAccessibleWrap::get_uniqueID(long *uniqueID)
|
||||
{
|
||||
__try {
|
||||
void *id = nsnull;
|
||||
nsresult rv = GetUniqueID(&id);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
*uniqueID = - reinterpret_cast<long>(id);
|
||||
*uniqueID = - reinterpret_cast<long>(UniqueID());
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
@ -1575,60 +1570,53 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED ||
|
||||
eventType == nsIAccessibleEvent::EVENT_FOCUS) {
|
||||
UpdateSystemCaret();
|
||||
|
||||
} else if (eventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
// If the accessible children are changed then drop the IEnumVariant current
|
||||
// position of the accessible.
|
||||
UnattachIEnumVariant();
|
||||
}
|
||||
|
||||
|
||||
PRInt32 childID = GetChildIDFor(accessible); // get the id for the accessible
|
||||
if (!childID)
|
||||
return NS_OK; // Can't fire an event without a child ID
|
||||
|
||||
// See if we're in a scrollable area with its own window
|
||||
nsAccessible *newAccessible = nsnull;
|
||||
if (eventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
// Don't use frame from current accessible when we're hiding that
|
||||
// accessible.
|
||||
newAccessible = accessible->GetCachedParent();
|
||||
} else {
|
||||
newAccessible = accessible;
|
||||
}
|
||||
|
||||
HWND hWnd = GetHWNDFor(newAccessible);
|
||||
HWND hWnd = GetHWNDFor(accessible);
|
||||
NS_ENSURE_TRUE(hWnd, NS_ERROR_FAILURE);
|
||||
|
||||
// Gecko uses two windows for every scrollable area. One window contains
|
||||
// scrollbars and the child window contains only the client area.
|
||||
// Details of the 2 window system:
|
||||
// * Scrollbar window: caret drawing window & return value for WindowFromAccessibleObject()
|
||||
// * Client area window: text drawing window & MSAA event window
|
||||
nsAutoString tag;
|
||||
nsCAutoString id;
|
||||
nsIContent* cnt = accessible->GetContent();
|
||||
if (cnt) {
|
||||
cnt->Tag()->ToString(tag);
|
||||
nsIAtom* aid = cnt->GetID();
|
||||
if (aid)
|
||||
aid->ToUTF8String(id);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_A11Y
|
||||
printf("\n\nMSAA event: event: %d, target: %s@id='%s', childid: %d, hwnd: %d\n\n",
|
||||
eventType, NS_ConvertUTF16toUTF8(tag).get(), id.get(),
|
||||
childID, hWnd);
|
||||
#endif
|
||||
|
||||
// Fire MSAA event for client area window.
|
||||
NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID);
|
||||
|
||||
// If the accessible children are changed then drop the IEnumVariant current
|
||||
// position of the accessible.
|
||||
if (eventType == nsIAccessibleEvent::EVENT_REORDER)
|
||||
UnattachIEnumVariant();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//------- Helper methods ---------
|
||||
|
||||
PRInt32 nsAccessibleWrap::GetChildIDFor(nsIAccessible* aAccessible)
|
||||
PRInt32 nsAccessibleWrap::GetChildIDFor(nsAccessible* aAccessible)
|
||||
{
|
||||
// A child ID of the window is required, when we use NotifyWinEvent,
|
||||
// so that the 3rd party application can call back and get the IAccessible
|
||||
// the event occurred on.
|
||||
|
||||
void *uniqueID = nsnull;
|
||||
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
|
||||
if (!accessNode) {
|
||||
return 0;
|
||||
}
|
||||
accessNode->GetUniqueID(&uniqueID);
|
||||
|
||||
// Yes, this means we're only compatibible with 32 bit
|
||||
// MSAA is only available for 32 bit windows, so it's okay
|
||||
return - NS_PTR_TO_INT32(uniqueID);
|
||||
// XXX: bug 606080
|
||||
return aAccessible ? - NS_PTR_TO_INT32(aAccessible->UniqueID()) : 0;
|
||||
}
|
||||
|
||||
HWND
|
||||
|
|
|
@ -310,7 +310,7 @@ public: // construction, destruction
|
|||
virtual nsresult HandleAccEvent(AccEvent* aEvent);
|
||||
|
||||
// Helper methods
|
||||
static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
|
||||
static PRInt32 GetChildIDFor(nsAccessible* aAccessible);
|
||||
static HWND GetHWNDFor(nsAccessible *aAccessible);
|
||||
static HRESULT ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
|
||||
BSTR *aIA2Attributes);
|
||||
|
|
|
@ -109,7 +109,7 @@ nsDocAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
|
|||
if (aVarChild.vt == VT_I4 && aVarChild.lVal < 0) {
|
||||
// Convert child ID to unique ID.
|
||||
void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
|
||||
return GetCachedAccessibleInSubtree(uniqueID);
|
||||
return GetCachedAccessibleByUniqueIDInSubtree(uniqueID);
|
||||
}
|
||||
|
||||
return nsAccessibleWrap::GetXPAccessibleFor(aVarChild);
|
||||
|
|
|
@ -509,15 +509,13 @@ nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
|
|||
|
||||
if (accessible) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_HIDE, accessible, PR_FALSE);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_HIDE, accessible);
|
||||
nsEventShell::FireEvent(event);
|
||||
|
||||
accessible->Shutdown();
|
||||
|
||||
// Remove accessible from document cache and tree cache.
|
||||
// Shutdown and remove accessible from document cache and tree cache.
|
||||
nsDocAccessible *docAccessible = GetDocAccessible();
|
||||
if (docAccessible)
|
||||
docAccessible->RemoveAccessNodeFromCache(accessible);
|
||||
docAccessible->ShutdownAccessible(accessible);
|
||||
|
||||
mAccessibleCache.Remove(key);
|
||||
}
|
||||
|
@ -539,12 +537,10 @@ nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
|
|||
nsAccessible *accessible = mAccessibleCache.GetWeak(key);
|
||||
|
||||
if (accessible) {
|
||||
accessible->Shutdown();
|
||||
|
||||
// Remove accessible from document cache and tree cache.
|
||||
// Shutdown and remove accessible from document cache and tree cache.
|
||||
nsDocAccessible *docAccessible = GetDocAccessible();
|
||||
if (docAccessible)
|
||||
docAccessible->RemoveAccessNodeFromCache(accessible);
|
||||
docAccessible->ShutdownAccessible(accessible);
|
||||
|
||||
mAccessibleCache.Remove(key);
|
||||
}
|
||||
|
@ -610,7 +606,7 @@ nsXULTreeAccessible::TreeViewChanged()
|
|||
// AT because it should be expensive to fire destroy events for each tree item
|
||||
// in cache.
|
||||
nsRefPtr<AccEvent> eventDestroy =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_HIDE, this, PR_FALSE);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_HIDE, this);
|
||||
if (!eventDestroy)
|
||||
return;
|
||||
|
||||
|
@ -621,7 +617,7 @@ nsXULTreeAccessible::TreeViewChanged()
|
|||
mTree->GetView(getter_AddRefs(mTreeView));
|
||||
|
||||
nsRefPtr<AccEvent> eventCreate =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_SHOW, this, PR_FALSE);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_SHOW, this);
|
||||
if (!eventCreate)
|
||||
return;
|
||||
|
||||
|
@ -662,18 +658,6 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeItemAccessibleBase,
|
|||
nsAccessible,
|
||||
nsXULTreeItemAccessibleBase)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessibleBase: nsIAccessNode implementation
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeItemAccessibleBase::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
// Since mContent is same for all tree items and tree itself, use |this|
|
||||
// pointer as the unique ID.
|
||||
*aUniqueID = static_cast<void*>(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessibleBase: nsIAccessible implementation
|
||||
|
||||
|
@ -888,6 +872,12 @@ nsXULTreeItemAccessibleBase::Shutdown()
|
|||
nsAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
nsXULTreeItemAccessibleBase::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessibleBase: nsAccessible public methods
|
||||
|
||||
|
|
|
@ -181,9 +181,6 @@ public:
|
|||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
|
||||
|
||||
|
@ -207,6 +204,7 @@ public:
|
|||
// nsAccessNode
|
||||
virtual PRBool IsDefunct();
|
||||
virtual void Shutdown();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
|
|
@ -804,18 +804,6 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsXULTreeGridCellAccessible,
|
|||
nsIAccessibleTableCell,
|
||||
nsXULTreeGridCellAccessible)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridCellAccessible: nsIAccessNode implementation
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeGridCellAccessible::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUniqueID);
|
||||
*aUniqueID = static_cast<void*>(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridCellAccessible: nsIAccessible implementation
|
||||
|
||||
|
@ -1124,6 +1112,12 @@ nsXULTreeGridCellAccessible::Init()
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
nsXULTreeGridCellAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridCellAccessible: nsAccessible public implementation
|
||||
|
||||
|
|
|
@ -141,9 +141,6 @@ public:
|
|||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
|
||||
|
||||
|
@ -161,6 +158,7 @@ public:
|
|||
// nsAccessNode
|
||||
virtual PRBool IsDefunct();
|
||||
virtual PRBool Init();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
|
||||
|
|
|
@ -51,6 +51,7 @@ _TEST_FILES =\
|
|||
test_general.html \
|
||||
test_general.xul \
|
||||
test_inputs.html \
|
||||
test_link.html \
|
||||
test_tree.xul \
|
||||
test_treegrid.xul \
|
||||
$(NULL)
|
||||
|
|
|
@ -19,18 +19,55 @@
|
|||
src="../actions.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function getAnchorTargetDocumentAcc()
|
||||
{
|
||||
var thisTabDocAcc = getTabDocAccessible();
|
||||
var thisDocTabPanelAcc = thisTabDocAcc.parent.parent;
|
||||
var tabPanelsAcc = thisDocTabPanelAcc.parent;
|
||||
var newDocTabPanelAcc = tabPanelsAcc.lastChild.firstChild;
|
||||
return newDocTabPanelAcc.firstChild;
|
||||
}
|
||||
|
||||
function linkChecker(aID)
|
||||
{
|
||||
this.type = EVENT_DOCUMENT_LOAD_COMPLETE;
|
||||
this.__defineGetter__("target", getAnchorTargetDocumentAcc);
|
||||
|
||||
this.check = function linkChecker_check()
|
||||
{
|
||||
var anchorTargetWindow =
|
||||
getAccessible(getAnchorTargetDocumentAcc(), [nsIAccessibleDocument]).
|
||||
window;
|
||||
anchorTargetWindow.close();
|
||||
}
|
||||
|
||||
this.getID = function linkChecker_getID()
|
||||
{
|
||||
return "link '" + aID + "' states check ";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var actionsArray = [
|
||||
{
|
||||
ID: "link1",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS
|
||||
events: CLICK_EVENTS,
|
||||
eventSeq: [
|
||||
new linkChecker("link1")
|
||||
]
|
||||
},
|
||||
{
|
||||
ID: "img1",
|
||||
actionName: "click",
|
||||
events: CLICK_EVENTS
|
||||
targetID: "link1",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS,
|
||||
eventSeq: [
|
||||
new linkChecker("link1")
|
||||
]
|
||||
},
|
||||
{
|
||||
ID: "link2",
|
||||
|
@ -39,7 +76,8 @@
|
|||
},
|
||||
{
|
||||
ID: "img2",
|
||||
actionName: "click",
|
||||
targetID: "link2",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
|
@ -49,7 +87,8 @@
|
|||
},
|
||||
{
|
||||
ID: "img3",
|
||||
actionName: "click",
|
||||
targetID: "link3",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
|
@ -59,7 +98,8 @@
|
|||
},
|
||||
{
|
||||
ID: "img4",
|
||||
actionName: "click",
|
||||
targetID: "link4",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS
|
||||
}
|
||||
];
|
||||
|
@ -83,7 +123,7 @@
|
|||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<a href="http://mozilla.org" id="link1">
|
||||
<a href="about:mozilla" id="link1" target="_blank">
|
||||
<img src="../moz.png" id="img1">
|
||||
</a>
|
||||
<a id="link2" onmousedown="">
|
||||
|
@ -95,5 +135,7 @@
|
|||
<a id="link4" onmouseup="">
|
||||
<img src="../moz.png" id="img4">
|
||||
</a>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -50,42 +50,6 @@ const nsIDOMXULElement = Components.interfaces.nsIDOMXULElement;
|
|||
|
||||
const nsIPropertyElement = Components.interfaces.nsIPropertyElement;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// States
|
||||
|
||||
const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
|
||||
const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
|
||||
const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE;
|
||||
const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
|
||||
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
|
||||
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
|
||||
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
|
||||
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
|
||||
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
|
||||
const STATE_INVALID = nsIAccessibleStates.STATE_INVALID;
|
||||
const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
|
||||
const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
|
||||
const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
|
||||
const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
|
||||
const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
|
||||
const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
|
||||
const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
|
||||
const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
|
||||
const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
|
||||
const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
|
||||
const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
|
||||
|
||||
const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
|
||||
const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
|
||||
const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
|
||||
const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
|
||||
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
|
||||
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
|
||||
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
|
||||
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
|
||||
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
|
||||
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// OS detect
|
||||
const MAC = (navigator.platform.indexOf("Mac") != -1)? true : false;
|
||||
|
@ -96,6 +60,8 @@ const WIN = (navigator.platform.indexOf("Win") != -1)? true : false;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Accessible general
|
||||
|
||||
const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
|
||||
|
||||
const kEmbedChar = String.fromCharCode(0xfffc);
|
||||
|
||||
/**
|
||||
|
@ -264,6 +230,19 @@ function isAccessible(aAccOrElmOrID, aInterfaces)
|
|||
true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an accessible that contains the DOM node for the given identifier.
|
||||
*/
|
||||
function getContainerAccessible(aAccOrElmOrID)
|
||||
{
|
||||
var node = getNode(aAccOrElmOrID);
|
||||
if (!node)
|
||||
return null;
|
||||
|
||||
while ((node = node.parentNode) && !isAccessible(node));
|
||||
return node ? getAccessible(node) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return root accessible for the given identifier.
|
||||
*/
|
||||
|
@ -274,6 +253,25 @@ function getRootAccessible(aAccOrElmOrID)
|
|||
return acc ? acc.rootDocument.QueryInterface(nsIAccessible) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return tab document accessible the given accessible is contained by.
|
||||
*/
|
||||
function getTabDocAccessible(aAccOrElmOrID)
|
||||
{
|
||||
var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document,
|
||||
[nsIAccessNode]);
|
||||
|
||||
var docAcc = acc.document.QueryInterface(nsIAccessible);
|
||||
var containerDocAcc = docAcc.parent.QueryInterface(nsIAccessNode).document;
|
||||
|
||||
// Test is running is stand-alone mode.
|
||||
if (acc.rootDocument == containerDocAcc)
|
||||
return docAcc;
|
||||
|
||||
// In the case of running all tests together.
|
||||
return containerDocAcc.QueryInterface(nsIAccessible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return application accessible.
|
||||
*/
|
||||
|
@ -542,6 +540,15 @@ function prettyName(aIdentifier)
|
|||
} catch (e) {
|
||||
msg += "defunct";
|
||||
}
|
||||
|
||||
if (acc) {
|
||||
var exp = /native\s*@\s*(0x[a-f0-9]+)/g;
|
||||
var match = exp.exec(acc.valueOf());
|
||||
if (match)
|
||||
msg += ", address: " + match[1];
|
||||
else
|
||||
msg += ", address: " + acc.valueOf();
|
||||
}
|
||||
msg += "]";
|
||||
|
||||
return msg;
|
||||
|
@ -571,14 +578,16 @@ addLoadEvent(initialize);
|
|||
function getNodePrettyName(aNode)
|
||||
{
|
||||
try {
|
||||
if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
|
||||
return " '" + aNode.getAttribute("id") + "' ";
|
||||
|
||||
if (aNode.nodeType == nsIDOMNode.DOCUMENT_NODE)
|
||||
return " 'document node' ";
|
||||
|
||||
return " '" + aNode.localName + " node' ";
|
||||
var name = " '" + aNode.localName;
|
||||
if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
|
||||
name += "@id='" + aNode.getAttribute("id") + "'";
|
||||
|
||||
name += " node' "
|
||||
return name;
|
||||
} catch (e) {
|
||||
return "no node info";
|
||||
return "' no node info '";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ const EVENT_DOCUMENT_LOAD_STOPPED = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_STOPP
|
|||
const EVENT_HIDE = nsIAccessibleEvent.EVENT_HIDE;
|
||||
const EVENT_FOCUS = nsIAccessibleEvent.EVENT_FOCUS;
|
||||
const EVENT_NAME_CHANGE = nsIAccessibleEvent.EVENT_NAME_CHANGE;
|
||||
const EVENT_MENUPOPUP_START = nsIAccessibleEvent.EVENT_MENUPOPUP_START;
|
||||
const EVENT_MENUPOPUP_END = nsIAccessibleEvent.EVENT_MENUPOPUP_END;
|
||||
const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
|
||||
const EVENT_SCROLLING_START = nsIAccessibleEvent.EVENT_SCROLLING_START;
|
||||
const EVENT_SELECTION_ADD = nsIAccessibleEvent.EVENT_SELECTION_ADD;
|
||||
|
@ -554,7 +556,9 @@ function eventQueue(aEventType)
|
|||
styledNode.textContent = "matched";
|
||||
|
||||
// Dump matched events into console.
|
||||
dump("\n*****\nEQ matched: " + eventTypeToString(currType) + "\n*****\n");
|
||||
if (gA11yEventDumpToConsole)
|
||||
dump("\n*****\nEQ matched: " + eventTypeToString(currType) + "\n*****\n");
|
||||
|
||||
} else {
|
||||
styledNode.textContent = "expected";
|
||||
}
|
||||
|
@ -932,6 +936,9 @@ var gA11yEventObserver =
|
|||
info += ". Listeners count: " + listenersArray.length;
|
||||
|
||||
eventFromDumpArea = false;
|
||||
|
||||
if (gA11yEventDumpToConsole)
|
||||
dump("\n" + info + "\n");
|
||||
dumpInfoToDOM(info);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ _TEST_FILES =\
|
|||
test_aria_statechange.html \
|
||||
test_attrs.html \
|
||||
test_caretmove.html \
|
||||
$(warning test_coalescence.html temporarily disabled) \
|
||||
test_coalescence.html \
|
||||
test_contextmenu.html \
|
||||
test_docload.html \
|
||||
test_docload.xul \
|
||||
test_dragndrop.html \
|
||||
|
|
|
@ -364,6 +364,11 @@
|
|||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=513213"
|
||||
title="coalesce events when new event is appended to the queue">
|
||||
Mozilla Bug 513213
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Context menu tests</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../states.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
function showContextMenu(aID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_MENUPOPUP_START, getContextMenuNode()),
|
||||
];
|
||||
|
||||
this.invoke = function showContextMenu_invoke()
|
||||
{
|
||||
synthesizeMouse(this.DOMNode, 4, 4, { type: "contextmenu", button: 2 });
|
||||
}
|
||||
|
||||
this.getID = function showContextMenu_getID()
|
||||
{
|
||||
return "show context menu";
|
||||
}
|
||||
}
|
||||
|
||||
function selectMenuItem()
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_FOCUS, getFocusedMenuItem)
|
||||
];
|
||||
|
||||
this.invoke = function selectMenuItem_invoke()
|
||||
{
|
||||
synthesizeKey("VK_DOWN", { });
|
||||
}
|
||||
|
||||
this.getID = function selectMenuItem_getID()
|
||||
{
|
||||
return "select first menuitem";
|
||||
}
|
||||
}
|
||||
|
||||
function closeContextMenu(aID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_MENUPOPUP_END,
|
||||
getAccessible(getContextMenuNode()))
|
||||
];
|
||||
|
||||
this.invoke = function closeContextMenu_invoke()
|
||||
{
|
||||
synthesizeKey("VK_ESCAPE", { });
|
||||
}
|
||||
|
||||
this.getID = function closeContextMenu_getID()
|
||||
{
|
||||
return "close context menu";
|
||||
}
|
||||
}
|
||||
|
||||
function getContextMenuNode()
|
||||
{
|
||||
return getRootAccessible().DOMDocument.
|
||||
getElementById("contentAreaContextMenu");
|
||||
}
|
||||
|
||||
function getFocusedMenuItem()
|
||||
{
|
||||
var menu = getAccessible(getAccessible(getContextMenuNode()));
|
||||
for (var idx = 0; idx < menu.childCount; idx++) {
|
||||
var item = menu.getChildAt(idx);
|
||||
|
||||
if (hasState(item, STATE_FOCUSED))
|
||||
return getAccessible(item, [nsIAccessNode]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Do tests
|
||||
|
||||
var gQueue = null;
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
function doTests()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new showContextMenu("input"));
|
||||
gQueue.push(new selectMenuItem());
|
||||
gQueue.push(new closeContextMenu());
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTests);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=580535"
|
||||
title="Broken accessibility in context menus">
|
||||
Mozilla Bug 580535
|
||||
</a><br>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<input id="input">
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -58,11 +58,34 @@
|
|||
}
|
||||
}
|
||||
|
||||
function showNFocusAlertDialog()
|
||||
{
|
||||
this.ID = "alertdialog";
|
||||
this.DOMNode = getNode(this.ID);
|
||||
|
||||
this.invoke = function showNFocusAlertDialog_invoke()
|
||||
{
|
||||
document.getElementById(this.ID).style.display = 'block';
|
||||
document.getElementById(this.ID).focus();
|
||||
todo(false, "Enable show event handling when bug 422744 is fixed.");
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_FOCUS, this.DOMNode),
|
||||
// new invokerChecker(EVENT_SHOW, this.DOMNode)
|
||||
];
|
||||
|
||||
this.getID = function showNFocusAlertDialog_getID()
|
||||
{
|
||||
return "Show and focus alert dialog " + prettyName(this.ID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do tests.
|
||||
*/
|
||||
|
||||
// gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
|
@ -82,6 +105,8 @@
|
|||
|
||||
gQueue.push(new focusElmWhileSubdocIsFocused("button"));
|
||||
|
||||
gQueue.push(new showNFocusAlertDialog());
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -102,6 +127,11 @@
|
|||
title=" Inconsistent focus events when returning to a document frame">
|
||||
Mozilla Bug 352220
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=580464"
|
||||
title="Accessible focus incorrect after JS focus() but correct after switching apps or using menu bar">
|
||||
Mozilla Bug 580464
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -112,6 +142,13 @@
|
|||
<button id="button">button</button>
|
||||
<iframe id="editabledoc" src="focus.html"></iframe>
|
||||
|
||||
<div id="alertdialog" style="display: none" tabindex="-1" role="alertdialog" aria-labelledby="title2" aria-describedby="desc2">
|
||||
<div id="title2">Blah blah</div>
|
||||
<div id="desc2">Woof woof woof.</div>
|
||||
<button>Close</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -230,16 +230,17 @@
|
|||
|
||||
this.invoke = function cloneAndReplaceInDOM_invoke()
|
||||
{
|
||||
var newElm = this.DOMNode.cloneNode(true);
|
||||
newElm.removeAttribute('id');
|
||||
this.eventSeq[1][1] = newElm;
|
||||
this.DOMNode.parentNode.replaceChild(newElm, this.DOMNode);
|
||||
this.DOMNode.parentNode.replaceChild(this.newElm, this.DOMNode);
|
||||
}
|
||||
|
||||
this.getID = function cloneAndReplaceInDOM_getID()
|
||||
{
|
||||
return aNodeOrID + " clone and replace in DOM.";
|
||||
}
|
||||
|
||||
this.newElm = this.DOMNode.cloneNode(true);
|
||||
this.newElm.removeAttribute('id');
|
||||
this.setTarget(kShowEvent, this.newElm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -279,7 +280,7 @@
|
|||
* Do tests.
|
||||
*/
|
||||
var gQueue = null;
|
||||
// gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
function doTests()
|
||||
{
|
||||
|
@ -292,13 +293,6 @@
|
|||
gQueue.push(new changeStyle(id, "display", "none", kHideEvents));
|
||||
gQueue.push(new changeStyle(id, "display", "inline", kShowEvents));
|
||||
|
||||
// Show/hide events by changing of visibility style of accessible DOM node
|
||||
// from 'visible' to 'hidden', 'hidden' to 'visible'.
|
||||
var id = "link2";
|
||||
getAccessible(id);
|
||||
gQueue.push(new changeStyle(id, "visibility", "hidden", kHideEvents));
|
||||
gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
|
||||
|
||||
// Show/hide events by changing of display style of accessible DOM node
|
||||
// from 'inline' to 'block', 'block' to 'inline'.
|
||||
var id = "link3";
|
||||
|
@ -306,12 +300,6 @@
|
|||
gQueue.push(new changeStyle(id, "display", "block", kHideAndShowEvents));
|
||||
gQueue.push(new changeStyle(id, "display", "inline", kHideAndShowEvents));
|
||||
|
||||
// Show/hide events by changing of visibility style of accessible DOM node
|
||||
// from 'collapse' to 'visible', 'visible' to 'collapse'.
|
||||
var id = "link4";
|
||||
gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
|
||||
gQueue.push(new changeStyle(id, "visibility", "collapse", kHideEvents));
|
||||
|
||||
// Show/hide events by adding new accessible DOM node and removing old one.
|
||||
var id = "link5";
|
||||
gQueue.push(new cloneAndAppendToDOM(id));
|
||||
|
@ -347,16 +335,13 @@
|
|||
|
||||
// Show/hide events by creating new accessible DOM node and replacing
|
||||
// old one.
|
||||
// XXX: bug 472810
|
||||
// gQueue.push(new cloneAndReplaceInDOM("link6"));
|
||||
getAccessible("link6"); // ensure accessible is created
|
||||
gQueue.push(new cloneAndReplaceInDOM("link6"));
|
||||
|
||||
// Show/hide events by changing class name on the parent node.
|
||||
gQueue.push(new changeClass("container2", "link7", "", kShowEvents));
|
||||
gQueue.push(new changeClass("container2", "link7", "displayNone",
|
||||
kHideEvents));
|
||||
gQueue.push(new changeClass("container3", "link8", "", kShowEvents));
|
||||
gQueue.push(new changeClass("container3", "link8", "visibilityHidden",
|
||||
kHideEvents));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
@ -372,11 +357,16 @@
|
|||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=469985"
|
||||
title=" turn the test from bug 354745 into mochitest">
|
||||
Mozilla Bug 469985
|
||||
</a>
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=472662"
|
||||
title="no reorder event when html:link display property is changed from 'none' to 'inline'">
|
||||
Mozilla Bug 472662
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
|
|
|
@ -84,22 +84,36 @@
|
|||
/**
|
||||
* Insert inaccessible child node containing accessibles.
|
||||
*/
|
||||
function insertChildSpan(aID)
|
||||
function insertChildSpan(aID, aInsertAllTogether)
|
||||
{
|
||||
this.__proto__ = new textInsertInvoker(aID, 0, 5, "33322");
|
||||
|
||||
this.invoke = function insertChildSpan_invoke()
|
||||
{
|
||||
// <span><span>333</span><span>22</span></span>
|
||||
var topSpan = document.createElement("span");
|
||||
var fSpan = document.createElement("span");
|
||||
fSpan.textContent = "333";
|
||||
topSpan.appendChild(fSpan);
|
||||
var sSpan = document.createElement("span");
|
||||
sSpan.textContent = "22";
|
||||
topSpan.appendChild(sSpan);
|
||||
if (aInsertAllTogether) {
|
||||
var topSpan = document.createElement("span");
|
||||
var fSpan = document.createElement("span");
|
||||
fSpan.textContent = "333";
|
||||
topSpan.appendChild(fSpan);
|
||||
var sSpan = document.createElement("span");
|
||||
sSpan.textContent = "22";
|
||||
topSpan.appendChild(sSpan);
|
||||
|
||||
this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
|
||||
this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
|
||||
|
||||
} else {
|
||||
var topSpan = document.createElement("span");
|
||||
this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
|
||||
|
||||
var fSpan = document.createElement("span");
|
||||
fSpan.textContent = "333";
|
||||
topSpan.appendChild(fSpan);
|
||||
|
||||
var sSpan = document.createElement("span");
|
||||
sSpan.textContent = "22";
|
||||
topSpan.appendChild(sSpan);
|
||||
}
|
||||
}
|
||||
|
||||
this.getID = function insertChildSpan_getID()
|
||||
|
@ -271,7 +285,8 @@
|
|||
// Text remove event on inaccessible child HTML span removal containing
|
||||
// accessible text nodes.
|
||||
gQueue.push(new removeChildSpan("p"));
|
||||
gQueue.push(new insertChildSpan("p"));
|
||||
gQueue.push(new insertChildSpan("p"), true);
|
||||
gQueue.push(new insertChildSpan("p"), false);
|
||||
|
||||
// Remove embedded character.
|
||||
gQueue.push(new removeChildDiv("div"));
|
||||
|
@ -323,6 +338,11 @@
|
|||
title="Cache text offsets within hypertext accessible">
|
||||
Mozilla Bug 575052
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275"
|
||||
title="Rework accessible tree update code">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
|
|
@ -15,6 +15,7 @@ const ROLE_COMBOBOX = nsIAccessibleRole.ROLE_COMBOBOX;
|
|||
const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
|
||||
const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
|
||||
const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
|
||||
const ROLE_DIALOG = nsIAccessibleRole.ROLE_DIALOG;
|
||||
const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
|
||||
const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
|
||||
const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
|
||||
|
@ -100,3 +101,23 @@ function getRole(aAccOrElmOrID)
|
|||
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analogy of SimpleTest.is function used to check the role.
|
||||
*/
|
||||
function isRole(aIdentifier, aRole, aMsg)
|
||||
{
|
||||
var role = getRole(aIdentifier);
|
||||
if (role == - 1)
|
||||
return;
|
||||
|
||||
if (role == aRole) {
|
||||
ok(true, aMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
var got = roleToString(role);
|
||||
var expected = roleToString(aRole);
|
||||
|
||||
ok(false, aMsg + "got '" + got + "', expected '" + expected + "'");
|
||||
}
|
||||
|
|
|
@ -6,6 +6,46 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// State constants
|
||||
|
||||
// const STATE_BUSY is defined in common.js
|
||||
const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
|
||||
const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE;
|
||||
const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
|
||||
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
|
||||
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
|
||||
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
|
||||
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
|
||||
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
|
||||
const STATE_INVALID = nsIAccessibleStates.STATE_INVALID;
|
||||
const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
|
||||
const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
|
||||
const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
|
||||
const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
|
||||
const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
|
||||
const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
|
||||
const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
|
||||
const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
|
||||
const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
|
||||
const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
|
||||
const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
|
||||
|
||||
const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
|
||||
const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
|
||||
const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
|
||||
const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
|
||||
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
|
||||
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
|
||||
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
|
||||
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
|
||||
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
|
||||
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Test functions
|
||||
|
||||
/**
|
||||
* Tests the states and extra states of the given accessible.
|
||||
* Also tests for unwanted states and extra states.
|
||||
|
@ -149,6 +189,16 @@ function getStates(aAccOrElmOrID)
|
|||
return [state.value, extraState.value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the accessible has given states.
|
||||
*/
|
||||
function hasState(aAccOrElmOrID, aState, aExtraState)
|
||||
{
|
||||
var [state, exstate] = getStates(aAccOrElmOrID);
|
||||
return (aState ? state & aState : true) &&
|
||||
(aExtraState ? exstate & aExtraState : true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Private implementation details
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
// strong roles
|
||||
testStates("link1", STATE_LINKED);
|
||||
testStates("link2", STATE_LINKED);
|
||||
testStates("link3", STATE_LINKED);
|
||||
testStates("link4", STATE_LINKED);
|
||||
testStates("link5", 0, 0, STATE_LINKED);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -52,6 +52,7 @@
|
|||
<a id="link2" onclick="">link</a>
|
||||
<a id="link3" onmousedown="">link</a>
|
||||
<a id="link4" onmouseup="">link</a>
|
||||
<a id="link5">not link</a>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -68,7 +68,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452161
|
|||
var frame = document.getElementById("frame");
|
||||
frame.contentDocument.designMode = "on";
|
||||
testEditable(frame.contentDocument);
|
||||
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
src="common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="states.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="nsIAccessible_selects.js"></script>
|
||||
|
||||
|
|
|
@ -30,26 +30,22 @@
|
|||
|
||||
function focusAnchor(aID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
this.link = getAccessible(this.DOMNode);
|
||||
this.linkChild = this.link.firstChild;
|
||||
this.linkChildNode = getAccessible(this.linkChild, [nsIAccessNode]).DOMNode;
|
||||
this.linkNode = getNode(aID);
|
||||
this.link = getAccessible(this.linkNode);
|
||||
|
||||
this.eventSeq = [
|
||||
// new invokerChecker(EVENT_HIDE, this.linkChild),
|
||||
// new invokerChecker(EVENT_SHOW, getAccessible, this.linkChildNode),
|
||||
new invokerChecker(EVENT_FOCUS, this.link)
|
||||
];
|
||||
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.link),
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.DOMNode)
|
||||
new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
|
||||
];
|
||||
|
||||
this.invoke = function focusAnchor_invoke()
|
||||
{
|
||||
todo(false, "enable event hide/show events");
|
||||
getNode(aID).focus();
|
||||
this.linkNode.focus();
|
||||
}
|
||||
|
||||
this.check = function focusAnchor_check(aEvent)
|
||||
{
|
||||
isnot(this.link, aEvent.accessible,
|
||||
"Focus should be fired against new link accessible!");
|
||||
}
|
||||
|
||||
this.getID = function focusAnchor_getID()
|
||||
|
@ -58,34 +54,27 @@
|
|||
}
|
||||
}
|
||||
|
||||
function tabAnchor(aID, aPrevID)
|
||||
function tabAnchor(aID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
this.link = getAccessible(this.DOMNode);
|
||||
this.linkChild = this.link.firstChild;
|
||||
this.linkChildNode = getAccessible(this.linkChild, [nsIAccessNode]).DOMNode;
|
||||
this.prevLink = getAccessible(aPrevID);
|
||||
this.prevLinkNode = getAccessible(this.prevLink, [nsIAccessNode]).DOMNode;
|
||||
this.linkNode = getNode(aID);
|
||||
this.link = getAccessible(this.linkNode);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.prevLink),
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.prevLinkNode),
|
||||
new invokerChecker(EVENT_HIDE, this.linkChild),
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.linkChildNode),
|
||||
new invokerChecker(EVENT_FOCUS, this.link)
|
||||
new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
|
||||
];
|
||||
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.link),
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.DOMNode)
|
||||
];
|
||||
|
||||
this.invoke = function focusAnchor_invoke()
|
||||
this.invoke = function tabAnchor_invoke()
|
||||
{
|
||||
synthesizeKey("VK_TAB", { shiftKey: false });
|
||||
}
|
||||
|
||||
this.getID = function focusAnchor_getID()
|
||||
this.check = function tabAnchor_check(aEvent)
|
||||
{
|
||||
isnot(this.link, aEvent.accessible,
|
||||
"Focus should be fired against new link accessible!");
|
||||
}
|
||||
|
||||
this.getID = function tabAnchor_getID()
|
||||
{
|
||||
return "focus a:focus{overflow:scroll} #2";
|
||||
}
|
||||
|
@ -95,20 +84,20 @@
|
|||
// Do tests
|
||||
|
||||
var gQueue = null;
|
||||
// gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
function doTests()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
// CSS 'overflow: scroll' property setting and unsetting causes accessible
|
||||
// recreation (and fire show/hide events) if the accessible is not
|
||||
// focused. If it's focused its children are recreated. For example,
|
||||
// focusing the HTML:a with ':focus {overflow: scroll; }' CSS style
|
||||
// shouldn't cause of HTML:a accessible recreation. The same time blur
|
||||
// makes its accessible to be recreated.
|
||||
gQueue.push(new focusAnchor("a"))
|
||||
gQueue.push(new tabAnchor("a2", "a"));
|
||||
// recreation (and fire show/hide events). For example, the focus and
|
||||
// blur of HTML:a with ':focus {overflow: scroll; }' CSS style causes its
|
||||
// accessible recreation. The focus event should be fired on new
|
||||
// accessible.
|
||||
gQueue.push(new focusAnchor("a"));
|
||||
gQueue.push(new tabAnchor("a2"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
@ -125,6 +114,11 @@
|
|||
title="mochitest for bug 413777: focus the a:focus {overflow: scroll;} shouldn't recreate HTML a accessible">
|
||||
Mozilla Bug 591163
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a><br>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
|
|
@ -70,6 +70,9 @@
|
|||
var tabsAccTree = {
|
||||
role: ROLE_PAGETABLIST,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_PUSHBUTTON // tab scroll up button
|
||||
},
|
||||
{
|
||||
role: ROLE_PAGETAB,
|
||||
children: [
|
||||
|
@ -88,6 +91,9 @@
|
|||
},
|
||||
{
|
||||
role: ROLE_PUSHBUTTON
|
||||
},
|
||||
{
|
||||
role: ROLE_PUSHBUTTON // tab scroll down button
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
@ -48,6 +48,8 @@ include $(topsrcdir)/config/rules.mk
|
|||
_TEST_FILES =\
|
||||
test_list_editabledoc.html \
|
||||
test_list.html \
|
||||
test_recreation.html \
|
||||
test_tableinsubtree.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -78,10 +78,6 @@
|
|||
|
||||
function doTest()
|
||||
{
|
||||
todo(false, "Enable when bug 570275 is fixed");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new addLi("list"));
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Test accessible recreation</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
function recreateAccessible(aID, aWontBeAccessible)
|
||||
{
|
||||
this.node = getNode(aID);
|
||||
this.accessible =
|
||||
isAccessible(this.node) ? getAccessible(this.node) : null;
|
||||
|
||||
this.eventSeq = [ ];
|
||||
|
||||
if (this.accessible)
|
||||
this.eventSeq.push(new invokerChecker(EVENT_HIDE,
|
||||
this.accessible));
|
||||
|
||||
if (!aWontBeAccessible)
|
||||
this.eventSeq.push(new invokerChecker(EVENT_SHOW, getAccessible,
|
||||
this.node));
|
||||
|
||||
this.eventSeq.push(new invokerChecker(EVENT_REORDER,
|
||||
getContainerAccessible(this.node)));
|
||||
|
||||
if (this.accessible) {
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, this.accessible)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
function changeAttr(aID, aAttr, aValue)
|
||||
{
|
||||
this.__proto__ = new recreateAccessible(aID);
|
||||
|
||||
this.invoke = function changeAttr_invoke()
|
||||
{
|
||||
this.node.setAttribute(aAttr, aValue);
|
||||
}
|
||||
|
||||
this.getID = function changeAttr_getID()
|
||||
{
|
||||
return "change " + aAttr + "attribute for " + aID;
|
||||
}
|
||||
}
|
||||
|
||||
function removeAttr(aID, aAttr)
|
||||
{
|
||||
this.__proto__ = new recreateAccessible(aID, true);
|
||||
|
||||
this.invoke = function remvoeAttr_invoke()
|
||||
{
|
||||
this.node.removeAttribute(aAttr);
|
||||
}
|
||||
|
||||
this.getID = function remvoeAttr_getID()
|
||||
{
|
||||
return "remove " + aAttr + "attribute for " + aID;
|
||||
}
|
||||
}
|
||||
|
||||
function changeRole(aID, aHasAccessible)
|
||||
{
|
||||
this.__proto__ = new changeAttr(aID, "role", "button");
|
||||
}
|
||||
|
||||
function removeRole(aID)
|
||||
{
|
||||
this.__proto__ = new removeAttr(aID, "role");
|
||||
}
|
||||
|
||||
function changeOnclick(aID)
|
||||
{
|
||||
this.__proto__ = new changeAttr(aID, "onclick", "alert(3);");
|
||||
}
|
||||
|
||||
function changeHref(aID)
|
||||
{
|
||||
this.__proto__ = new changeAttr(aID, "href", "www");
|
||||
}
|
||||
|
||||
function changeMultiselectable(aID)
|
||||
{
|
||||
this.__proto__ = new changeAttr(aID, "aria-multiselectable", "true");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
// make the accessible an inaccessible
|
||||
gQueue.push(new changeRole("span"));
|
||||
|
||||
// make the inaccessible an accessible
|
||||
gQueue.push(new removeRole("span"));
|
||||
|
||||
// recreate an accessible by role change
|
||||
gQueue.push(new changeRole("div1"));
|
||||
|
||||
// recreate an accessible by onclick change
|
||||
gQueue.push(new changeOnclick("div2"));
|
||||
|
||||
// recreate an accessible by href change
|
||||
gQueue.push(new changeHref("anchor"));
|
||||
|
||||
// recreate an accessible by aria-multiselectable change
|
||||
gQueue.push(new changeMultiselectable("div3"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<span id="span">span</span>
|
||||
<div id="div1">div</div>
|
||||
<div id="div2">div</div>
|
||||
<a id="anchor">anchor</a>
|
||||
<div id="div3" role="listbox">list</div>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,120 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Table creation in ARIA dialog test</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
function showARIADialog(aID)
|
||||
{
|
||||
this.node = getNode(aID);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, this.node)
|
||||
];
|
||||
|
||||
this.invoke = function showARIADialog_invoke()
|
||||
{
|
||||
this.node.style.display = "block";
|
||||
getNode("input").value = "hello";
|
||||
getNode("cell").textContent = "cell1";
|
||||
getNode("input").focus();
|
||||
}
|
||||
|
||||
this.finalCheck = function showARIADialog_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_DIALOG,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TABLE,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_ROW,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_CELL,
|
||||
children: [ { role: ROLE_TEXT_LEAF } ]
|
||||
},
|
||||
{
|
||||
role: ROLE_CELL,
|
||||
children: [ { role: ROLE_ENTRY } ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(aID, tree);
|
||||
}
|
||||
|
||||
this.getID = function showARIADialog_getID()
|
||||
{
|
||||
return "show ARIA dialog";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
// make the accessible an inaccessible
|
||||
gQueue.push(new showARIADialog("dialog"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div id="dialog" role="dialog" style="display: none;">
|
||||
<table>
|
||||
<tr><td id="cell"></td><td><input id="input"></td>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -330,6 +330,7 @@ pref("browser.search.log", false);
|
|||
// Ordering of Search Engines in the Engine list.
|
||||
pref("browser.search.order.1", "chrome://browser-region/locale/region.properties");
|
||||
pref("browser.search.order.2", "chrome://browser-region/locale/region.properties");
|
||||
pref("browser.search.order.3", "chrome://browser-region/locale/region.properties");
|
||||
|
||||
// search bar results always open in a new tab
|
||||
pref("browser.search.openintab", false);
|
||||
|
|
|
@ -972,8 +972,9 @@ var PlacesStarButton = {
|
|||
this.updateState();
|
||||
this._batching = false;
|
||||
},
|
||||
|
||||
onItemAdded: function PSB_onItemAdded(aItemId, aFolder, aIndex, aItemType) {
|
||||
|
||||
onItemAdded: function PSB_onItemAdded(aItemId, aFolder, aIndex, aItemType,
|
||||
aURI) {
|
||||
if (!this._batching && !this._starred)
|
||||
this.updateState();
|
||||
},
|
||||
|
|
|
@ -787,7 +787,6 @@ const gFormSubmitObserver = {
|
|||
init: function()
|
||||
{
|
||||
this.panel = document.getElementById('invalid-form-popup');
|
||||
this.panel.appendChild(document.createTextNode(""));
|
||||
},
|
||||
|
||||
panelIsOpen: function()
|
||||
|
@ -820,8 +819,7 @@ const gFormSubmitObserver = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Limit the message to 256 characters.
|
||||
this.panel.firstChild.nodeValue = element.validationMessage.substring(0, 256);
|
||||
this.panel.firstChild.textContent = element.validationMessage;
|
||||
|
||||
element.focus();
|
||||
|
||||
|
@ -3634,7 +3632,7 @@ var FullScreen = {
|
|||
// The user may quit fullscreen during an animation
|
||||
clearInterval(this._animationInterval);
|
||||
clearTimeout(this._animationTimeout);
|
||||
gNavToolbox.style.marginTop = "0px";
|
||||
gNavToolbox.style.marginTop = "";
|
||||
if (this._isChromeCollapsed)
|
||||
this.mouseoverToggle(true);
|
||||
this._isAnimating = false;
|
||||
|
@ -3767,7 +3765,7 @@ var FullScreen = {
|
|||
if (animateFrameAmount >= gNavToolbox.boxObject.height) {
|
||||
// We've animated enough
|
||||
clearInterval(FullScreen._animationInterval);
|
||||
gNavToolbox.style.marginTop = "0px";
|
||||
gNavToolbox.style.marginTop = "";
|
||||
FullScreen._isAnimating = false;
|
||||
FullScreen._shouldAnimate = false; // Just to make sure
|
||||
FullScreen.mouseoverToggle(false);
|
||||
|
@ -4620,10 +4618,8 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
|
|||
if (popup != aEvent.currentTarget)
|
||||
return;
|
||||
|
||||
var i;
|
||||
|
||||
// Empty the menu
|
||||
for (i = popup.childNodes.length-1; i >= 0; --i) {
|
||||
for (var i = popup.childNodes.length-1; i >= 0; --i) {
|
||||
var deadItem = popup.childNodes[i];
|
||||
if (deadItem.hasAttribute("toolbarId"))
|
||||
popup.removeChild(deadItem);
|
||||
|
@ -4631,9 +4627,9 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
|
|||
|
||||
var firstMenuItem = aInsertPoint || popup.firstChild;
|
||||
|
||||
let toolbarNodes = [document.getElementById("addon-bar")];
|
||||
for (i = 0; i < gNavToolbox.childNodes.length; ++i)
|
||||
toolbarNodes.push(gNavToolbox.childNodes[i]);
|
||||
let toolbarNodes = Array.slice(gNavToolbox.childNodes);
|
||||
toolbarNodes.push(document.getElementById("addon-bar"));
|
||||
|
||||
toolbarNodes.forEach(function(toolbar) {
|
||||
var toolbarName = toolbar.getAttribute("toolbarname");
|
||||
if (toolbarName) {
|
||||
|
@ -5094,54 +5090,28 @@ function asyncOpenWebPanel(event)
|
|||
return true;
|
||||
}
|
||||
|
||||
function handleLinkClick(event, href, linkNode)
|
||||
{
|
||||
function handleLinkClick(event, href, linkNode) {
|
||||
if (event.button == 2) // right click
|
||||
return false;
|
||||
|
||||
var where = whereToOpenLink(event);
|
||||
if (where == "current")
|
||||
return false;
|
||||
|
||||
var doc = event.target.ownerDocument;
|
||||
|
||||
switch (event.button) {
|
||||
case 0: // if left button clicked
|
||||
#ifdef XP_MACOSX
|
||||
if (event.metaKey) { // Cmd
|
||||
#else
|
||||
if (event.ctrlKey) {
|
||||
#endif
|
||||
openNewTabWith(href, doc, null, event, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.shiftKey && event.altKey) {
|
||||
var feedService =
|
||||
Cc["@mozilla.org/browser/feeds/result-service;1"].
|
||||
getService(Ci.nsIFeedResultService);
|
||||
feedService.forcePreviewPage = true;
|
||||
loadURI(href, null, null, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.shiftKey) {
|
||||
openNewWindowWith(href, doc, null, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.altKey) {
|
||||
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
||||
true, doc.documentURIObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
case 1: // if middle button clicked
|
||||
var tab = gPrefService.getBoolPref("browser.tabs.opentabfor.middleclick");
|
||||
if (tab)
|
||||
openNewTabWith(href, doc, null, event, false);
|
||||
else
|
||||
openNewWindowWith(href, doc, null, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
if (where == "save") {
|
||||
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
||||
true, doc.documentURIObject);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
urlSecurityCheck(href, doc.nodePrincipal);
|
||||
openLinkIn(href, where, { fromContent: true,
|
||||
referrerURI: doc.documentURIObject,
|
||||
charset: doc.characterSet });
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
function middleMousePaste(event) {
|
||||
|
@ -5735,7 +5705,7 @@ var OfflineApps = {
|
|||
|
||||
var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
|
||||
getService(Ci.nsIOfflineCacheUpdateService);
|
||||
updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject);
|
||||
updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject, window);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -7516,6 +7486,7 @@ let gPrivateBrowsingUI = {
|
|||
// temporary fix until bug 463607 is fixed
|
||||
document.getElementById("Tools:Sanitize").setAttribute("disabled", "true");
|
||||
|
||||
let docElement = document.documentElement;
|
||||
if (this._privateBrowsingService.autoStarted) {
|
||||
// Disable the menu item in auto-start mode
|
||||
document.getElementById("privateBrowsingItem")
|
||||
|
@ -7526,15 +7497,16 @@ let gPrivateBrowsingUI = {
|
|||
#endif
|
||||
document.getElementById("Tools:PrivateBrowsing")
|
||||
.setAttribute("disabled", "true");
|
||||
if (window.location.href == getBrowserURL())
|
||||
docElement.setAttribute("privatebrowsingmode", "permanent");
|
||||
}
|
||||
else if (window.location.href == getBrowserURL()) {
|
||||
// Adjust the window's title
|
||||
let docElement = document.documentElement;
|
||||
docElement.setAttribute("title",
|
||||
docElement.getAttribute("title_privatebrowsing"));
|
||||
docElement.setAttribute("titlemodifier",
|
||||
docElement.getAttribute("titlemodifier_privatebrowsing"));
|
||||
docElement.setAttribute("browsingmode", "private");
|
||||
docElement.setAttribute("privatebrowsingmode", "temporary");
|
||||
gBrowser.updateTitlebar();
|
||||
}
|
||||
|
||||
|
@ -7581,7 +7553,7 @@ let gPrivateBrowsingUI = {
|
|||
docElement.getAttribute("title_normal"));
|
||||
docElement.setAttribute("titlemodifier",
|
||||
docElement.getAttribute("titlemodifier_normal"));
|
||||
docElement.setAttribute("browsingmode", "normal");
|
||||
docElement.removeAttribute("privatebrowsingmode");
|
||||
}
|
||||
|
||||
// Enable the menu item in after exiting the auto-start mode
|
||||
|
|
|
@ -167,7 +167,9 @@
|
|||
<panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>
|
||||
|
||||
<!-- for invalid form error message -->
|
||||
<panel id="invalid-form-popup" noautofocus="true" hidden="true" level="parent"/>
|
||||
<panel id="invalid-form-popup" noautofocus="true" hidden="true" level="parent">
|
||||
<description/>
|
||||
</panel>
|
||||
|
||||
<panel id="editBookmarkPanel"
|
||||
orient="vertical"
|
||||
|
@ -1012,7 +1014,9 @@
|
|||
key="manBookmarkKb"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="BMB_bookmarkThisPage"
|
||||
#ifndef XP_MACOSX
|
||||
class="menuitem-iconic"
|
||||
#endif
|
||||
label="&bookmarkThisPageCmd.label;"
|
||||
command="Browser:AddBookmarkAs"
|
||||
key="addBookmarkAsKb"/>
|
||||
|
|
|
@ -958,14 +958,17 @@ nsContextMenu.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
// in case we need to prompt the user for authentication
|
||||
function callbacks() {}
|
||||
callbacks.prototype = {
|
||||
getInterface: function sLA_callbacks_getInterface(aIID) {
|
||||
if (aIID.equals(Ci.nsIAuthPrompt) || aIID.equals(Ci.nsIAuthPrompt2)) {
|
||||
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIPromptFactory);
|
||||
return ww.getPrompt(doc.defaultView, aIID);
|
||||
// If the channel demands authentication prompt, we must cancel it
|
||||
// because the save-as-timer would expire and cancel the channel
|
||||
// before we get credentials from user. Both authentication dialog
|
||||
// and save as dialog would appear on the screen as we fall back to
|
||||
// the old fashioned way after the timeout.
|
||||
timer.cancel();
|
||||
channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
|
|
@ -1366,19 +1366,12 @@
|
|||
if (!this._beginRemoveTab(aTab, false, null, true))
|
||||
return;
|
||||
|
||||
/* Don't animate if:
|
||||
- the caller didn't opt in
|
||||
- this is the last tab in the window
|
||||
- this is a pinned tab
|
||||
- a bunch of other tabs are already closing (arbitrary threshold)
|
||||
- the fadein attribute hasn't been set yet
|
||||
- browser.tabs.animate is false */
|
||||
|
||||
if (!animate ||
|
||||
if (!animate /* the caller didn't opt in */ ||
|
||||
isLastTab ||
|
||||
aTab.pinned ||
|
||||
this._removingTabs.length > 3 ||
|
||||
aTab.getAttribute("fadein") != "true" ||
|
||||
this._removingTabs.length > 3 /* don't want lots of concurrent animations */ ||
|
||||
aTab.getAttribute("fadein") != "true" /* fade-in transition hasn't been triggered yet */ ||
|
||||
window.getComputedStyle(aTab).maxWidth == "1px" /* fade-in transition hasn't moved yet */ ||
|
||||
!Services.prefs.getBoolPref("browser.tabs.animate")) {
|
||||
this._endRemoveTab(aTab);
|
||||
return;
|
||||
|
|
|
@ -70,6 +70,7 @@ function GroupItem(listOfEls, options) {
|
|||
options = {};
|
||||
|
||||
this._inited = false;
|
||||
this._uninited = false;
|
||||
this._children = []; // an array of Items
|
||||
this.defaultSize = new Point(TabItems.tabWidth * 1.5, TabItems.tabHeight * 1.5);
|
||||
this.isAGroupItem = true;
|
||||
|
@ -366,7 +367,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
// Function: save
|
||||
// Saves this groupItem to persistent storage.
|
||||
save: function GroupItem_save() {
|
||||
if (!this._inited) // too soon to save now
|
||||
if (!this._inited || this._uninited) // too soon/late to save
|
||||
return;
|
||||
|
||||
var data = this.getStorageData();
|
||||
|
@ -374,6 +375,14 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
Storage.saveGroupItem(gWindow, data);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: deleteData
|
||||
// Deletes the groupItem in the persistent storage.
|
||||
deleteData: function GroupItem_deleteData() {
|
||||
this._uninited = true;
|
||||
Storage.deleteGroupItem(gWindow, this.id);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: getTitle
|
||||
// Returns the title of this groupItem as a string.
|
||||
|
@ -561,7 +570,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
}
|
||||
});
|
||||
|
||||
Storage.deleteGroupItem(gWindow, this.id);
|
||||
this.deleteData();
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -647,7 +656,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
self.$undoContainer = null;
|
||||
Items.unsquish();
|
||||
|
||||
Storage.deleteGroupItem(gWindow, self.id);
|
||||
self.deleteData();
|
||||
};
|
||||
|
||||
this.$undoContainer.click(function(e) {
|
||||
|
@ -2072,7 +2081,7 @@ let GroupItems = {
|
|||
child.close();
|
||||
});
|
||||
|
||||
Storage.deleteGroupItem(gWindow, groupItem.id);
|
||||
groupItem.deleteData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -202,11 +202,10 @@ function TabItem(tab, options) {
|
|||
this._updateDebugBounds();
|
||||
|
||||
TabItems.register(this);
|
||||
|
||||
if (!this.reconnected) {
|
||||
|
||||
if (!this.reconnected)
|
||||
GroupItems.newTab(this, options);
|
||||
}
|
||||
|
||||
|
||||
// tabs which were not reconnected at all or were not immediately added
|
||||
// to a group get the same treatment.
|
||||
if (!this.reconnected || (reconnected && !reconnected.addedToGroup) ) {
|
||||
|
@ -804,7 +803,7 @@ let TabItems = {
|
|||
let oldURL = tabItem.url;
|
||||
tabItem.url = tabUrl;
|
||||
|
||||
if (!tabItem.reconnected && (oldURL == 'about:blank' || !oldURL))
|
||||
if (!tabItem.reconnected)
|
||||
this.reconnect(tabItem);
|
||||
|
||||
tabItem.save();
|
||||
|
@ -1057,10 +1056,10 @@ let TabItems = {
|
|||
item.reconnected = true;
|
||||
found = {addedToGroup: tabData.groupID};
|
||||
} else {
|
||||
// if it's not a blank tab or it belongs to a group, it would mean
|
||||
// the item is reconnected.
|
||||
item.reconnected =
|
||||
(item.tab.linkedBrowser.currentURI.spec != 'about:blank' || item.parent);
|
||||
// We should never have any orphaned tabs. Therefore, item is not
|
||||
// connected if it has no parent and GroupItems.newTab() would handle
|
||||
// the group creation.
|
||||
item.reconnected = (item.parent != null);
|
||||
}
|
||||
item.save();
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ _BROWSER_FILES = \
|
|||
browser_bug581242.js \
|
||||
browser_bug581253.js \
|
||||
browser_bug581947.js \
|
||||
browser_bug585785.js \
|
||||
browser_bug585830.js \
|
||||
browser_bug592338.js \
|
||||
browser_bug594131.js \
|
||||
|
|
|
@ -65,12 +65,6 @@ function wait_for_install_dialog(aCallback) {
|
|||
|
||||
var TESTS = [
|
||||
function test_blocked_install() {
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "unsigned.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
|
||||
// Wait for the blocked notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -86,8 +80,6 @@ function test_blocked_install() {
|
|||
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -105,24 +97,21 @@ function test_blocked_install() {
|
|||
runNextTest();
|
||||
});
|
||||
});
|
||||
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
function test_whitelisted_install() {
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "unsigned.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_whitelisted_install() {
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -141,19 +130,21 @@ function test_whitelisted_install() {
|
|||
runNextTest();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
function test_failed_download() {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "missing.xpi"
|
||||
"XPI": "unsigned.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_failed_download() {
|
||||
// Wait for the failed notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -167,18 +158,18 @@ function test_failed_download() {
|
|||
Services.perms.remove("example.com", "install");
|
||||
runNextTest();
|
||||
});
|
||||
},
|
||||
|
||||
function test_corrupt_file() {
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "corrupt.xpi"
|
||||
"XPI": "missing.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_corrupt_file() {
|
||||
// Wait for the failed notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -192,18 +183,18 @@ function test_corrupt_file() {
|
|||
Services.perms.remove("example.com", "install");
|
||||
runNextTest();
|
||||
});
|
||||
},
|
||||
|
||||
function test_incompatible() {
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "incompatible.xpi"
|
||||
"XPI": "corrupt.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_incompatible() {
|
||||
// Wait for the failed notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -217,22 +208,20 @@ function test_incompatible() {
|
|||
Services.perms.remove("example.com", "install");
|
||||
runNextTest();
|
||||
});
|
||||
},
|
||||
|
||||
function test_restartless() {
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "restartless.xpi"
|
||||
"XPI": "incompatible.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_restartless() {
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -254,24 +243,23 @@ function test_restartless() {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
function test_multiple() {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"Unsigned XPI": "unsigned.xpi",
|
||||
"Restartless XPI": "restartless.xpi"
|
||||
"XPI": "restartless.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_multiple() {
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -294,17 +282,24 @@ function test_multiple() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"Unsigned XPI": "unsigned.xpi",
|
||||
"Restartless XPI": "restartless.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_url() {
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "unsigned.xpi");
|
||||
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -322,20 +317,15 @@ function test_url() {
|
|||
runNextTest();
|
||||
});
|
||||
});
|
||||
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "unsigned.xpi");
|
||||
},
|
||||
|
||||
function test_localfile() {
|
||||
var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.getService(Components.interfaces.nsIChromeRegistry);
|
||||
try {
|
||||
var path = cr.convertChromeURL(makeURI(CHROMEROOT + "corrupt.xpi")).spec;
|
||||
} catch (ex) {
|
||||
var path = CHROMEROOT + "corrupt.xpi";
|
||||
}
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(path);
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -347,6 +337,16 @@ function test_localfile() {
|
|||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
runNextTest();
|
||||
});
|
||||
|
||||
var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.getService(Components.interfaces.nsIChromeRegistry);
|
||||
try {
|
||||
var path = cr.convertChromeURL(makeURI(CHROMEROOT + "corrupt.xpi")).spec;
|
||||
} catch (ex) {
|
||||
var path = CHROMEROOT + "corrupt.xpi";
|
||||
}
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(path);
|
||||
},
|
||||
|
||||
function test_wronghost() {
|
||||
|
@ -357,8 +357,6 @@ function test_wronghost() {
|
|||
|
||||
gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
gBrowser.loadURI(TESTROOT + "corrupt.xpi");
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -371,24 +369,15 @@ function test_wronghost() {
|
|||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
runNextTest();
|
||||
});
|
||||
|
||||
gBrowser.loadURI(TESTROOT + "corrupt.xpi");
|
||||
}, true);
|
||||
gBrowser.loadURI(TESTROOT2 + "enabled.html");
|
||||
},
|
||||
|
||||
function test_reload() {
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"Unsigned XPI": "unsigned.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -423,23 +412,23 @@ function test_reload() {
|
|||
}, true);
|
||||
gBrowser.loadURI(TESTROOT2 + "enabled.html");
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
function test_theme() {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"Theme XPI": "theme.xpi"
|
||||
"Unsigned XPI": "unsigned.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_theme() {
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -465,16 +454,21 @@ function test_theme() {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
function test_renotify_blocked() {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "unsigned.xpi"
|
||||
"Theme XPI": "theme.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_renotify_blocked() {
|
||||
// Wait for the blocked notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -484,8 +478,6 @@ function test_renotify_blocked() {
|
|||
aPanel.removeEventListener("popuphidden", arguments.callee, false);
|
||||
info("Timeouts after this probably mean bug 589954 regressed");
|
||||
executeSoon(function () {
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
is(notification.id, "addon-install-blocked-notification",
|
||||
|
@ -502,28 +494,24 @@ function test_renotify_blocked() {
|
|||
});
|
||||
});
|
||||
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
});
|
||||
}, false);
|
||||
|
||||
// hide the panel (this simulates the user dismissing it)
|
||||
aPanel.hidePopup();
|
||||
});
|
||||
},
|
||||
|
||||
function test_renotify_installed() {
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "unsigned.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
},
|
||||
|
||||
function test_renotify_installed() {
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
|
@ -535,11 +523,8 @@ function test_renotify_installed() {
|
|||
|
||||
// Install another
|
||||
executeSoon(function () {
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
info("Timeouts after this probably mean bug 589954 regressed");
|
||||
|
||||
// Wait for the complete notification
|
||||
|
@ -555,15 +540,29 @@ function test_renotify_installed() {
|
|||
runNextTest();
|
||||
});
|
||||
});
|
||||
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
});
|
||||
}, false);
|
||||
|
||||
// hide the panel (this simulates the user dismissing it)
|
||||
aPanel.hidePopup();
|
||||
});
|
||||
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"XPI": "unsigned.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -577,8 +576,6 @@ function runNextTest() {
|
|||
is(aInstalls.length, 0, "Should be no active installs");
|
||||
|
||||
if (TESTS.length == 0) {
|
||||
Services.prefs.setBoolPref("extensions.logging.enabled", false);
|
||||
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
@ -589,11 +586,44 @@ function runNextTest() {
|
|||
});
|
||||
};
|
||||
|
||||
var XPInstallObserver = {
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo);
|
||||
info("Observed " + aTopic + " for " + installInfo.installs.length + " installs");
|
||||
installInfo.installs.forEach(function(aInstall) {
|
||||
info("Install of " + aInstall.sourceURI.spec + " was in state " + aInstall.state);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function test() {
|
||||
requestLongerTimeout(2);
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref("extensions.logging.enabled", true);
|
||||
|
||||
Services.obs.addObserver(XPInstallObserver, "addon-install-started", false);
|
||||
Services.obs.addObserver(XPInstallObserver, "addon-install-blocked", false);
|
||||
Services.obs.addObserver(XPInstallObserver, "addon-install-failed", false);
|
||||
Services.obs.addObserver(XPInstallObserver, "addon-install-complete", false);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
// Make sure no more test parts run in case we were timed out
|
||||
TESTS = [];
|
||||
|
||||
AddonManager.getAllInstalls(function(aInstalls) {
|
||||
aInstalls.forEach(function(aInstall) {
|
||||
aInstall.cancel();
|
||||
});
|
||||
});
|
||||
|
||||
Services.prefs.clearUserPref("extensions.logging.enabled");
|
||||
|
||||
Services.obs.removeObserver(XPInstallObserver, "addon-install-started");
|
||||
Services.obs.removeObserver(XPInstallObserver, "addon-install-blocked");
|
||||
Services.obs.removeObserver(XPInstallObserver, "addon-install-failed");
|
||||
Services.obs.removeObserver(XPInstallObserver, "addon-install-complete");
|
||||
});
|
||||
|
||||
runNextTest();
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ function checkPopupHide()
|
|||
|
||||
function checkPopupMessage(doc)
|
||||
{
|
||||
is(gInvalidFormPopup.firstChild.nodeValue,
|
||||
doc.getElementById('i').validationMessage.substring(0,256),
|
||||
"The panel should show the 256 first characters of the validationMessage");
|
||||
is(gInvalidFormPopup.firstChild.textContent,
|
||||
doc.getElementById('i').validationMessage,
|
||||
"The panel should show the message from validationMessage");
|
||||
}
|
||||
|
||||
let gObserver = {
|
||||
|
@ -132,50 +132,11 @@ function test3()
|
|||
gBrowser.selectedTab.linkedBrowser.loadURI(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, we check that the validation message is correctly cut.
|
||||
*/
|
||||
function test4()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i'><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
||||
gInvalidFormPopup.addEventListener("popupshown", function() {
|
||||
gInvalidFormPopup.removeEventListener("popupshown", arguments.callee, false);
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
is(doc.activeElement, doc.getElementById('i'),
|
||||
"First invalid element should be focused");
|
||||
|
||||
checkPopupShow();
|
||||
checkPopupMessage(doc);
|
||||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test5);
|
||||
}, false);
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
let msg = "";
|
||||
for (let i=0; i<50; ++i) {
|
||||
msg += "abcde ";
|
||||
}
|
||||
// msg has 300 characters
|
||||
gBrowser.contentDocument.getElementById('i').setCustomValidity(msg);
|
||||
gBrowser.contentDocument.getElementById('s').click();
|
||||
}, true);
|
||||
|
||||
gBrowser.selectedTab = tab;
|
||||
gBrowser.selectedTab.linkedBrowser.loadURI(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, we check that, we can hide the popup by interacting with the
|
||||
* invalid element.
|
||||
*/
|
||||
function test5()
|
||||
function test4()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -197,7 +158,7 @@ function test5()
|
|||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test6);
|
||||
executeSoon(test5);
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
@ -215,7 +176,7 @@ function test5()
|
|||
* In this test, we check that we can hide the popup by blurring the invalid
|
||||
* element.
|
||||
*/
|
||||
function test6()
|
||||
function test5()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -237,7 +198,7 @@ function test6()
|
|||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test7);
|
||||
executeSoon(test6);
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
@ -254,7 +215,7 @@ function test6()
|
|||
/**
|
||||
* In this test, we check that we can hide the popup by pressing TAB.
|
||||
*/
|
||||
function test7()
|
||||
function test6()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -276,7 +237,7 @@ function test7()
|
|||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test8);
|
||||
executeSoon(test7);
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
@ -293,7 +254,7 @@ function test7()
|
|||
/**
|
||||
* In this test, we check that the popup will hide if we move to another tab.
|
||||
*/
|
||||
function test8()
|
||||
function test7()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -317,7 +278,7 @@ function test8()
|
|||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(test9);
|
||||
executeSoon(test8);
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
@ -336,7 +297,7 @@ function test8()
|
|||
* invalid form is submitted in another tab than the current focused one
|
||||
* (submitted in background).
|
||||
*/
|
||||
function test9()
|
||||
function test8()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -355,7 +316,7 @@ function test9()
|
|||
gBrowser.removeTab(tab, {animate: false});
|
||||
|
||||
// Next test
|
||||
executeSoon(test10);
|
||||
executeSoon(test9);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -376,7 +337,7 @@ function test9()
|
|||
/**
|
||||
* In this test, we check that the author defined error message is shown.
|
||||
*/
|
||||
function test10()
|
||||
function test9()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input x-moz-errormessage='foo' required id='i'><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -390,7 +351,7 @@ function test10()
|
|||
|
||||
checkPopupShow();
|
||||
|
||||
is(gInvalidFormPopup.firstChild.nodeValue, "foo",
|
||||
is(gInvalidFormPopup.firstChild.textContent, "foo",
|
||||
"The panel should show the author defined error message");
|
||||
|
||||
// Clean-up and next test.
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
var tab;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
tab = gBrowser.addTab();
|
||||
isnot(tab.getAttribute("fadein"), "true", "newly opened tab is yet to fade in");
|
||||
|
||||
// Try to remove the tab right before the opening animation's first frame
|
||||
window.mozRequestAnimationFrame(checkAnimationState);
|
||||
}
|
||||
|
||||
function checkAnimationState() {
|
||||
if (tab.getAttribute("fadein") != "true") {
|
||||
window.mozRequestAnimationFrame(checkAnimationState);
|
||||
return;
|
||||
}
|
||||
|
||||
info(window.getComputedStyle(tab).maxWidth);
|
||||
gBrowser.removeTab(tab, { animate: true });
|
||||
if (!tab.parentNode) {
|
||||
ok(true, "tab removed synchronously since the opening animation hasn't moved yet");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
info("tab didn't close immediately, so the tab opening animation must have started moving");
|
||||
info("waiting for the tab to close asynchronously");
|
||||
tab.addEventListener("transitionend", function (event) {
|
||||
if (event.propertyName == "max-width")
|
||||
executeSoon(function () {
|
||||
ok(!tab.parentNode, "tab removed asynchronously");
|
||||
finish();
|
||||
});
|
||||
}, false);
|
||||
}
|
|
@ -56,6 +56,7 @@ _BROWSER_FILES = \
|
|||
browser_tabview_bug595804.js \
|
||||
browser_tabview_bug595930.js \
|
||||
browser_tabview_bug595943.js \
|
||||
browser_tabview_bug598600.js \
|
||||
browser_tabview_dragdrop.js \
|
||||
browser_tabview_exit_button.js \
|
||||
browser_tabview_group.js \
|
||||
|
@ -67,6 +68,7 @@ _BROWSER_FILES = \
|
|||
browser_tabview_startup_transitions.js \
|
||||
browser_tabview_undo_group.js \
|
||||
browser_tabview_firstrun_pref.js \
|
||||
head.js \
|
||||
search1.html \
|
||||
search2.html \
|
||||
$(NULL)
|
||||
|
|
|
@ -59,7 +59,7 @@ function test() {
|
|||
"The currently selected tab should be the first tab in the groupItemOne");
|
||||
|
||||
// create another group with a tab.
|
||||
let groupItemTwo = createEmptyGroupItem(contentWindow, 200);
|
||||
let groupItemTwo = createEmptyGroupItem(contentWindow, 300, 300, 200);
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
@ -111,16 +111,3 @@ function testGroupSwitch(contentWindow, groupItemOne, groupItemTwo) {
|
|||
|
||||
finish();
|
||||
}
|
||||
|
||||
function createEmptyGroupItem(contentWindow, padding) {
|
||||
let pageBounds = contentWindow.Items.getPageBounds();
|
||||
pageBounds.inset(padding, padding);
|
||||
|
||||
let box = new contentWindow.Rect(pageBounds);
|
||||
box.width = 300;
|
||||
box.height = 300;
|
||||
|
||||
let emptyGroupItem = new contentWindow.GroupItem([], { bounds: box });
|
||||
|
||||
return emptyGroupItem;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/* ***** 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 tabview bug598600 test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.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 ***** */
|
||||
let newWin;
|
||||
let prefService;
|
||||
|
||||
function test() {
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
prefService =
|
||||
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).
|
||||
getBranch("browser.panorama.");
|
||||
// make sure we don't trigger the 'first run' behavior
|
||||
prefService.setBoolPref("experienced_first_run", true);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
// open a new window and setup the window state.
|
||||
newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(event) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
let newState = {
|
||||
windows: [{
|
||||
tabs: [{
|
||||
entries: [{ "url": "about:blank" }],
|
||||
hidden: true,
|
||||
attributes: {},
|
||||
extData: {
|
||||
"tabview-tab":
|
||||
'{"bounds":{"left":20,"top":35,"width":280,"height":210},' +
|
||||
'"userSize":null,"url":"about:blank","groupID":1,' +
|
||||
'"imageData":null,"title":null}'
|
||||
}
|
||||
},{
|
||||
entries: [{ url: "about:blank" }],
|
||||
index: 1,
|
||||
hidden: false,
|
||||
attributes: {},
|
||||
extData: {
|
||||
"tabview-tab":
|
||||
'{"bounds":{"left":375,"top":35,"width":280,"height":210},' +
|
||||
'"userSize":null,"url":"about:blank","groupID":2,' +
|
||||
'"imageData":null,"title":null}'
|
||||
}
|
||||
}],
|
||||
selected:2,
|
||||
_closedTabs: [],
|
||||
extData: {
|
||||
"tabview-groups": '{"nextID":3,"activeGroupId":2}',
|
||||
"tabview-group":
|
||||
'{"1":{"bounds":{"left":15,"top":10,"width":320,"height":375},' +
|
||||
'"userSize":null,"locked":{},"title":"","id":1},' +
|
||||
'"2":{"bounds":{"left":380,"top":5,"width":320,"height":375},' +
|
||||
'"userSize":null,"locked":{},"title":"","id":2}}',
|
||||
"tabview-ui": '{"pageBounds":{"left":0,"top":0,"width":875,"height":650}}'
|
||||
}, sizemode:"normal"
|
||||
}]
|
||||
};
|
||||
ss.setWindowState(newWin, JSON.stringify(newState), true);
|
||||
|
||||
// add a new tab.
|
||||
newWin.gBrowser.addTab();
|
||||
is(newWin.gBrowser.tabs.length, 3, "There are 3 browser tabs");
|
||||
|
||||
let onTabViewShow = function() {
|
||||
newWin.removeEventListener("tabviewshown", onTabViewShow, false);
|
||||
|
||||
let contentWindow = newWin.document.getElementById("tab-view").contentWindow;
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 2, "Has two group items");
|
||||
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphan tabs");
|
||||
|
||||
// clean up and finish
|
||||
prefService.setBoolPref("experienced_first_run", false);
|
||||
newWin.close();
|
||||
|
||||
finish();
|
||||
}
|
||||
newWin.addEventListener("tabviewshown", onTabViewShow, false);
|
||||
newWin.TabView.toggle();
|
||||
}, false);
|
||||
}
|
|
@ -95,10 +95,8 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
|||
ok(tabItem, "The tab item exists");
|
||||
|
||||
// calculate the offsets
|
||||
let groupTwoRect = groupTwo.getBounds();
|
||||
let groupTwoRectCenter = groupTwoRect.center();
|
||||
let tabItemRect = tabItem.getBounds();
|
||||
let tabItemRectCenter = tabItemRect.center();
|
||||
let groupTwoRectCenter = groupTwo.getBounds().center();
|
||||
let tabItemRectCenter = tabItem.getBounds().center();
|
||||
let offsetX =
|
||||
Math.round(groupTwoRectCenter.x - tabItemRectCenter.x);
|
||||
let offsetY =
|
||||
|
@ -132,41 +130,23 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
|||
simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
|
||||
}
|
||||
|
||||
function simulateDragDrop(tabItem, offsetX, offsetY, contentWindow) {
|
||||
// enter drag mode
|
||||
let dataTransfer;
|
||||
function simulateDragDrop(element, offsetX, offsetY, contentWindow) {
|
||||
let rect = element.getBoundingClientRect();
|
||||
let startX = (rect.right - rect.left)/2;
|
||||
let startY = (rect.bottom - rect.top)/2;
|
||||
let incrementX = offsetX / 2;
|
||||
let incrementY = offsetY / 2;
|
||||
|
||||
EventUtils.synthesizeMouse(
|
||||
tabItem, 1, 1, { type: "mousedown" }, contentWindow);
|
||||
event = contentWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent(
|
||||
"dragenter", true, true, contentWindow, 0, 0, 0, 0, 0,
|
||||
false, false, false, false, 1, null, dataTransfer);
|
||||
tabItem.dispatchEvent(event);
|
||||
|
||||
// drag over
|
||||
if (offsetX || offsetY) {
|
||||
let Ci = Components.interfaces;
|
||||
let utils = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
let rect = tabItem.getBoundingClientRect();
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
let left = rect.left + Math.round(i * offsetX / 5);
|
||||
let top = rect.top + Math.round(i * offsetY / 5);
|
||||
utils.sendMouseEvent("mousemove", left, top, 0, 1, 0);
|
||||
}
|
||||
event = contentWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent(
|
||||
"dragover", true, true, contentWindow, 0, 0, 0, 0, 0,
|
||||
false, false, false, false, 0, null, dataTransfer);
|
||||
tabItem.dispatchEvent(event);
|
||||
}
|
||||
element, startX, startY, { type: "mousedown" });
|
||||
|
||||
// drop
|
||||
EventUtils.synthesizeMouse(tabItem, 0, 0, { type: "mouseup" }, contentWindow);
|
||||
event = contentWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent(
|
||||
"drop", true, true, contentWindow, 0, 0, 0, 0, 0,
|
||||
false, false, false, false, 0, null, dataTransfer);
|
||||
tabItem.dispatchEvent(event);
|
||||
for (let i = 1; i <= 2; i++) {
|
||||
EventUtils.synthesizeMouse(
|
||||
element, (startX + incrementX * i), (startY + incrementY * i),
|
||||
{ type: "mousemove" });
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouse(
|
||||
element, (startX + incrementX * 2), (startY + incrementY * 2),
|
||||
{ type: "mouseup" });
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ function testEmptyGroupItem(contentWindow) {
|
|||
let groupItemCount = contentWindow.GroupItems.groupItems.length;
|
||||
|
||||
// create empty group item
|
||||
let emptyGroupItem = createEmptyGroupItem(contentWindow, 100);
|
||||
let emptyGroupItem = createEmptyGroupItem(contentWindow, 300, 300, 100, true);
|
||||
ok(emptyGroupItem.isEmpty(), "This group is empty");
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, ++groupItemCount,
|
||||
|
@ -89,7 +89,7 @@ function testEmptyGroupItem(contentWindow) {
|
|||
}
|
||||
|
||||
function testGroupItemWithTabItem(contentWindow) {
|
||||
let groupItem = createEmptyGroupItem(contentWindow, 200);
|
||||
let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200, true);
|
||||
let tabItemCount = 0;
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
|
@ -161,17 +161,3 @@ function testGroupItemWithTabItem(contentWindow) {
|
|||
|
||||
EventUtils.synthesizeMouse(newTabButton[0], 1, 1, {}, contentWindow);
|
||||
}
|
||||
|
||||
function createEmptyGroupItem(contentWindow, padding) {
|
||||
let pageBounds = contentWindow.Items.getPageBounds();
|
||||
pageBounds.inset(padding, padding);
|
||||
|
||||
let box = new contentWindow.Rect(pageBounds);
|
||||
box.width = 300;
|
||||
box.height = 300;
|
||||
|
||||
let emptyGroupItem = new contentWindow.GroupItem([], { bounds: box,
|
||||
immediately: true });
|
||||
|
||||
return emptyGroupItem;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ function onTabViewWindowLoaded() {
|
|||
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphaned tabs");
|
||||
|
||||
// 2) create a group, add a blank tab
|
||||
let groupItem = createEmptyGroupItem(contentWindow, 200);
|
||||
let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
newWin.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
@ -110,19 +110,6 @@ function onTabViewWindowLoaded() {
|
|||
EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
|
||||
}
|
||||
|
||||
function createEmptyGroupItem(contentWindow, padding) {
|
||||
let pageBounds = contentWindow.Items.getPageBounds();
|
||||
pageBounds.inset(padding, padding);
|
||||
|
||||
let box = new contentWindow.Rect(pageBounds);
|
||||
box.width = 300;
|
||||
box.height = 300;
|
||||
|
||||
let emptyGroupItem = new contentWindow.GroupItem([], { bounds: box });
|
||||
|
||||
return emptyGroupItem;
|
||||
}
|
||||
|
||||
function whenWindowObservesOnce(win, topic, callback) {
|
||||
let windowWatcher =
|
||||
Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);
|
||||
|
|
|
@ -71,15 +71,13 @@ function onTabViewLoadedAndShown() {
|
|||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
// go into private browsing and make sure Tab View becomes hidden
|
||||
pb.privateBrowsingEnabled = true;
|
||||
ok(!TabView.isVisible(), "Tab View is no longer visible");
|
||||
afterAllTabsLoaded(function() {
|
||||
togglePBAndThen(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is no longer visible");
|
||||
verifyPB();
|
||||
|
||||
// exit private browsing and make sure Tab View is shown again
|
||||
pb.privateBrowsingEnabled = false;
|
||||
ok(TabView.isVisible(), "Tab View is visible again");
|
||||
afterAllTabsLoaded(function() {
|
||||
togglePBAndThen(function() {
|
||||
ok(TabView.isVisible(), "Tab View is visible again");
|
||||
verifyNormal();
|
||||
|
||||
// exit Tab View
|
||||
|
@ -95,14 +93,12 @@ function onTabViewHidden() {
|
|||
ok(!TabView.isVisible(), "Tab View is not visible");
|
||||
|
||||
// go into private browsing and make sure Tab View remains hidden
|
||||
pb.privateBrowsingEnabled = true;
|
||||
ok(!TabView.isVisible(), "Tab View is still not visible");
|
||||
afterAllTabsLoaded(function() {
|
||||
togglePBAndThen(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is still not visible");
|
||||
verifyPB();
|
||||
|
||||
// turn private browsing back off
|
||||
pb.privateBrowsingEnabled = false;
|
||||
afterAllTabsLoaded(function() {
|
||||
togglePBAndThen(function() {
|
||||
verifyNormal();
|
||||
|
||||
// clean up
|
||||
|
@ -139,6 +135,21 @@ function verifyNormal() {
|
|||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
function togglePBAndThen(callback) {
|
||||
function pbObserver(aSubject, aTopic, aData) {
|
||||
if (aTopic != "private-browsing-transition-complete")
|
||||
return;
|
||||
|
||||
Services.obs.removeObserver(pbObserver, "private-browsing-transition-complete");
|
||||
|
||||
afterAllTabsLoaded(callback);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(pbObserver, "private-browsing-transition-complete", false);
|
||||
pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
|
||||
}
|
||||
|
||||
// ----------
|
||||
function afterAllTabsLoaded(callback) {
|
||||
let stillToLoad = 0;
|
||||
|
|
|
@ -11,14 +11,15 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Fennec Electrolysis.
|
||||
* The Original Code is the utilities for tabview.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.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
|
||||
|
@ -34,27 +35,17 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/ipc/DocumentRendererShmemParent.h"
|
||||
function createEmptyGroupItem(contentWindow, width, height, padding, noAnimation) {
|
||||
let pageBounds = contentWindow.Items.getPageBounds();
|
||||
pageBounds.inset(padding, padding);
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
let box = new contentWindow.Rect(pageBounds);
|
||||
box.width = width;
|
||||
box.height = height;
|
||||
|
||||
let immediately = noAnimation ? true: false;
|
||||
let emptyGroupItem =
|
||||
new contentWindow.GroupItem([], { bounds: box, immediately: immediately });
|
||||
|
||||
DocumentRendererShmemParent::DocumentRendererShmemParent()
|
||||
{}
|
||||
|
||||
DocumentRendererShmemParent::~DocumentRendererShmemParent()
|
||||
{}
|
||||
|
||||
void
|
||||
DocumentRendererShmemParent::SetCanvas(nsICanvasRenderingContextInternal* aCanvas)
|
||||
{
|
||||
mCanvas = aCanvas;
|
||||
}
|
||||
|
||||
bool
|
||||
DocumentRendererShmemParent::Recv__delete__(const PRInt32& x, const PRInt32& y,
|
||||
const PRInt32& w, const PRInt32& h,
|
||||
Shmem& data)
|
||||
{
|
||||
mCanvas->Swap(data, x, y, w, h);
|
||||
return true;
|
||||
return emptyGroupItem;
|
||||
}
|
|
@ -130,11 +130,24 @@
|
|||
if (!pasteAndGo)
|
||||
return;
|
||||
var controller = document.commandDispatcher.getControllerForCommand("cmd_paste");
|
||||
var enabled = controller.isCommandEnabled("cmd_paste");
|
||||
if (enabled)
|
||||
pasteAndGo.removeAttribute("disabled");
|
||||
else
|
||||
pasteAndGo.setAttribute("disabled", "true");
|
||||
var couldBeURL = controller.isCommandEnabled("cmd_paste");
|
||||
if (couldBeURL) {
|
||||
let cbSvc = Cc["@mozilla.org/widget/clipboard;1"].
|
||||
getService(Ci.nsIClipboard);
|
||||
let xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
xferable.addDataFlavor("text/unicode");
|
||||
cbSvc.getData(xferable, cbSvc.kGlobalClipboard);
|
||||
let data = {};
|
||||
xferable.getTransferData("text/unicode", data, {});
|
||||
data = data.value.QueryInterface(Ci.nsISupportsString).data;
|
||||
try {
|
||||
makeURI(data);
|
||||
} catch (ex) { // clipboard data is not a URL
|
||||
couldBeURL = false;
|
||||
}
|
||||
}
|
||||
pasteAndGo.hidden = !couldBeURL;
|
||||
}, false);
|
||||
|
||||
var insertLocation = cxmenu.firstChild;
|
||||
|
@ -147,7 +160,8 @@
|
|||
GetStringFromName("pasteAndGo.label");
|
||||
pasteAndGo.setAttribute("label", label);
|
||||
pasteAndGo.setAttribute("anonid", "paste-and-go");
|
||||
pasteAndGo.setAttribute("oncommand", "goDoCommand('cmd_paste'); gURLBar.handleCommand();");
|
||||
pasteAndGo.setAttribute("oncommand",
|
||||
"gURLBar.value = ''; goDoCommand('cmd_paste'); gURLBar.handleCommand();");
|
||||
cxmenu.insertBefore(pasteAndGo, insertLocation.nextSibling);
|
||||
}
|
||||
]]></constructor>
|
||||
|
|
|
@ -50,8 +50,12 @@ function getBrowserURL()
|
|||
return "chrome://browser/content/browser.xul";
|
||||
}
|
||||
|
||||
function getTopWin()
|
||||
{
|
||||
function getTopWin(skipPopups) {
|
||||
if (skipPopups) {
|
||||
return Components.classes["@mozilla.org/browser/browserglue;1"]
|
||||
.getService(Components.interfaces.nsIBrowserGlue)
|
||||
.getMostRecentBrowserWindow();
|
||||
}
|
||||
return Services.wm.getMostRecentWindow("navigator:browser");
|
||||
}
|
||||
|
||||
|
@ -158,18 +162,33 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
|
|||
* relatedToCurrent (boolean)
|
||||
*/
|
||||
function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) {
|
||||
var params;
|
||||
|
||||
if (arguments.length == 3 && typeof arguments[2] == "object") {
|
||||
params = aAllowThirdPartyFixup;
|
||||
} else {
|
||||
params = {
|
||||
allowThirdPartyFixup: aAllowThirdPartyFixup,
|
||||
postData: aPostData,
|
||||
referrerURI: aReferrerURI
|
||||
};
|
||||
}
|
||||
|
||||
params.fromContent = false;
|
||||
|
||||
openLinkIn(url, where, params);
|
||||
}
|
||||
|
||||
function openLinkIn(url, where, params) {
|
||||
if (!where || !url)
|
||||
return;
|
||||
|
||||
var aRelatedToCurrent;
|
||||
if (arguments.length == 3 &&
|
||||
typeof arguments[2] == "object") {
|
||||
let params = arguments[2];
|
||||
aAllowThirdPartyFixup = params.allowThirdPartyFixup;
|
||||
aPostData = params.postData;
|
||||
aReferrerURI = params.referrerURI;
|
||||
aRelatedToCurrent = params.relatedToCurrent;
|
||||
}
|
||||
var aFromContent = params.fromContent;
|
||||
var aAllowThirdPartyFixup = params.allowThirdPartyFixup;
|
||||
var aPostData = params.postData;
|
||||
var aCharset = params.charset;
|
||||
var aReferrerURI = params.referrerURI;
|
||||
var aRelatedToCurrent = params.relatedToCurrent;
|
||||
|
||||
if (where == "save") {
|
||||
saveURL(url, null, null, true, null, aReferrerURI);
|
||||
|
@ -179,6 +198,11 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
|
|||
const Ci = Components.interfaces;
|
||||
|
||||
var w = getTopWin();
|
||||
if ((where == "tab" || where == "tabshifted") &&
|
||||
w.document.documentElement.getAttribute("chromehidden")) {
|
||||
w = getTopWin(true);
|
||||
aRelatedToCurrent = false;
|
||||
}
|
||||
|
||||
if (!w || where == "window") {
|
||||
var sa = Cc["@mozilla.org/supports-array;1"].
|
||||
|
@ -188,12 +212,19 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
|
|||
createInstance(Ci.nsISupportsString);
|
||||
wuri.data = url;
|
||||
|
||||
let charset = null;
|
||||
if (aCharset) {
|
||||
charset = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
charset.data = "charset=" + aCharset;
|
||||
}
|
||||
|
||||
var allowThirdPartyFixupSupports = Cc["@mozilla.org/supports-PRBool;1"].
|
||||
createInstance(Ci.nsISupportsPRBool);
|
||||
allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup;
|
||||
|
||||
sa.AppendElement(wuri);
|
||||
sa.AppendElement(null);
|
||||
sa.AppendElement(charset);
|
||||
sa.AppendElement(aReferrerURI);
|
||||
sa.AppendElement(aPostData);
|
||||
sa.AppendElement(allowThirdPartyFixupSupports);
|
||||
|
@ -210,7 +241,9 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
|
|||
return;
|
||||
}
|
||||
|
||||
var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground");
|
||||
var loadInBackground = aFromContent ?
|
||||
getBoolPref("browser.tabs.loadInBackground") :
|
||||
getBoolPref("browser.tabs.loadBookmarksInBackground");
|
||||
|
||||
if (where == "current" && w.gBrowser.selectedTab.pinned) {
|
||||
try {
|
||||
|
@ -237,6 +270,7 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
|
|||
let browser = w.gBrowser;
|
||||
browser.loadOneTab(url, {
|
||||
referrerURI: aReferrerURI,
|
||||
charset: aCharset,
|
||||
postData: aPostData,
|
||||
inBackground: loadInBackground,
|
||||
allowThirdPartyFixup: aAllowThirdPartyFixup,
|
||||
|
@ -449,7 +483,7 @@ function openTroubleshootingPage()
|
|||
*/
|
||||
function openFeedbackPage()
|
||||
{
|
||||
openUILinkIn("http://input.mozilla.com/sad", "tab");
|
||||
openUILinkIn("http://input.mozilla.com/feedback", "tab");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ FeedWriter.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Calls doCommand for a the given XUL element within the context of the
|
||||
* Calls doCommand for a given XUL element within the context of the
|
||||
* content document.
|
||||
*
|
||||
* @param aElement
|
||||
|
|
|
@ -1161,7 +1161,8 @@ var gEditItemOverlay = {
|
|||
this._folderMenuList.selectedItem = folderItem;
|
||||
},
|
||||
|
||||
onItemAdded: function EIO_onItemAdded(aItemId, aFolder, aIndex, aItemType) {
|
||||
onItemAdded: function EIO_onItemAdded(aItemId, aFolder, aIndex, aItemType,
|
||||
aURI) {
|
||||
this._lastNewItem = aItemId;
|
||||
},
|
||||
|
||||
|
|
|
@ -46,8 +46,6 @@
|
|||
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE page [
|
||||
<!ENTITY % historyDTD SYSTEM "chrome://browser/locale/history/history.dtd">
|
||||
%historyDTD;
|
||||
<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
|
||||
%placesDTD;
|
||||
]>
|
||||
|
|
|
@ -391,7 +391,7 @@
|
|||
<vbox id="defaultView" flex="1">
|
||||
<vbox id="searchModifiers" hidden="true">
|
||||
<toolbar id="organizerScopeBar" class="chromeclass-toolbar" align="center">
|
||||
<label id="scopeBarTitle" value="&search.label;"/>
|
||||
<label id="scopeBarTitle" value="&search.in.label;"/>
|
||||
<toolbarbutton id="scopeBarAll" type="radio" group="scopeBar"
|
||||
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
|
||||
label="&search.scopeBookmarks.label;"
|
||||
|
|
|
@ -1381,7 +1381,7 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ptm", function() {
|
|||
},
|
||||
|
||||
/**
|
||||
* Transaction for editing a the description of a bookmark or a folder.
|
||||
* Transaction for editing the description of a bookmark or a folder.
|
||||
*
|
||||
* @param aItemId
|
||||
* id of the item to edit.
|
||||
|
|
|
@ -58,12 +58,11 @@ var dragDirections = { LEFT: 0, UP: 1, RIGHT: 2, DOWN: 3 };
|
|||
* @param aDirection
|
||||
* Direction for the dragging gesture, see dragDirections helper object.
|
||||
*/
|
||||
function synthesizeDragWithDirection(aElement, aExpectedDragData, aDirection) {
|
||||
var trapped = false;
|
||||
|
||||
function synthesizeDragWithDirection(aElement, aExpectedDragData, aDirection, aCallback) {
|
||||
// Dragstart listener function.
|
||||
var trapDrag = function(event) {
|
||||
trapped = true;
|
||||
gBookmarksToolbar.addEventListener("dragstart", function(event)
|
||||
{
|
||||
info("A dragstart event has been trapped.");
|
||||
var dataTransfer = event.dataTransfer;
|
||||
is(dataTransfer.mozItemCount, aExpectedDragData.length,
|
||||
"Number of dragged items should be the same.");
|
||||
|
@ -88,7 +87,23 @@ function synthesizeDragWithDirection(aElement, aExpectedDragData, aDirection) {
|
|||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
gBookmarksToolbar.removeEventListener("dragstart", arguments.callee, false);
|
||||
|
||||
// This is likely to cause a click event, and, in case we are dragging a
|
||||
// bookmark, an unwanted page visit. Prevent the click event.
|
||||
aElement.addEventListener("click", prevent, false);
|
||||
EventUtils.synthesizeMouse(aElement,
|
||||
startingPoint.x + xIncrement * 9,
|
||||
startingPoint.y + yIncrement * 9,
|
||||
{ type: "mouseup" });
|
||||
aElement.removeEventListener("click", prevent, false);
|
||||
|
||||
// Cleanup eventually opened menus.
|
||||
if (aElement.localName == "menu" && aElement.open)
|
||||
aElement.open = false;
|
||||
aCallback()
|
||||
}, false);
|
||||
|
||||
var prevent = function(aEvent) {aEvent.preventDefault();}
|
||||
|
||||
|
@ -122,26 +137,10 @@ function synthesizeDragWithDirection(aElement, aExpectedDragData, aDirection) {
|
|||
startingPoint.x + xIncrement * 1,
|
||||
startingPoint.y + yIncrement * 1,
|
||||
{ type: "mousemove" });
|
||||
gBookmarksToolbar.addEventListener("dragstart", trapDrag, false);
|
||||
EventUtils.synthesizeMouse(aElement,
|
||||
startingPoint.x + xIncrement * 9,
|
||||
startingPoint.y + yIncrement * 9,
|
||||
{ type: "mousemove" });
|
||||
ok(trapped, "A dragstart event has been trapped.");
|
||||
gBookmarksToolbar.removeEventListener("dragstart", trapDrag, false);
|
||||
|
||||
// This is likely to cause a click event, and, in case we are dragging a
|
||||
// bookmark, an unwanted page visit. Prevent the click event.
|
||||
aElement.addEventListener("click", prevent, false);
|
||||
EventUtils.synthesizeMouse(aElement,
|
||||
startingPoint.x + xIncrement * 9,
|
||||
startingPoint.y + yIncrement * 9,
|
||||
{ type: "mouseup" });
|
||||
aElement.removeEventListener("click", prevent, false);
|
||||
|
||||
// Cleanup eventually opened menus.
|
||||
if (aElement.localName == "menu" && aElement.open)
|
||||
aElement.open = false;
|
||||
}
|
||||
|
||||
function getToolbarNodeForItemId(aItemId) {
|
||||
|
@ -190,17 +189,28 @@ var gTests = [
|
|||
isnot(element._placesNode, null, "Toolbar node has an associated Places node.");
|
||||
var expectedData = getExpectedDataForPlacesNode(element._placesNode);
|
||||
|
||||
ok(true, "Dragging left");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.LEFT);
|
||||
ok(true, "Dragging right");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.RIGHT);
|
||||
ok(true, "Dragging up");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.UP);
|
||||
ok(true, "Dragging down");
|
||||
synthesizeDragWithDirection(element, new Array(), dragDirections.DOWN);
|
||||
|
||||
// Cleanup.
|
||||
PlacesUtils.bookmarks.removeItem(folderId);
|
||||
info("Dragging left");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.LEFT,
|
||||
function ()
|
||||
{
|
||||
info("Dragging right");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.RIGHT,
|
||||
function ()
|
||||
{
|
||||
info("Dragging up");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.UP,
|
||||
function ()
|
||||
{
|
||||
info("Dragging down");
|
||||
synthesizeDragWithDirection(element, new Array(), dragDirections.DOWN,
|
||||
function () {
|
||||
// Cleanup.
|
||||
PlacesUtils.bookmarks.removeItem(folderId);
|
||||
nextTest();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -221,17 +231,28 @@ var gTests = [
|
|||
isnot(element._placesNode, null, "Toolbar node has an associated Places node.");
|
||||
var expectedData = getExpectedDataForPlacesNode(element._placesNode);
|
||||
|
||||
ok(true, "Dragging left");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.LEFT);
|
||||
ok(true, "Dragging right");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.RIGHT);
|
||||
ok(true, "Dragging up");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.UP);
|
||||
ok(true, "Dragging down");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.DOWN);
|
||||
|
||||
// Cleanup.
|
||||
PlacesUtils.bookmarks.removeItem(itemId);
|
||||
info("Dragging left");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.LEFT,
|
||||
function ()
|
||||
{
|
||||
info("Dragging right");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.RIGHT,
|
||||
function ()
|
||||
{
|
||||
info("Dragging up");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.UP,
|
||||
function ()
|
||||
{
|
||||
info("Dragging down");
|
||||
synthesizeDragWithDirection(element, expectedData, dragDirections.DOWN,
|
||||
function () {
|
||||
// Cleanup.
|
||||
PlacesUtils.bookmarks.removeItem(folderId);
|
||||
nextTest();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
];
|
||||
|
@ -242,7 +263,7 @@ function nextTest() {
|
|||
info("Start of test: " + test.desc);
|
||||
test.run();
|
||||
|
||||
setTimeout(nextTest, 0);
|
||||
waitForFocus(nextTest);
|
||||
}
|
||||
else {
|
||||
// Collapse the personal toolbar if needed.
|
||||
|
@ -256,11 +277,12 @@ let toolbar = document.getElementById("PersonalToolbar");
|
|||
let wasCollapsed = toolbar.collapsed;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Uncollapse the personal toolbar if needed.
|
||||
if (wasCollapsed)
|
||||
setToolbarVisibility(toolbar, true);
|
||||
|
||||
waitForExplicitFinish();
|
||||
nextTest();
|
||||
waitForFocus(nextTest);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,24 @@
|
|||
// This test makes sure that the Forget This Site command is hidden for multiple
|
||||
// selections.
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
|
||||
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
|
||||
}
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
|
@ -61,6 +79,7 @@ function test() {
|
|||
ww.unregisterNotification(observer);
|
||||
let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
SimpleTest.waitForFocus(function() {
|
||||
executeSoon(function() {
|
||||
// Select History in the left pane.
|
||||
organizer.PlacesOrganizer.selectLeftPaneQuery('History');
|
||||
let PO = organizer.PlacesOrganizer;
|
||||
|
@ -78,7 +97,7 @@ function test() {
|
|||
// Open the context menu
|
||||
let contextmenu = doc.getElementById("placesContext");
|
||||
contextmenu.addEventListener("popupshown", function() {
|
||||
contextmenu.removeEventListener("popupshown", arguments.callee, false);
|
||||
contextmenu.removeEventListener("popupshown", arguments.callee, true);
|
||||
let forgetThisSite = doc.getElementById("placesContext_deleteHost");
|
||||
let hideForgetThisSite = (selectionCount != 1);
|
||||
is(forgetThisSite.hidden, hideForgetThisSite,
|
||||
|
@ -86,17 +105,27 @@ function test() {
|
|||
"be hidden with " + selectionCount + " items selected");
|
||||
// Close the context menu
|
||||
contextmenu.hidePopup();
|
||||
// Wait for the Organizer window to actually be closed
|
||||
function closeObserver(aSubject, aTopic, aData) {
|
||||
if (aTopic != "domwindowclosed")
|
||||
return;
|
||||
ww.unregisterNotification(closeObserver);
|
||||
SimpleTest.waitForFocus(function() {
|
||||
// Proceed
|
||||
funcNext();
|
||||
});
|
||||
}
|
||||
ww.registerNotification(closeObserver);
|
||||
// Close Library window.
|
||||
organizer.close();
|
||||
// Proceed
|
||||
funcNext();
|
||||
}, false);
|
||||
}, true);
|
||||
// Get cell coordinates
|
||||
var x = {}, y = {}, width = {}, height = {};
|
||||
tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text",
|
||||
x, y, width, height);
|
||||
// Initiate a context menu for the selected cell
|
||||
EventUtils.synthesizeMouse(tree.body, x + 4, y + 4, {type: "contextmenu"}, organizer);
|
||||
EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, {type: "contextmenu"}, organizer);
|
||||
});
|
||||
}, organizer);
|
||||
}
|
||||
|
||||
|
@ -111,9 +140,7 @@ function test() {
|
|||
testForgetThisSiteVisibility(1, function() {
|
||||
testForgetThisSiteVisibility(2, function() {
|
||||
// Cleanup
|
||||
history.QueryInterface(Ci.nsIBrowserHistory)
|
||||
.removeAllPages();
|
||||
finish();
|
||||
waitForClearHistory(finish);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ var bookmarksObserver = {
|
|||
},
|
||||
|
||||
// nsINavBookmarkObserver
|
||||
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex) {
|
||||
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex, aURI) {
|
||||
var node = null;
|
||||
var index = null;
|
||||
[node, index] = getNodeForTreeItem(aItemId, gLibrary.PlacesOrganizer._places);
|
||||
|
|
|
@ -223,7 +223,7 @@ var bookmarksObserver = {
|
|||
|
||||
// nsINavBookmarkObserver
|
||||
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex,
|
||||
aItemType) {
|
||||
aItemType, aURI) {
|
||||
var views = getViewsForFolder(aFolderId);
|
||||
ok(views.length > 0, "Found affected views (" + views.length + "): " + views);
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ var observer = {
|
|||
onEndUpdateBatch: function() {
|
||||
this._endUpdateBatch = true;
|
||||
},
|
||||
onItemAdded: function(id, folder, index, itemType) {
|
||||
onItemAdded: function(id, folder, index, itemType, uri) {
|
||||
this._itemAddedId = id;
|
||||
this._itemAddedParent = folder;
|
||||
this._itemAddedIndex = index;
|
||||
|
|
|
@ -762,6 +762,19 @@ var gCookiesWindow = {
|
|||
this._view._filterSet.reverse();
|
||||
}
|
||||
|
||||
// Adjust the Sort Indicator
|
||||
var domainCol = document.getElementById("domainCol");
|
||||
var nameCol = document.getElementById("nameCol");
|
||||
var sortOrderString = ascending ? "ascending" : "descending";
|
||||
if (aProperty == "rawHost") {
|
||||
domainCol.setAttribute("sortDirection", sortOrderString);
|
||||
nameCol.removeAttribute("sortDirection");
|
||||
}
|
||||
else {
|
||||
nameCol.setAttribute("sortDirection", sortOrderString);
|
||||
domainCol.removeAttribute("sortDirection");
|
||||
}
|
||||
|
||||
this._view._invalidateCache(0);
|
||||
this._view.selection.clearSelection();
|
||||
this._view.selection.select(0);
|
||||
|
|
|
@ -79,10 +79,10 @@
|
|||
hidecolumnpicker="true" seltype="single">
|
||||
<treecols>
|
||||
<treecol id="domainCol" label="&cookiedomain.label;" flex="2" primary="true"
|
||||
class="sortDirectionIndicator" persist="width" onclick="gCookiesWindow.sort('rawHost');" />
|
||||
persist="width" onclick="gCookiesWindow.sort('rawHost');"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="nameCol" label="&cookiename.label;" flex="1"
|
||||
class="sortDirectionIndicator" persist="width"
|
||||
persist="width"
|
||||
onclick="gCookiesWindow.sort('name');"/>
|
||||
</treecols>
|
||||
<treechildren id="cookiesChildren"/>
|
||||
|
|
|
@ -38,6 +38,24 @@
|
|||
// This test makes sure that the Forget This Site command is hidden in private
|
||||
// browsing mode.
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
|
||||
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
|
||||
}
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
|
@ -60,6 +78,7 @@ function test() {
|
|||
Services.ww.unregisterNotification(observer);
|
||||
let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
SimpleTest.waitForFocus(function() {
|
||||
executeSoon(function() {
|
||||
// Select History in the left pane.
|
||||
let PO = organizer.PlacesOrganizer;
|
||||
PO.selectLeftPaneQuery('History');
|
||||
|
@ -76,7 +95,7 @@ function test() {
|
|||
// Open the context menu
|
||||
let contextmenu = doc.getElementById("placesContext");
|
||||
contextmenu.addEventListener("popupshown", function() {
|
||||
contextmenu.removeEventListener("popupshown", arguments.callee, false);
|
||||
contextmenu.removeEventListener("popupshown", arguments.callee, true);
|
||||
let forgetThisSite = doc.getElementById("placesContext_deleteHost");
|
||||
is(forgetThisSite.hidden, !expected,
|
||||
"The Forget This Site menu item should " + (expected ? "not " : "") + "be hidden");
|
||||
|
@ -85,17 +104,27 @@ function test() {
|
|||
"The Forget This Site command should " + (expected ? "not " : "") + "be disabled");
|
||||
// Close the context menu
|
||||
contextmenu.hidePopup();
|
||||
// Wait for the Organizer window to actually be closed
|
||||
function closeObserver(aSubject, aTopic, aData) {
|
||||
if (aTopic != "domwindowclosed")
|
||||
return;
|
||||
Services.ww.unregisterNotification(closeObserver);
|
||||
SimpleTest.waitForFocus(function() {
|
||||
// Proceed
|
||||
funcNext();
|
||||
});
|
||||
}
|
||||
Services.ww.registerNotification(closeObserver);
|
||||
// Close Library window.
|
||||
organizer.close();
|
||||
// Proceed
|
||||
funcNext();
|
||||
}, false);
|
||||
}, true);
|
||||
// Get cell coordinates
|
||||
var x = {}, y = {}, width = {}, height = {};
|
||||
tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text",
|
||||
x, y, width, height);
|
||||
// Initiate a context menu for the selected cell
|
||||
EventUtils.synthesizeMouse(tree.body, x + 4, y + 4, {type: "contextmenu"}, organizer);
|
||||
EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, {type: "contextmenu"}, organizer);
|
||||
});
|
||||
}, organizer);
|
||||
}
|
||||
|
||||
|
@ -115,9 +144,7 @@ function test() {
|
|||
pb.privateBrowsingEnabled = false;
|
||||
testForgetThisSiteVisibility(true, function() {
|
||||
// Cleanup
|
||||
history.QueryInterface(Ci.nsIBrowserHistory)
|
||||
.removeAllPages();
|
||||
finish();
|
||||
waitForClearHistory(finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// This test makes sure that browsingmode attribute of the window is correctly
|
||||
// This test makes sure that privatebrowsingmode attribute of the window is correctly
|
||||
// switched with private browsing mode changes.
|
||||
|
||||
function test() {
|
||||
|
@ -45,20 +45,20 @@ function test() {
|
|||
getService(Ci.nsIPrivateBrowsingService);
|
||||
let docRoot = document.documentElement;
|
||||
|
||||
is(docRoot.getAttribute("browsingmode"), "normal",
|
||||
"browsingmode should be \"normal\" initially");
|
||||
ok(!docRoot.hasAttribute("privatebrowsingmode"),
|
||||
"privatebrowsingmode should not be present in normal mode");
|
||||
|
||||
// enter private browsing mode
|
||||
pb.privateBrowsingEnabled = true;
|
||||
|
||||
is(docRoot.getAttribute("browsingmode"), "private",
|
||||
"browsingmode should be \"private\" inside the private browsing mode");
|
||||
is(docRoot.getAttribute("privatebrowsingmode"), "temporary",
|
||||
"privatebrowsingmode should be \"temporary\" inside the private browsing mode");
|
||||
|
||||
// leave private browsing mode
|
||||
pb.privateBrowsingEnabled = false;
|
||||
|
||||
is(docRoot.getAttribute("browsingmode"), "normal",
|
||||
"browsingmode should be \"normal\" outside the private browsing mode");
|
||||
ok(!docRoot.hasAttribute("privatebrowsingmode"),
|
||||
"privatebrowsingmode should not be present in normal mode");
|
||||
|
||||
// cleanup
|
||||
gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
|
||||
|
|
|
@ -604,7 +604,8 @@
|
|||
label = this._stringBundle.getString("cmd_pasteAndSearch");
|
||||
element.setAttribute("label", label);
|
||||
element.setAttribute("anonid", "paste-and-search");
|
||||
element.setAttribute("oncommand", "goDoCommand('cmd_paste'); document.getElementById('searchbar').handleSearchCommand();");
|
||||
element.setAttribute("oncommand",
|
||||
"BrowserSearch.searchBar.value = ''; goDoCommand('cmd_paste'); BrowserSearch.searchBar.handleSearchCommand();");
|
||||
cxmenu.insertBefore(element, insertLocation.nextSibling);
|
||||
pasteAndSearch = element;
|
||||
}
|
||||
|
|
|
@ -45,8 +45,9 @@ include $(DEPTH)/config/autoconf.mk
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = browser_405664.js \
|
||||
browser_415700.js \
|
||||
browser_addEngine.js \
|
||||
testEngine.xml \
|
||||
testEngine.src \
|
||||
browser_426329.js \
|
||||
426329.xml \
|
||||
browser_483086.js \
|
||||
|
|
|
@ -1,85 +0,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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ryan Flint <rflint@dslr.net> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
var gSS = Services.search;
|
||||
|
||||
function observers(aSubject, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
test2();
|
||||
break;
|
||||
case "engine-current":
|
||||
test3();
|
||||
break;
|
||||
case "engine-removed":
|
||||
test4();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
Services.obs.addObserver(observers, "browser-search-engine-modified", false);
|
||||
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
}
|
||||
|
||||
function test2() {
|
||||
var engine = gSS.getEngineByName("Foo");
|
||||
ok(engine, "Engine was added.");
|
||||
|
||||
var aEngine = gSS.getEngineByAlias("fooalias");
|
||||
ok(!aEngine, "Alias was not parsed from engine description");
|
||||
|
||||
gSS.currentEngine = engine;
|
||||
}
|
||||
|
||||
function test3() {
|
||||
var engine = gSS.currentEngine;
|
||||
is(engine.name, "Foo", "Current engine was changed successfully");
|
||||
|
||||
gSS.removeEngine(engine);
|
||||
}
|
||||
|
||||
function test4() {
|
||||
var engine = gSS.currentEngine;
|
||||
ok(engine, "An engine is present.");
|
||||
isnot(engine.name, "Foo", "Current engine reset after removal");
|
||||
|
||||
Services.obs.removeObserver(observers, "browser-search-engine-modified");
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ryan Flint <rflint@dslr.net> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
var gSS = Services.search;
|
||||
|
||||
function observer(aSubject, aTopic, aData) {
|
||||
if (!gCurrentTest) {
|
||||
info("Observer called with no test active");
|
||||
return;
|
||||
}
|
||||
|
||||
let engine = aSubject.QueryInterface(Ci.nsISearchEngine);
|
||||
info("Observer: " + aData + " for " + engine.name);
|
||||
let method;
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
if (gCurrentTest.added)
|
||||
method = "added"
|
||||
break;
|
||||
case "engine-current":
|
||||
if (gCurrentTest.current)
|
||||
method = "current";
|
||||
break;
|
||||
case "engine-removed":
|
||||
if (gCurrentTest.removed)
|
||||
method = "removed";
|
||||
break;
|
||||
}
|
||||
|
||||
if (method)
|
||||
gCurrentTest[method](engine);
|
||||
}
|
||||
|
||||
function checkEngine(checkObj, engineObj) {
|
||||
info("Checking engine");
|
||||
for (var prop in checkObj)
|
||||
is(checkObj[prop], engineObj[prop], prop + " is correct");
|
||||
}
|
||||
|
||||
var gTests = [
|
||||
{
|
||||
name: "opensearch install",
|
||||
engine: {
|
||||
name: "Foo",
|
||||
alias: null,
|
||||
description: "Foo Search",
|
||||
searchForm: "http://mochi.test:8888/browser/browser/components/search/test/",
|
||||
type: Ci.nsISearchEngine.TYPE_OPENSEARCH
|
||||
},
|
||||
run: function () {
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
},
|
||||
added: function (engine) {
|
||||
ok(engine, "engine was added.");
|
||||
|
||||
checkEngine(this.engine, engine);
|
||||
|
||||
let engineFromSS = gSS.getEngineByName(this.engine.name);
|
||||
is(engine, engineFromSS, "engine is obtainable via getEngineByName");
|
||||
|
||||
let aEngine = gSS.getEngineByAlias("fooalias");
|
||||
ok(!aEngine, "Alias was not parsed from engine description");
|
||||
|
||||
gSS.currentEngine = engine;
|
||||
},
|
||||
current: function (engine) {
|
||||
let currentEngine = gSS.currentEngine;
|
||||
is(engine, currentEngine, "engine is current");
|
||||
is(engine.name, this.engine.name, "current engine was changed successfully");
|
||||
|
||||
gSS.removeEngine(engine);
|
||||
},
|
||||
removed: function (engine) {
|
||||
let currentEngine = gSS.currentEngine;
|
||||
ok(currentEngine, "An engine is present.");
|
||||
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
|
||||
|
||||
nextTest();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "sherlock install",
|
||||
engine: {
|
||||
name: "Test Sherlock",
|
||||
alias: null,
|
||||
description: "Test Description",
|
||||
searchForm: "http://example.com/searchform",
|
||||
type: Ci.nsISearchEngine.TYPE_SHERLOCK
|
||||
},
|
||||
run: function () {
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.src",
|
||||
Ci.nsISearchEngine.DATA_TEXT, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
},
|
||||
added: function (engine) {
|
||||
ok(engine, "engine was added.");
|
||||
checkEngine(this.engine, engine);
|
||||
|
||||
let engineFromSS = gSS.getEngineByName(this.engine.name);
|
||||
is(engineFromSS, engine, "engine is obtainable via getEngineByName");
|
||||
|
||||
gSS.removeEngine(engine);
|
||||
},
|
||||
removed: function (engine) {
|
||||
let currentEngine = gSS.currentEngine;
|
||||
ok(currentEngine, "An engine is present.");
|
||||
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
|
||||
|
||||
nextTest();
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var gCurrentTest = null;
|
||||
function nextTest() {
|
||||
if (gTests.length) {
|
||||
gCurrentTest = gTests.shift();
|
||||
info("Running " + gCurrentTest.name);
|
||||
gCurrentTest.run();
|
||||
} else
|
||||
executeSoon(finish);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
registerCleanupFunction(cleanup);
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<search
|
||||
name="Test Sherlock"
|
||||
description="Test Description"
|
||||
method="GET"
|
||||
searchform="http://example.com/searchform"
|
||||
action="http://example.com/action"
|
||||
queryCharset="UTF-8"
|
||||
>
|
||||
<input name="userParam" user>
|
||||
<input name="param" value="value">
|
||||
</search>
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
var gStateObject;
|
||||
var gTreeData;
|
||||
|
@ -54,13 +55,26 @@ window.onload = function() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
|
||||
if (sessionData.value.charAt(0) == '(')
|
||||
sessionData.value = sessionData.value.slice(1, -1);
|
||||
try {
|
||||
gStateObject = JSON.parse(sessionData.value);
|
||||
}
|
||||
catch (exJSON) {
|
||||
var s = new Cu.Sandbox("about:blank");
|
||||
gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
|
||||
// If we couldn't parse the string with JSON.parse originally, make sure
|
||||
// that the value in the textbox will be parsable.
|
||||
sessionData.value = JSON.stringify(gStateObject);
|
||||
}
|
||||
|
||||
// make sure the data is tracked to be restored in case of a subsequent crash
|
||||
var event = document.createEvent("UIEvents");
|
||||
event.initUIEvent("input", true, true, window, 0);
|
||||
sessionData.dispatchEvent(event);
|
||||
|
||||
gStateObject = JSON.parse(sessionData.value);
|
||||
|
||||
|
||||
initTreeView();
|
||||
|
||||
document.getElementById("errorTryAgain").focus();
|
||||
|
|
|
@ -1268,15 +1268,32 @@ SessionStoreService.prototype = {
|
|||
},
|
||||
|
||||
getTabValue: function sss_getTabValue(aTab, aKey) {
|
||||
var data = aTab.__SS_extdata || {};
|
||||
let data = {};
|
||||
if (aTab.__SS_extdata) {
|
||||
data = aTab.__SS_extdata;
|
||||
}
|
||||
else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
|
||||
// If the tab hasn't been fully restored, get the data from the to-be-restored data
|
||||
data = aTab.linkedBrowser.__SS_data.extData;
|
||||
}
|
||||
return data[aKey] || "";
|
||||
},
|
||||
|
||||
setTabValue: function sss_setTabValue(aTab, aKey, aStringValue) {
|
||||
if (!aTab.__SS_extdata) {
|
||||
aTab.__SS_extdata = {};
|
||||
// If the tab hasn't been restored, then set the data there, otherwise we
|
||||
// could lose newly added data.
|
||||
let saveTo;
|
||||
if (aTab.__SS_extdata) {
|
||||
saveTo = aTab.__SS_extdata;
|
||||
}
|
||||
aTab.__SS_extdata[aKey] = aStringValue;
|
||||
else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
|
||||
saveTo = aTab.linkedBrowser.__SS_data.extData;
|
||||
}
|
||||
else {
|
||||
aTab.__SS_extdata = {};
|
||||
saveTo = aTab.__SS_extdata;
|
||||
}
|
||||
saveTo[aKey] = aStringValue;
|
||||
this.saveStateDelayed(aTab.ownerDocument.defaultView);
|
||||
},
|
||||
|
||||
|
@ -1400,9 +1417,22 @@ SessionStoreService.prototype = {
|
|||
if (!browser || !browser.currentURI)
|
||||
// can happen when calling this function right after .addTab()
|
||||
return tabData;
|
||||
else if (browser.__SS_data && browser.__SS_data._tabStillLoading)
|
||||
else if (browser.__SS_data && browser.__SS_data._tabStillLoading) {
|
||||
// use the data to be restored when the tab hasn't been completely loaded
|
||||
return browser.__SS_data;
|
||||
tabData = browser.__SS_data;
|
||||
if (aTab.pinned)
|
||||
tabData.pinned = true;
|
||||
else
|
||||
delete tabData.pinned;
|
||||
if (browser.userTypedValue) {
|
||||
tabData.userTypedValue = browser.userTypedValue;
|
||||
tabData.userTypedClear = browser.userTypedClear;
|
||||
} else {
|
||||
delete tabData.userTypedValue;
|
||||
delete tabData.userTypedClear;
|
||||
}
|
||||
return tabData;
|
||||
}
|
||||
|
||||
var history = null;
|
||||
try {
|
||||
|
@ -1443,10 +1473,15 @@ SessionStoreService.prototype = {
|
|||
if (browser.userTypedValue) {
|
||||
tabData.userTypedValue = browser.userTypedValue;
|
||||
tabData.userTypedClear = browser.userTypedClear;
|
||||
} else {
|
||||
delete tabData.userTypedValue;
|
||||
delete tabData.userTypedClear;
|
||||
}
|
||||
|
||||
if (aTab.pinned)
|
||||
tabData.pinned = true;
|
||||
else
|
||||
delete tabData.pinned;
|
||||
tabData.hidden = aTab.hidden;
|
||||
|
||||
var disallow = [];
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче