зеркало из https://github.com/mozilla/gecko-dev.git
bug 417249, bug 417578, bug 405951, bug 413778, bug 412878. Fix missing, incorrect or crashing doc load events in Firefox and Thunderbird. r=surkov, a=blocking1.9
This commit is contained in:
Родитель
4bcebb89c2
Коммит
a48279000e
|
@ -44,8 +44,9 @@ interface nsIDocument;
|
|||
interface nsIFrame;
|
||||
interface nsObjectFrame;
|
||||
interface nsIContent;
|
||||
interface nsITimer;
|
||||
|
||||
[uuid(933f7472-cbe3-4d95-a77a-ce7ea3812b32)]
|
||||
[uuid(27386cf1-f27e-4d2d-9bf4-c4621d50d299)]
|
||||
interface nsIAccessibilityService : nsIAccessibleRetrieval
|
||||
{
|
||||
nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
|
||||
|
@ -100,6 +101,17 @@ interface nsIAccessibilityService : nsIAccessibleRetrieval
|
|||
void invalidateSubtreeFor(in nsIPresShell aPresShell,
|
||||
in nsIContent aChangedContent,
|
||||
in PRUint32 aEvent);
|
||||
|
||||
/**
|
||||
* An internal doc load event has occured. Handle the event and remove it from the list.
|
||||
* @param aTimer The timer created to handle this doc load event
|
||||
* @param aClosure The nsIWebProgress* for the load event
|
||||
* @param aEventType The type of load event, one of: nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START,
|
||||
* nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE or
|
||||
* nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED
|
||||
*/
|
||||
void processDocLoadEvent(in nsITimer aTimer, in voidPtr aClosure, in PRUint32 aEventType);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -95,6 +95,9 @@ nsApplicationAccessibleWrap *nsAccessNode::gApplicationAccessible = nsnull;
|
|||
nsIAccessibilityService *nsAccessNode::sAccService = nsnull;
|
||||
nsIAccessibilityService *nsAccessNode::GetAccService()
|
||||
{
|
||||
if (!gIsAccessibilityActive)
|
||||
return nsnull;
|
||||
|
||||
if (!sAccService) {
|
||||
nsresult rv = CallGetService("@mozilla.org/accessibilityService;1",
|
||||
&sAccService);
|
||||
|
@ -315,7 +318,7 @@ void nsAccessNode::ShutdownXPAccessibility()
|
|||
NS_IF_RELEASE(sAccService);
|
||||
|
||||
nsApplicationAccessibleWrap::Unload();
|
||||
ClearCache(gGlobalDocAccessibleCache);
|
||||
gGlobalDocAccessibleCache.Enumerate(ClearDocCacheEntry, nsnull);
|
||||
|
||||
// Release gApplicationAccessible after everything else is shutdown
|
||||
// so we don't accidently create it again while tearing down root accessibles
|
||||
|
@ -791,6 +794,14 @@ PLDHashOperator nsAccessNode::ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAcce
|
|||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
PLDHashOperator nsAccessNode::ClearDocCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg)
|
||||
{
|
||||
nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(aAccessNode));
|
||||
privateAccessNode->Shutdown();
|
||||
|
||||
return PL_DHASH_NEXT; // nsDocAccessible::Shutdown() removes the doc from doc cache
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessNode::ClearCache(nsAccessNodeHashtable& aCache)
|
||||
{
|
||||
|
|
|
@ -98,6 +98,7 @@ class nsAccessNode: public nsIAccessNode, public nsPIAccessNode
|
|||
static void ClearCache(nsAccessNodeHashtable& aCache);
|
||||
|
||||
static PLDHashOperator PR_CALLBACK ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
|
||||
static PLDHashOperator PR_CALLBACK ClearDocCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
|
||||
|
||||
// Static cache methods for global document cache
|
||||
static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDocument *aDocument);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccessibilityUtils.h"
|
||||
#include "nsARIAMap.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsCURILoader.h"
|
||||
#include "nsDocAccessible.h"
|
||||
#include "nsHTMLImageAccessibleWrap.h"
|
||||
|
@ -155,10 +156,21 @@ nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
|
|||
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
}
|
||||
nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
|
||||
if (progress) {
|
||||
if (progress)
|
||||
progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
|
||||
}
|
||||
nsAccessNodeWrap::ShutdownAccessibility();
|
||||
// Cancel and release load timers
|
||||
while (mLoadTimers.Count() > 0 ) {
|
||||
nsCOMPtr<nsITimer> timer = mLoadTimers.ObjectAt(0);
|
||||
void *closure = nsnull;
|
||||
timer->GetClosure(&closure);
|
||||
if (closure) {
|
||||
nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(closure);
|
||||
NS_RELEASE(webProgress); // Release nsIWebProgress for timer
|
||||
}
|
||||
timer->Cancel();
|
||||
mLoadTimers.RemoveObjectAt(0);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -169,70 +181,94 @@ NS_IMETHODIMP nsAccessibilityService::OnStateChange(nsIWebProgress *aWebProgress
|
|||
{
|
||||
NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
|
||||
|
||||
if (0 == (aStateFlags & (STATE_START | STATE_STOP))) {
|
||||
if (!aWebProgress || 0 == (aStateFlags & (STATE_START | STATE_STOP))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCAutoString name;
|
||||
aRequest->GetName(name);
|
||||
if (name.EqualsLiteral("about:blank"))
|
||||
return NS_OK;
|
||||
|
||||
if (NS_FAILED(aStatus) && (aStateFlags & STATE_START))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (!timer)
|
||||
return NS_OK;
|
||||
mLoadTimers.AppendObject(timer);
|
||||
NS_ADDREF(aWebProgress);
|
||||
|
||||
if (aStateFlags & STATE_START)
|
||||
timer->InitWithFuncCallback(StartLoadCallback, aWebProgress, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
else if (NS_SUCCEEDED(aStatus))
|
||||
timer->InitWithFuncCallback(EndLoadCallback, aWebProgress, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
else // Failed end load
|
||||
timer->InitWithFuncCallback(FailedLoadCallback, aWebProgress, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::ProcessDocLoadEvent(nsITimer *aTimer, void *aClosure, PRUint32 aEventType)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> domWindow;
|
||||
aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
|
||||
NS_ASSERTION(domWindow, "DOM Window for state change is null");
|
||||
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
|
||||
nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(aClosure);
|
||||
webProgress->GetDOMWindow(getter_AddRefs(domWindow));
|
||||
NS_RELEASE(webProgress);
|
||||
mLoadTimers.RemoveObject(aTimer);
|
||||
NS_ENSURE_STATE(domWindow);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
domWindow->GetDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDOMNode> domDocNode(do_QueryInterface(domDoc));
|
||||
NS_ENSURE_TRUE(domDocNode, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIAccessibleDocument> docAccessible;
|
||||
|
||||
PRUint32 eventType = 0;
|
||||
if (aStateFlags & STATE_STOP) {
|
||||
// Do not create accessible for page load end events
|
||||
// in case it was already shut down before page finished loading
|
||||
docAccessible = nsAccessNode::GetDocAccessibleFor(domDocNode); // Cached doc accessibles only
|
||||
if (!docAccessible)
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIDOMDocument> domDocTest;
|
||||
docAccessible->GetDocument(getter_AddRefs(domDocTest));
|
||||
if (domDocTest != domDoc) {
|
||||
// Doc from accessible is not the doc we started from
|
||||
// We must be shutdown, and domDocTest should be null
|
||||
NS_ASSERTION(!domDocTest, "Doc not shut down but reports incorrect DOM document");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
eventType = NS_FAILED(aStatus) ? nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED :
|
||||
nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE;
|
||||
}
|
||||
else {
|
||||
// Get the accessible for the new document.
|
||||
// If it not created yet this will create it & cache it, as well as
|
||||
// set up event listeners so that MSAA/ATK toolkit and internal
|
||||
// accessibility events will get fired.
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
GetAccessibleFor(domDocNode, getter_AddRefs(accessible)); // Create if necessary
|
||||
docAccessible = do_QueryInterface(accessible);
|
||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START;
|
||||
if (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START) {
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(domWindow));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_STATE(docShell);
|
||||
PRUint32 loadType;
|
||||
docShell->GetLoadType(&loadType);
|
||||
if (loadType == LOAD_RELOAD_NORMAL ||
|
||||
loadType == LOAD_RELOAD_BYPASS_CACHE ||
|
||||
loadType == LOAD_RELOAD_BYPASS_PROXY ||
|
||||
loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
|
||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
|
||||
aEventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIAccessibleDocument> privDocAccessible = do_QueryInterface(docAccessible);
|
||||
if (eventType && privDocAccessible) {
|
||||
privDocAccessible->FireDocLoadEvents(eventType);
|
||||
}
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
domWindow->GetDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDOMNode> docNode = do_QueryInterface(domDoc);
|
||||
NS_ENSURE_STATE(docNode);
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
GetAccessibleFor(docNode, getter_AddRefs(accessible));
|
||||
nsCOMPtr<nsPIAccessibleDocument> privDocAccessible = do_QueryInterface(accessible);
|
||||
NS_ENSURE_STATE(privDocAccessible);
|
||||
privDocAccessible->FireDocLoadEvents(aEventType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsAccessibilityService::StartLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsIAccessibilityService *accService = nsAccessNode::GetAccService();
|
||||
if (accService)
|
||||
accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START);
|
||||
}
|
||||
|
||||
void nsAccessibilityService::EndLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsIAccessibilityService *accService = nsAccessNode::GetAccService();
|
||||
if (accService)
|
||||
accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
|
||||
}
|
||||
|
||||
void nsAccessibilityService::FailedLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsIAccessibilityService *accService = nsAccessNode::GetAccService();
|
||||
if (accService)
|
||||
accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
|
||||
}
|
||||
|
||||
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
|
||||
NS_IMETHODIMP nsAccessibilityService::OnProgressChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
|
||||
|
@ -378,6 +414,12 @@ nsAccessibilityService::CreateRootAccessible(nsIPresShell *aShell,
|
|||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
||||
|
||||
nsCOMPtr<nsISupports> container = aDocument->GetContainer();
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||
docShell->GetContentViewer(getter_AddRefs(contentViewer));
|
||||
NS_ENSURE_TRUE(contentViewer, NS_ERROR_FAILURE); // Doc was already shut down
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
|
||||
do_QueryInterface(container);
|
||||
NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
|
||||
|
|
|
@ -40,7 +40,10 @@
|
|||
#define __nsAccessibilityService_h__
|
||||
|
||||
#include "nsIAccessibilityService.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
|
@ -135,6 +138,11 @@ private:
|
|||
* @return PR_TRUE if there is a universal ARIA property set on the node
|
||||
*/
|
||||
PRBool HasUniversalAriaProperty(nsIContent *aContent, nsIWeakReference *aWeakShell);
|
||||
|
||||
static void StartLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
static void EndLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
static void FailedLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
nsCOMArray<nsITimer> mLoadTimers;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -78,11 +78,14 @@ void nsCaretAccessible::Shutdown()
|
|||
|
||||
nsresult nsCaretAccessible::ClearControlSelectionListener()
|
||||
{
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
mCurrentControlSelection = nsnull;
|
||||
mCurrentControl = nsnull;
|
||||
mCurrentControlSelection = nsnull;
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
||||
if (!selPrivate) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return selPrivate->RemoveSelectionListener(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -526,17 +526,13 @@ NS_IMETHODIMP nsDocAccessible::Shutdown()
|
|||
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
||||
ShutdownChildDocuments(treeItem);
|
||||
|
||||
if (mDocLoadTimer) {
|
||||
mDocLoadTimer->Cancel();
|
||||
mDocLoadTimer = nsnull;
|
||||
}
|
||||
|
||||
RemoveEventListeners();
|
||||
|
||||
mWeakShell = nsnull; // Avoid reentrancy
|
||||
|
||||
ClearCache(mAccessNodeCache);
|
||||
|
||||
nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
|
||||
mDocument = nsnull;
|
||||
|
||||
nsHyperTextAccessibleWrap::Shutdown();
|
||||
|
@ -553,6 +549,10 @@ NS_IMETHODIMP nsDocAccessible::Shutdown()
|
|||
}
|
||||
}
|
||||
|
||||
// Remove from the cache after other parts of Shutdown(), so that Shutdown() procedures
|
||||
// can find the doc or root accessible in the cache if they need it.
|
||||
gGlobalDocAccessibleCache.Remove(static_cast<void*>(kungFuDeathGripDoc));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -771,6 +771,14 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
|||
}
|
||||
mIsContentLoaded = isFinished;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
||||
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
||||
if (!treeItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
|
||||
if (isFinished) {
|
||||
// Need to wait until scrollable view is available
|
||||
AddScrollListener();
|
||||
|
@ -780,36 +788,31 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
|||
// Make the parent forget about the old document as a child
|
||||
privateAccessible->InvalidateChildren();
|
||||
}
|
||||
// Use short timer before firing state change event for finished doc,
|
||||
// because the window is made visible asynchronously
|
||||
if (!mDocLoadTimer) {
|
||||
mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
}
|
||||
if (mDocLoadTimer) {
|
||||
mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
||||
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
||||
if (!treeItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
if (sameTypeRoot != treeItem) {
|
||||
return NS_OK;
|
||||
// Fire show/hide events to indicate frame/iframe content is new, rather than
|
||||
// doc load event which causes screen readers to act is if entire page is reloaded
|
||||
InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
|
||||
}
|
||||
|
||||
// Loading document: fire EVENT_STATE_CHANGE to set STATE_BUSY
|
||||
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
||||
new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY,
|
||||
PR_FALSE, PR_TRUE);
|
||||
FireAccessibleEvent(accEvent);
|
||||
}
|
||||
|
||||
nsAccUtils::FireAccEvent(aEventType, this);
|
||||
// Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
|
||||
if (gLastFocusedNode) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
|
||||
nsAccUtils::GetDocShellTreeItemFor(gLastFocusedNode);
|
||||
if (focusedTreeItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
|
||||
focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
|
||||
if (sameTypeRoot == sameTypeRootOfFocus) {
|
||||
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
||||
new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY, PR_FALSE, PR_FALSE);
|
||||
FireAccessibleEvent(accEvent);
|
||||
FireAnchorJumpEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sameTypeRoot == treeItem) {
|
||||
// Not a frame or iframe
|
||||
nsAccUtils::FireAccEvent(aEventType, this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2067,55 +2070,3 @@ nsDocAccessible::FireShowHideEvents(nsIDOMNode *aDOMNode, PRBool aAvoidOnThisNod
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsDocAccessible::DocLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
// Doc has finished loading, fire "load finished" event
|
||||
// By using short timer we can wait make the window visible,
|
||||
// which it does asynchronously. This avoids confusing the screen reader with a
|
||||
// hidden window. Waiting also allows us to see of the document has focus,
|
||||
// which is important because we only fire doc loaded events for focused documents.
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
reinterpret_cast<nsDocAccessible*>(aClosure);
|
||||
if (!docAcc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire doc finished event
|
||||
nsCOMPtr<nsIDOMNode> docDomNode;
|
||||
docAcc->GetDOMNode(getter_AddRefs(docDomNode));
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(docDomNode));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsISupports> container = doc->GetContainer();
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
|
||||
if (!docShellTreeItem) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
if (sameTypeRoot != docShellTreeItem) {
|
||||
// A frame or iframe has finished loading new content
|
||||
docAcc->InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
|
||||
if (gLastFocusedNode) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
|
||||
nsAccUtils::GetDocShellTreeItemFor(gLastFocusedNode);
|
||||
if (focusedTreeItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
|
||||
focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
|
||||
if (sameTypeRoot == sameTypeRootOfFocus) {
|
||||
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
||||
new nsAccStateChangeEvent(docAcc, nsIAccessibleStates::STATE_BUSY,
|
||||
PR_FALSE, PR_FALSE);
|
||||
docAcc->FireAccessibleEvent(accEvent);
|
||||
docAcc->FireAnchorJumpEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -221,10 +221,6 @@ protected:
|
|||
PRBool mIsAnchorJumped;
|
||||
static PRUint32 gLastFocusedAccessiblesState;
|
||||
static nsIAtom *gLastFocusedFrameType;
|
||||
|
||||
private:
|
||||
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
nsCOMPtr<nsITimer> mDocLoadTimer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -406,29 +406,11 @@ void nsRootAccessible::TryFireEarlyLoadEvent(nsIDOMNode *aDocNode)
|
|||
nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem));
|
||||
NS_ASSERTION(rootContentTreeItem, "No root content tree item");
|
||||
if (!rootContentTreeItem) { // Not at root of content
|
||||
return;
|
||||
if (rootContentTreeItem == treeItem) {
|
||||
// No frames or iframes, so we can fire the doc load finished event early
|
||||
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode,
|
||||
eRemoveDupes);
|
||||
}
|
||||
if (rootContentTreeItem != treeItem) {
|
||||
nsCOMPtr<nsIAccessibleDocument> rootContentDocAccessible =
|
||||
GetDocAccessibleFor(rootContentTreeItem);
|
||||
nsCOMPtr<nsIAccessible> rootContentAccessible =
|
||||
do_QueryInterface(rootContentDocAccessible);
|
||||
if (!rootContentAccessible) {
|
||||
return;
|
||||
}
|
||||
PRUint32 state, extState;
|
||||
rootContentAccessible->GetFinalState(&state, &extState);
|
||||
if ((state & nsIAccessibleStates::STATE_BUSY) ||
|
||||
(extState & nsIAccessibleStates::EXT_STATE_DEFUNCT)) {
|
||||
// Don't fire page load events on subdocuments for initial page load of entire page
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No frames or iframes, so we can fire the doc load finished event early
|
||||
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode,
|
||||
eRemoveDupes);
|
||||
}
|
||||
|
||||
PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
|
||||
|
@ -632,9 +614,6 @@ nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
|
|||
nsCOMPtr<nsPIAccessNode> privateAcc = do_QueryInterface(accDoc);
|
||||
if (privateAcc) {
|
||||
privateAcc->Shutdown();
|
||||
// Remove from the cache after Shutdown(), so that Shutdown() procedures
|
||||
// can find the doc or root accessible in the cache if they need it.
|
||||
gGlobalDocAccessibleCache.Remove(static_cast<void*>(doc));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -162,11 +162,6 @@ __try {
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocAccessibleWrap::Shutdown()
|
||||
{
|
||||
return nsDocAccessible::Shutdown();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
|
||||
{
|
||||
// Staying on the same page, jumping to a named anchor
|
||||
|
|
|
@ -87,7 +87,6 @@ public:
|
|||
/* [in] */ VARIANT varChild,
|
||||
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
|
||||
|
||||
NS_IMETHOD Shutdown();
|
||||
NS_IMETHOD FireAnchorJumpEvent();
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче