mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 166504. Crash when closing down with accessibility running because of late object release from third party apps. r=jgaunt, sr=jst, a=dbaron
This commit is contained in:
parent
6f89b182bd
commit
7da68e788f
@ -97,6 +97,7 @@ interface nsIAccessibilityService : nsISupports
|
||||
nsIAccessible createXULTooltipAccessible(in nsIDOMNode aNode);
|
||||
|
||||
nsIAccessible getAccessibleFor(in nsIDOMNode aNode);
|
||||
void Shutdown();
|
||||
};
|
||||
|
||||
|
||||
|
@ -101,14 +101,14 @@
|
||||
* nsAccessibility Service
|
||||
*/
|
||||
|
||||
nsAccessibilityService::nsAccessibilityService()
|
||||
nsAccessibilityService::nsAccessibilityService():mIsActive(PR_TRUE)
|
||||
{
|
||||
nsLayoutAtoms::AddRefAtoms();
|
||||
}
|
||||
|
||||
nsAccessibilityService::~nsAccessibilityService()
|
||||
{
|
||||
nsLayoutAtoms::ReleaseAtoms();
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsAccessibilityService, nsIAccessibilityService);
|
||||
@ -231,6 +231,16 @@ nsAccessibilityService::GetShellFromNode(nsIDOMNode *aNode, nsIWeakReference **a
|
||||
* nsIAccessibilityService methods:
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::Shutdown()
|
||||
{
|
||||
if (mIsActive) {
|
||||
nsLayoutAtoms::ReleaseAtoms();
|
||||
mIsActive = PR_FALSE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccessibilityService::CreateAccessible(nsIDOMNode* aDOMNode, nsISupports* aDocument, nsIAccessible **_retval)
|
||||
{
|
||||
|
@ -67,6 +67,7 @@ private:
|
||||
nsresult GetInfo(nsISupports* aFrame, nsIFrame** aRealFrame, nsIWeakReference** aShell, nsIDOMNode** aContent);
|
||||
void GetOwnerFor(nsIPresShell *aPresShell, nsIPresShell **aOwnerShell, nsIContent **aOwnerContent);
|
||||
nsIContent* FindContentForDocShell(nsIPresShell* aPresShell, nsIContent* aContent, nsIDocShell* aDocShell);
|
||||
PRBool mIsActive;
|
||||
};
|
||||
|
||||
#endif /* __nsIAccessibilityService_h__ */
|
||||
|
@ -419,6 +419,9 @@ NS_IMETHODIMP nsRootAccessible::RemoveAccessibleEventListener()
|
||||
mCaretAccessible->RemoveSelectionListener();
|
||||
mCaretAccessible = nsnull;
|
||||
}
|
||||
|
||||
mAccService = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,10 @@
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsWindow.h"
|
||||
#include "String.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIAccessibilityService.h"
|
||||
|
||||
// for the COM IEnumVARIANT solution in get_AccSelection()
|
||||
#define _ATLBASE_IMPL
|
||||
@ -79,6 +81,7 @@ static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
|
||||
PRInt32 RootAccessible::gListCount = 0;
|
||||
PRInt32 RootAccessible::gNextPos = 0;
|
||||
PRInt32 RootAccessible::gActiveRootAccessibles = 0;
|
||||
nsAccessibleEventMap RootAccessible::gList[MAX_LIST_SIZE];
|
||||
PRBool Accessible::gIsCacheDisabled = PR_FALSE;
|
||||
PRBool Accessible::gIsEnumVariantSupportDisabled = PR_FALSE;
|
||||
@ -104,7 +107,6 @@ Accessible::Accessible(nsIAccessible* aXPAccessible, nsIDOMNode* aNode, HWND aWn
|
||||
|
||||
// Inherited from SimpleDOMNode
|
||||
mWnd = aWnd; // The window handle, for NotifyWinEvent, or getting the accessible parent thru the window parent
|
||||
m_cRef = 0; // for reference counting, so we know when to delete ourselves
|
||||
|
||||
#ifdef DEBUG_LEAKS
|
||||
printf("Accessibles=%d\n", ++gAccessibles);
|
||||
@ -117,13 +119,14 @@ Accessible::Accessible(nsIAccessible* aXPAccessible, nsIDOMNode* aNode, HWND aWn
|
||||
//-----------------------------------------------------
|
||||
Accessible::~Accessible()
|
||||
{
|
||||
m_cRef = 0;
|
||||
mXPAccessible = nsnull;
|
||||
if (mCachedNextSibling) {
|
||||
mCachedNextSibling->Release();
|
||||
mCachedNextSibling = nsnull;
|
||||
}
|
||||
if (mCachedFirstChild) {
|
||||
mCachedFirstChild->Release();
|
||||
mCachedFirstChild = nsnull;
|
||||
}
|
||||
#ifdef DEBUG_LEAKS
|
||||
printf("Accessibles=%d\n", --gAccessibles);
|
||||
@ -936,10 +939,10 @@ void Accessible::GetNSAccessibleFor(VARIANT varChild, nsCOMPtr<nsIAccessible>& a
|
||||
aXPAccessible = mXPAccessible;
|
||||
}
|
||||
else {
|
||||
// XXX aaronl
|
||||
// I can't find anything that uses VARIANT with a child num
|
||||
// so let's not worry about optimizing this.
|
||||
NS_NOTREACHED("MSAA VARIANT with child number being used");
|
||||
// XXX It is rare to use a VARIANT with a child num
|
||||
// so optimizing this is not a priority
|
||||
// We can come back it do it later, if there are perf problems
|
||||
// with a specific assistive technology
|
||||
nsCOMPtr<nsIAccessible> xpAccessible;
|
||||
mXPAccessible->GetAccFirstChild(getter_AddRefs(xpAccessible));
|
||||
for (PRInt32 index = 0; xpAccessible; index ++) {
|
||||
@ -1099,11 +1102,13 @@ RootAccessible::Release(void)
|
||||
return DocAccessible::Release();
|
||||
}
|
||||
|
||||
RootAccessible::RootAccessible(nsIAccessible* aAcc, HWND aWnd):DocAccessible(aAcc,nsnull,aWnd)
|
||||
RootAccessible::RootAccessible(nsIAccessible* aAcc, HWND aWnd):
|
||||
DocAccessible(aAcc,nsnull,aWnd), mIsActive(PR_TRUE)
|
||||
{
|
||||
nsCOMPtr<nsIAccessibleEventReceiver> r(do_QueryInterface(mXPAccessible));
|
||||
if (r)
|
||||
r->AddAccessibleEventListener(this);
|
||||
nsCOMPtr<nsIAccessibleEventReceiver> accReceiver =
|
||||
do_QueryInterface(mXPAccessible);
|
||||
if (accReceiver)
|
||||
accReceiver->AddAccessibleEventListener(this);
|
||||
|
||||
static PRBool prefsInitialized;
|
||||
|
||||
@ -1127,17 +1132,58 @@ RootAccessible::RootAccessible(nsIAccessible* aAcc, HWND aWnd):DocAccessible(aAc
|
||||
gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
|
||||
}
|
||||
|
||||
++gActiveRootAccessibles;
|
||||
}
|
||||
|
||||
RootAccessible::~RootAccessible()
|
||||
{
|
||||
nsCOMPtr<nsIAccessibleEventReceiver> r(do_QueryInterface(mXPAccessible));
|
||||
if (r)
|
||||
r->RemoveAccessibleEventListener();
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
// free up accessibles
|
||||
for (int i=0; i < gListCount; i++)
|
||||
gList[i].mAccessible = nsnull;
|
||||
void RootAccessible::Shutdown()
|
||||
{
|
||||
if (mIsActive) {
|
||||
mIsActive = PR_FALSE;
|
||||
nsCOMPtr<nsIAccessibleEventReceiver> accReceiver =
|
||||
do_QueryInterface(mXPAccessible);
|
||||
if (accReceiver)
|
||||
accReceiver->RemoveAccessibleEventListener();
|
||||
|
||||
if (--gActiveRootAccessibles == 0) // Last root accessible.
|
||||
ShutdownAll();
|
||||
|
||||
mDOMNode = nsnull;
|
||||
mXPAccessible = nsnull;
|
||||
|
||||
if (mCachedNextSibling) {
|
||||
mCachedNextSibling->Release();
|
||||
mCachedNextSibling = nsnull;
|
||||
}
|
||||
if (mCachedFirstChild) {
|
||||
mCachedFirstChild->Release();
|
||||
mCachedFirstChild = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RootAccessible::ShutdownAll()
|
||||
{
|
||||
// Turn accessibility support off and destroy all objects rather
|
||||
// than waiting until shutdown otherwise there will be crashes when
|
||||
// releases occur in modules that are no longer loaded
|
||||
|
||||
// First free up accessibles
|
||||
for (PRInt32 count=0; count < gListCount; count++) {
|
||||
gList[count].mAccessible = nsnull;
|
||||
}
|
||||
gListCount = 0;
|
||||
|
||||
// Shutdown accessibility service
|
||||
nsCOMPtr<nsIAccessibilityService> accService =
|
||||
do_GetService("@mozilla.org/accessibilityService;1");
|
||||
if (accService) {
|
||||
accService->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void RootAccessible::GetNSAccessibleFor(VARIANT varChild, nsCOMPtr<nsIAccessible>& aAcc)
|
||||
@ -1196,6 +1242,10 @@ STDMETHODIMP RootAccessible::get_accChild(
|
||||
|
||||
NS_IMETHODIMP RootAccessible::HandleEvent(PRUint32 aEvent, nsIAccessible* aAccessible, AccessibleEventData* aData)
|
||||
{
|
||||
if (!mIsActive) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef SWALLOW_DOC_FOCUS_EVENTS
|
||||
// Remove this until we can figure out which focus events are coming at
|
||||
// the same time as native window focus events, although
|
||||
@ -1230,7 +1280,9 @@ NS_IMETHODIMP RootAccessible::HandleEvent(PRUint32 aEvent, nsIAccessible* aAcces
|
||||
}
|
||||
|
||||
HWND hWnd = mWnd;
|
||||
if (aEvent == EVENT_FOCUS && gmGetGUIThreadInfo) {
|
||||
if (gmGetGUIThreadInfo && (aEvent == EVENT_FOCUS ||
|
||||
aEvent == EVENT_MENUPOPUPSTART ||
|
||||
aEvent == EVENT_MENUPOPUPEND)) {
|
||||
GUITHREADINFO guiInfo;
|
||||
guiInfo.cbSize = sizeof(GUITHREADINFO);
|
||||
if (gmGetGUIThreadInfo(NULL, &guiInfo)) {
|
||||
|
@ -54,7 +54,6 @@
|
||||
#include "SimpleDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
struct FlagBits {
|
||||
@ -287,7 +286,9 @@ public:
|
||||
virtual ~RootAccessible();
|
||||
|
||||
STDMETHODIMP QueryInterface(REFIID, void**);
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void);
|
||||
NS_IMETHOD_(nsrefcnt) Release(void);
|
||||
|
||||
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accChild(
|
||||
/* [in] */ VARIANT varChild,
|
||||
@ -298,6 +299,8 @@ public:
|
||||
|
||||
PRUint32 GetIdFor(nsIAccessible* aAccessible);
|
||||
virtual void GetNSAccessibleFor(VARIANT varChild, nsCOMPtr<nsIAccessible>& aAcc);
|
||||
void Shutdown();
|
||||
void ShutdownAll();
|
||||
|
||||
private:
|
||||
// list of accessible that may have had
|
||||
@ -305,6 +308,8 @@ public:
|
||||
static nsAccessibleEventMap gList[MAX_LIST_SIZE];
|
||||
static PRInt32 gListCount;
|
||||
static PRInt32 gNextPos;
|
||||
static PRInt32 gActiveRootAccessibles;
|
||||
PRBool mIsActive;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -302,13 +302,6 @@ NS_IMETHODIMP SimpleDOMNode::GetComputedStyleDeclaration(nsIDOMCSSStyleDeclarati
|
||||
if (content)
|
||||
content->GetDocument(*getter_AddRefs(doc));
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
if (doc)
|
||||
doc->GetShellAt(0, getter_AddRefs(shell));
|
||||
|
||||
if (!shell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
doc->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
nsCOMPtr<nsIDOMViewCSS> viewCSS(do_QueryInterface(global));
|
||||
|
@ -916,6 +916,7 @@ nsWindow::~nsWindow()
|
||||
{
|
||||
#ifdef ACCESSIBILITY
|
||||
if (mRootAccessible) {
|
||||
mRootAccessible->Shutdown();
|
||||
mRootAccessible->Release();
|
||||
mRootAccessible = nsnull;
|
||||
}
|
||||
@ -4508,8 +4509,14 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
|
||||
if (mIsTopWidgetWindow && !mRootAccessible)
|
||||
CreateRootAccessible();
|
||||
if (mRootAccessible) {
|
||||
if (lParam == OBJID_CLIENT) // oleacc.dll will be loaded dynamically
|
||||
lAcc = Accessible::LresultFromObject(IID_IAccessible, wParam, mRootAccessible); // does an addref
|
||||
if (lParam == OBJID_CLIENT) { // oleacc.dll will be loaded dynamically
|
||||
IAccessible *rootAccessible = nsnull;
|
||||
mRootAccessible->QueryInterface(IID_IAccessible, (void**)&rootAccessible); // does an addref
|
||||
if (rootAccessible) {
|
||||
lAcc = Accessible::LresultFromObject(IID_IAccessible, wParam, rootAccessible); // does an addref
|
||||
rootAccessible->Release(); // release addref from QueryInterface
|
||||
}
|
||||
}
|
||||
if (lParam == OBJID_CARET) { // each root accessible owns a caret accessible
|
||||
VARIANT variant;
|
||||
VariantInit(&variant);
|
||||
|
@ -63,7 +63,7 @@ class nsIMenuBar;
|
||||
#ifdef ACCESSIBILITY
|
||||
struct IAccessible;
|
||||
#include "nsIAccessible.h"
|
||||
#include "nsIAccessibleEventListener.h"
|
||||
class RootAccessible;
|
||||
#endif
|
||||
|
||||
#define IME_MAX_CHAR_POS 64
|
||||
@ -587,7 +587,7 @@ protected:
|
||||
static UINT uWM_HEAP_DUMP; // Dump heap to a file
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
IAccessible* mRootAccessible;
|
||||
RootAccessible* mRootAccessible;
|
||||
static BOOL gIsAccessibilityOn;
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user