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:
aaronl%netscape.com 2003-02-13 22:56:18 +00:00
parent 6f89b182bd
commit 7da68e788f
9 changed files with 104 additions and 32 deletions

View File

@ -97,6 +97,7 @@ interface nsIAccessibilityService : nsISupports
nsIAccessible createXULTooltipAccessible(in nsIDOMNode aNode);
nsIAccessible getAccessibleFor(in nsIDOMNode aNode);
void Shutdown();
};

View File

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

View File

@ -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__ */

View File

@ -419,6 +419,9 @@ NS_IMETHODIMP nsRootAccessible::RemoveAccessibleEventListener()
mCaretAccessible->RemoveSelectionListener();
mCaretAccessible = nsnull;
}
mAccService = nsnull;
return NS_OK;
}

View File

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

View File

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

View File

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

View File

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

View File

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