Stop nsMenuItemIconX object from possibly outliving its nsMenuObjectX owner. b=499600 r=josh

This commit is contained in:
Steven Michaud 2009-07-06 15:59:46 -05:00
Родитель 1ec8d353f5
Коммит 6bed2b38b0
4 изменённых файлов: 34 добавлений и 2 удалений

Просмотреть файл

@ -79,13 +79,19 @@ public:
// icon. The request may not complete until after LoadIcon returns. // icon. The request may not complete until after LoadIcon returns.
nsresult LoadIcon(nsIURI* aIconURI); nsresult LoadIcon(nsIURI* aIconURI);
// Unless we take precautions, we may outlive the object that created us
// (mMenuObject, which owns our native menu item (mNativeMenuItem)).
// Destroy() should be called from mMenuObject's destructor to prevent
// this from happening. See bug 499600.
void Destroy();
protected: protected:
nsCOMPtr<nsIContent> mContent; nsCOMPtr<nsIContent> mContent;
nsCOMPtr<imgIRequest> mIconRequest; nsCOMPtr<imgIRequest> mIconRequest;
nsMenuObjectX* mMenuObject; nsMenuObjectX* mMenuObject; // [weak]
PRPackedBool mLoadedIcon; PRPackedBool mLoadedIcon;
PRPackedBool mSetIcon; PRPackedBool mSetIcon;
NSMenuItem* mNativeMenuItem; NSMenuItem* mNativeMenuItem; // [weak]
}; };
#endif // nsMenuItemIconX_h_ #endif // nsMenuItemIconX_h_

Просмотреть файл

@ -97,6 +97,19 @@ nsMenuItemIconX::~nsMenuItemIconX()
mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED); mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
} }
// Called from mMenuObjectX's destructor, to prevent us from outliving it
// (as might otherwise happen if calls to our imgIDecoderObserver methods
// are still outstanding). mMenuObjectX owns our nNativeMenuItem.
void nsMenuItemIconX::Destroy()
{
if (mIconRequest) {
mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
mIconRequest = nsnull;
}
mMenuObject = nsnull;
mNativeMenuItem = nil;
}
nsresult nsresult
nsMenuItemIconX::SetupIcon() nsMenuItemIconX::SetupIcon()
{ {
@ -126,6 +139,9 @@ nsMenuItemIconX::SetupIcon()
nsresult nsresult
nsMenuItemIconX::GetIconURI(nsIURI** aIconURI) nsMenuItemIconX::GetIconURI(nsIURI** aIconURI)
{ {
if (!mMenuObject)
return NS_ERROR_FAILURE;
// Mac native menu items support having both a checkmark and an icon // Mac native menu items support having both a checkmark and an icon
// simultaneously, but this is unheard of in the cross-platform toolkit, // simultaneously, but this is unheard of in the cross-platform toolkit,
// seemingly because the win32 theme is unable to cope with both at once. // seemingly because the win32 theme is unable to cope with both at once.
@ -320,6 +336,8 @@ nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest,
if (mLoadedIcon) if (mLoadedIcon)
return NS_OK; return NS_OK;
if (!mNativeMenuItem) return NS_ERROR_FAILURE;
nsCOMPtr<gfxIImageFrame> frame = aFrame; nsCOMPtr<gfxIImageFrame> frame = aFrame;
nsCOMPtr<nsIImage> image = do_GetInterface(frame); nsCOMPtr<nsIImage> image = do_GetInterface(frame);
if (!image) return NS_ERROR_FAILURE; if (!image) return NS_ERROR_FAILURE;

Просмотреть файл

@ -72,6 +72,10 @@ nsMenuItemX::~nsMenuItemX()
{ {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK; NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// Prevent the icon object from outliving us.
if (mIcon)
mIcon->Destroy();
// autorelease the native menu item so that anything else happening to this // autorelease the native menu item so that anything else happening to this
// object happens before the native menu item actually dies // object happens before the native menu item actually dies
[mNativeMenuItem autorelease]; [mNativeMenuItem autorelease];

Просмотреть файл

@ -117,6 +117,10 @@ nsMenuX::~nsMenuX()
{ {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK; NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// Prevent the icon object from outliving us.
if (mIcon)
mIcon->Destroy();
RemoveAll(); RemoveAll();
[mNativeMenu setDelegate:nil]; [mNativeMenu setDelegate:nil];