mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
ea95d72bfc
commit
c1cebef426
@ -44,8 +44,9 @@ interface nsIDocument;
|
|||||||
interface nsIFrame;
|
interface nsIFrame;
|
||||||
interface nsObjectFrame;
|
interface nsObjectFrame;
|
||||||
interface nsIContent;
|
interface nsIContent;
|
||||||
|
interface nsITimer;
|
||||||
|
|
||||||
[uuid(933f7472-cbe3-4d95-a77a-ce7ea3812b32)]
|
[uuid(27386cf1-f27e-4d2d-9bf4-c4621d50d299)]
|
||||||
interface nsIAccessibilityService : nsIAccessibleRetrieval
|
interface nsIAccessibilityService : nsIAccessibleRetrieval
|
||||||
{
|
{
|
||||||
nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
|
nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
|
||||||
@ -100,6 +101,17 @@ interface nsIAccessibilityService : nsIAccessibleRetrieval
|
|||||||
void invalidateSubtreeFor(in nsIPresShell aPresShell,
|
void invalidateSubtreeFor(in nsIPresShell aPresShell,
|
||||||
in nsIContent aChangedContent,
|
in nsIContent aChangedContent,
|
||||||
in PRUint32 aEvent);
|
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::sAccService = nsnull;
|
||||||
nsIAccessibilityService *nsAccessNode::GetAccService()
|
nsIAccessibilityService *nsAccessNode::GetAccService()
|
||||||
{
|
{
|
||||||
|
if (!gIsAccessibilityActive)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
if (!sAccService) {
|
if (!sAccService) {
|
||||||
nsresult rv = CallGetService("@mozilla.org/accessibilityService;1",
|
nsresult rv = CallGetService("@mozilla.org/accessibilityService;1",
|
||||||
&sAccService);
|
&sAccService);
|
||||||
@ -315,7 +318,7 @@ void nsAccessNode::ShutdownXPAccessibility()
|
|||||||
NS_IF_RELEASE(sAccService);
|
NS_IF_RELEASE(sAccService);
|
||||||
|
|
||||||
nsApplicationAccessibleWrap::Unload();
|
nsApplicationAccessibleWrap::Unload();
|
||||||
ClearCache(gGlobalDocAccessibleCache);
|
gGlobalDocAccessibleCache.Enumerate(ClearDocCacheEntry, nsnull);
|
||||||
|
|
||||||
// Release gApplicationAccessible after everything else is shutdown
|
// Release gApplicationAccessible after everything else is shutdown
|
||||||
// so we don't accidently create it again while tearing down root accessibles
|
// 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;
|
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
|
void
|
||||||
nsAccessNode::ClearCache(nsAccessNodeHashtable& aCache)
|
nsAccessNode::ClearCache(nsAccessNodeHashtable& aCache)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +98,7 @@ class nsAccessNode: public nsIAccessNode, public nsPIAccessNode
|
|||||||
static void ClearCache(nsAccessNodeHashtable& aCache);
|
static void ClearCache(nsAccessNodeHashtable& aCache);
|
||||||
|
|
||||||
static PLDHashOperator PR_CALLBACK ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
|
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 cache methods for global document cache
|
||||||
static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDocument *aDocument);
|
static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDocument *aDocument);
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "nsAccessibilityService.h"
|
#include "nsAccessibilityService.h"
|
||||||
#include "nsAccessibilityUtils.h"
|
#include "nsAccessibilityUtils.h"
|
||||||
#include "nsARIAMap.h"
|
#include "nsARIAMap.h"
|
||||||
|
#include "nsIContentViewer.h"
|
||||||
#include "nsCURILoader.h"
|
#include "nsCURILoader.h"
|
||||||
#include "nsDocAccessible.h"
|
#include "nsDocAccessible.h"
|
||||||
#include "nsHTMLImageAccessibleWrap.h"
|
#include "nsHTMLImageAccessibleWrap.h"
|
||||||
@ -155,10 +156,21 @@ nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
|
|||||||
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
|
nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
|
||||||
if (progress) {
|
if (progress)
|
||||||
progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
|
progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
|
||||||
}
|
|
||||||
nsAccessNodeWrap::ShutdownAccessibility();
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -169,70 +181,94 @@ NS_IMETHODIMP nsAccessibilityService::OnStateChange(nsIWebProgress *aWebProgress
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
|
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;
|
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;
|
nsCOMPtr<nsIDOMWindow> domWindow;
|
||||||
aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
|
nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(aClosure);
|
||||||
NS_ASSERTION(domWindow, "DOM Window for state change is null");
|
webProgress->GetDOMWindow(getter_AddRefs(domWindow));
|
||||||
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
|
NS_RELEASE(webProgress);
|
||||||
|
mLoadTimers.RemoveObject(aTimer);
|
||||||
|
NS_ENSURE_STATE(domWindow);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
if (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START) {
|
||||||
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;
|
|
||||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(domWindow));
|
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(domWindow));
|
||||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
|
||||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
NS_ENSURE_STATE(docShell);
|
||||||
PRUint32 loadType;
|
PRUint32 loadType;
|
||||||
docShell->GetLoadType(&loadType);
|
docShell->GetLoadType(&loadType);
|
||||||
if (loadType == LOAD_RELOAD_NORMAL ||
|
if (loadType == LOAD_RELOAD_NORMAL ||
|
||||||
loadType == LOAD_RELOAD_BYPASS_CACHE ||
|
loadType == LOAD_RELOAD_BYPASS_CACHE ||
|
||||||
loadType == LOAD_RELOAD_BYPASS_PROXY ||
|
loadType == LOAD_RELOAD_BYPASS_PROXY ||
|
||||||
loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
|
loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
|
||||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
|
aEventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsPIAccessibleDocument> privDocAccessible = do_QueryInterface(docAccessible);
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||||
if (eventType && privDocAccessible) {
|
domWindow->GetDocument(getter_AddRefs(domDoc));
|
||||||
privDocAccessible->FireDocLoadEvents(eventType);
|
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;
|
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); */
|
/* 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,
|
NS_IMETHODIMP nsAccessibilityService::OnProgressChange(nsIWebProgress *aWebProgress,
|
||||||
nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
|
nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
|
||||||
@ -378,6 +414,12 @@ nsAccessibilityService::CreateRootAccessible(nsIPresShell *aShell,
|
|||||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> container = aDocument->GetContainer();
|
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 =
|
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
|
||||||
do_QueryInterface(container);
|
do_QueryInterface(container);
|
||||||
NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
|
||||||
|
@ -40,7 +40,10 @@
|
|||||||
#define __nsAccessibilityService_h__
|
#define __nsAccessibilityService_h__
|
||||||
|
|
||||||
#include "nsIAccessibilityService.h"
|
#include "nsIAccessibilityService.h"
|
||||||
|
#include "nsCOMArray.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
|
#include "nsIWebProgress.h"
|
||||||
#include "nsIWebProgressListener.h"
|
#include "nsIWebProgressListener.h"
|
||||||
#include "nsWeakReference.h"
|
#include "nsWeakReference.h"
|
||||||
|
|
||||||
@ -135,6 +138,11 @@ private:
|
|||||||
* @return PR_TRUE if there is a universal ARIA property set on the node
|
* @return PR_TRUE if there is a universal ARIA property set on the node
|
||||||
*/
|
*/
|
||||||
PRBool HasUniversalAriaProperty(nsIContent *aContent, nsIWeakReference *aWeakShell);
|
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()
|
nsresult nsCaretAccessible::ClearControlSelectionListener()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
|
||||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
mCurrentControlSelection = nsnull;
|
|
||||||
mCurrentControl = nsnull;
|
mCurrentControl = nsnull;
|
||||||
|
mCurrentControlSelection = nsnull;
|
||||||
|
|
||||||
|
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
||||||
|
if (!selPrivate) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return selPrivate->RemoveSelectionListener(this);
|
return selPrivate->RemoveSelectionListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,17 +526,13 @@ NS_IMETHODIMP nsDocAccessible::Shutdown()
|
|||||||
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
||||||
ShutdownChildDocuments(treeItem);
|
ShutdownChildDocuments(treeItem);
|
||||||
|
|
||||||
if (mDocLoadTimer) {
|
|
||||||
mDocLoadTimer->Cancel();
|
|
||||||
mDocLoadTimer = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveEventListeners();
|
RemoveEventListeners();
|
||||||
|
|
||||||
mWeakShell = nsnull; // Avoid reentrancy
|
mWeakShell = nsnull; // Avoid reentrancy
|
||||||
|
|
||||||
ClearCache(mAccessNodeCache);
|
ClearCache(mAccessNodeCache);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
|
||||||
mDocument = nsnull;
|
mDocument = nsnull;
|
||||||
|
|
||||||
nsHyperTextAccessibleWrap::Shutdown();
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,6 +771,14 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
|||||||
}
|
}
|
||||||
mIsContentLoaded = isFinished;
|
mIsContentLoaded = isFinished;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
||||||
|
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
||||||
|
if (!treeItem) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||||
|
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||||
|
|
||||||
if (isFinished) {
|
if (isFinished) {
|
||||||
// Need to wait until scrollable view is available
|
// Need to wait until scrollable view is available
|
||||||
AddScrollListener();
|
AddScrollListener();
|
||||||
@ -780,36 +788,31 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
|||||||
// Make the parent forget about the old document as a child
|
// Make the parent forget about the old document as a child
|
||||||
privateAccessible->InvalidateChildren();
|
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) {
|
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);
|
|
||||||
}
|
}
|
||||||
|
// Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
|
||||||
nsAccUtils::FireAccEvent(aEventType, this);
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2067,55 +2070,3 @@ nsDocAccessible::FireShowHideEvents(nsIDOMNode *aDOMNode, PRBool aAvoidOnThisNod
|
|||||||
|
|
||||||
return NS_OK;
|
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;
|
PRBool mIsAnchorJumped;
|
||||||
static PRUint32 gLastFocusedAccessiblesState;
|
static PRUint32 gLastFocusedAccessiblesState;
|
||||||
static nsIAtom *gLastFocusedFrameType;
|
static nsIAtom *gLastFocusedFrameType;
|
||||||
|
|
||||||
private:
|
|
||||||
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
|
|
||||||
nsCOMPtr<nsITimer> mDocLoadTimer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -406,29 +406,11 @@ void nsRootAccessible::TryFireEarlyLoadEvent(nsIDOMNode *aDocNode)
|
|||||||
nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem;
|
nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem;
|
||||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem));
|
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem));
|
||||||
NS_ASSERTION(rootContentTreeItem, "No root content tree item");
|
NS_ASSERTION(rootContentTreeItem, "No root content tree item");
|
||||||
if (!rootContentTreeItem) { // Not at root of content
|
if (rootContentTreeItem == treeItem) {
|
||||||
return;
|
// 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,
|
PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
|
||||||
@ -632,9 +614,6 @@ nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
|
|||||||
nsCOMPtr<nsPIAccessNode> privateAcc = do_QueryInterface(accDoc);
|
nsCOMPtr<nsPIAccessNode> privateAcc = do_QueryInterface(accDoc);
|
||||||
if (privateAcc) {
|
if (privateAcc) {
|
||||||
privateAcc->Shutdown();
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -162,11 +162,6 @@ __try {
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsDocAccessibleWrap::Shutdown()
|
|
||||||
{
|
|
||||||
return nsDocAccessible::Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
|
NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
|
||||||
{
|
{
|
||||||
// Staying on the same page, jumping to a named anchor
|
// Staying on the same page, jumping to a named anchor
|
||||||
|
@ -87,7 +87,6 @@ public:
|
|||||||
/* [in] */ VARIANT varChild,
|
/* [in] */ VARIANT varChild,
|
||||||
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
|
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
|
||||||
|
|
||||||
NS_IMETHOD Shutdown();
|
|
||||||
NS_IMETHOD FireAnchorJumpEvent();
|
NS_IMETHOD FireAnchorJumpEvent();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user