From cd72e895866aceda273d5eed878e142be3811054 Mon Sep 17 00:00:00 2001 From: "neeti%netscape.com" Date: Wed, 24 Nov 1999 03:41:48 +0000 Subject: [PATCH] fix bug 15820,memory leak in ImageManagerImpl by converting it to a service on gtk, windows and mac.r=dp --- gfx/public/nsGfxCIID.h | 5 ++++ gfx/src/nsImageGroup.cpp | 24 ++++++++++------- gfx/src/nsImageManager.cpp | 10 ++++--- gfx/src/windows/nsGfxFactoryWin.cpp | 20 +++++++++++--- gfx/tests/btest/BitTest.cpp | 26 ++++++++++++------- webshell/tests/imgtest/ImageTest.cpp | 25 +++++++++++------- webshell/tests/viewer/nsSetupRegistry.cpp | 3 ++- webshell/tests/viewer/unix/gtk/nsGtkMain.cpp | 4 +-- .../tests/viewer/unix/motif/nsMotifMain.cpp | 23 ++++++++++++++-- webshell/tests/viewer/unix/qt/nsQtMain.cpp | 24 +++++++++++++++-- 10 files changed, 121 insertions(+), 43 deletions(-) diff --git a/gfx/public/nsGfxCIID.h b/gfx/public/nsGfxCIID.h index 1bf41ab27b18..d2741dca5c94 100644 --- a/gfx/public/nsGfxCIID.h +++ b/gfx/public/nsGfxCIID.h @@ -71,4 +71,9 @@ { 0x199c7040, 0xcab0, 0x11d2, \ { 0xa8, 0x49, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } } +#define NS_IMAGEMANAGER_CID \ +{ 0x140d2dd1, 0x96f4, 0x11d3, \ +{ 0x8a, 0xf3, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } } + + #endif diff --git a/gfx/src/nsImageGroup.cpp b/gfx/src/nsImageGroup.cpp index 88ced99d5c16..f44fe26d3fa1 100644 --- a/gfx/src/nsImageGroup.cpp +++ b/gfx/src/nsImageGroup.cpp @@ -20,6 +20,7 @@ * Contributor(s): */ +#include "nsIServiceManager.h" #include "nsIImageGroup.h" #include "nsIImageManager.h" #include "nsIImageObserver.h" @@ -34,9 +35,10 @@ #include "nsIDeviceContext.h" #include "nsIStreamListener.h" #include "nsILoadGroup.h" +#include "nsGfxCIID.h" static NS_DEFINE_IID(kIImageGroupIID, NS_IIMAGEGROUP_IID); - +static NS_DEFINE_IID(kImageManagerCID, NS_IMAGEMANAGER_CID); class ImageGroupImpl : public nsIImageGroup { @@ -328,22 +330,26 @@ extern "C" NS_GFX_(nsresult) NS_NewImageGroup(nsIImageGroup **aInstancePtrResult) { nsresult result; - + NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); if (nsnull == aInstancePtrResult) { return NS_ERROR_NULL_POINTER; } - - nsIImageManager *manager; - if ((result = NS_NewImageManager(&manager)) != NS_OK) { - return result; + nsCOMPtr manager; + manager = do_GetService(kImageManagerCID, &result); + if (NS_FAILED(result)) { + /* This is just to provide backwards compatibility, until the ImageManagerImpl + can be converted to a service on all platforms. Once, we done the conversion + on all platforms, we should be removing the call to NS_NewImageManager(...) + */ + if ((result = NS_NewImageManager(getter_AddRefs(manager))) != NS_OK) { + return result; + } } - nsIImageGroup *group = new ImageGroupImpl(manager); if (group == nsnull) { - return NS_ERROR_OUT_OF_MEMORY; + return NS_ERROR_OUT_OF_MEMORY; } - NS_RELEASE(manager); return group->QueryInterface(kIImageGroupIID, (void **) aInstancePtrResult); } diff --git a/gfx/src/nsImageManager.cpp b/gfx/src/nsImageManager.cpp index 615933c23a8e..1d83059fb3e4 100644 --- a/gfx/src/nsImageManager.cpp +++ b/gfx/src/nsImageManager.cpp @@ -49,7 +49,8 @@ private: }; // The singleton image manager -// XXX make this a service +// This a service on XP_PC , mac and gtk. Need to convert +// it to a service on all the remaining platforms. static ImageManagerImpl* gImageManager; ImageManagerImpl::ImageManagerImpl() @@ -64,6 +65,7 @@ ImageManagerImpl::~ImageManagerImpl() { IL_Shutdown(); NS_RELEASE(mSS); + gImageManager = nsnull; } NS_IMPL_ISUPPORTS1(ImageManagerImpl, nsIImageManager); @@ -108,8 +110,6 @@ NS_NewImageManager(nsIImageManager **aInstancePtrResult) } if (nsnull == gImageManager) { gImageManager = new ImageManagerImpl(); - //neeti - NS_IF_ADDREF(gImageManager); } if (nsnull == gImageManager) { return NS_ERROR_OUT_OF_MEMORY; @@ -117,8 +117,12 @@ NS_NewImageManager(nsIImageManager **aInstancePtrResult) return gImageManager->QueryInterface(kIImageManagerIID, (void **)aInstancePtrResult); } + +/* This is going to be obsolete, once ImageManagerImpl becomes a service on all platforms */ extern "C" NS_GFX_(void) NS_FreeImageManager() { + /*Do not release it on platforms on which ImageManagerImpl is a service. + Need to remove this method, once ImageManagerImpl is converted to a service on all platforms.*/ NS_IF_RELEASE(gImageManager); } diff --git a/gfx/src/windows/nsGfxFactoryWin.cpp b/gfx/src/windows/nsGfxFactoryWin.cpp index d0576e89ab45..ae15c9a6a393 100644 --- a/gfx/src/windows/nsGfxFactoryWin.cpp +++ b/gfx/src/windows/nsGfxFactoryWin.cpp @@ -33,6 +33,7 @@ #include "nsDeviceContextSpecWin.h" #include "nsDeviceContextSpecFactoryW.h" #include "nsScriptableRegion.h" +#include "nsIImageManager.h" static NS_DEFINE_IID(kCFontMetrics, NS_FONT_METRICS_CID); static NS_DEFINE_IID(kCFontEnumerator, NS_FONT_ENUMERATOR_CID); @@ -44,6 +45,7 @@ static NS_DEFINE_IID(kCRegion, NS_REGION_CID); static NS_DEFINE_IID(kCDeviceContextSpec, NS_DEVICE_CONTEXT_SPEC_CID); static NS_DEFINE_IID(kCDeviceContextSpecFactory, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); static NS_DEFINE_IID(kCDrawingSurface, NS_DRAWING_SURFACE_CID); +static NS_DEFINE_IID(kImageManagerImpl, NS_IMAGEMANAGER_CID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); @@ -129,7 +131,8 @@ NS_IMPL_RELEASE(nsGfxFactoryWin); nsresult nsGfxFactoryWin::CreateInstance(nsISupports *aOuter, const nsIID &aIID, void **aResult) -{ +{ + nsresult res; if (aResult == NULL) { return NS_ERROR_NULL_POINTER; } @@ -137,6 +140,7 @@ nsresult nsGfxFactoryWin::CreateInstance(nsISupports *aOuter, *aResult = NULL; nsISupports *inst = nsnull; + PRBool already_addreffed = PR_FALSE; if (mClassID.Equals(kCFontMetrics)) { nsFontMetricsWin* fm; @@ -201,6 +205,15 @@ nsresult nsGfxFactoryWin::CreateInstance(nsISupports *aOuter, inst = (nsISupports *)scriptableRgn; } } + else if (mClassID.Equals(kImageManagerImpl)) { + nsCOMPtr iManager; + res = NS_NewImageManager(getter_AddRefs(iManager)); + already_addreffed = PR_TRUE; + if (NS_SUCCEEDED(res)) + { + res = iManager->QueryInterface(NS_GET_IID(nsISupports), (void**)&inst); + } + } else if (mClassID.Equals(kCFontEnumerator)) { nsFontEnumeratorWin* fe; NS_NEWXPCOM(fe, nsFontEnumeratorWin); @@ -212,9 +225,10 @@ nsresult nsGfxFactoryWin::CreateInstance(nsISupports *aOuter, return NS_ERROR_OUT_OF_MEMORY; } - NS_ADDREF(inst); // Stabilize + if (already_addreffed == PR_FALSE) + NS_ADDREF(inst); // Stabilize - nsresult res = inst->QueryInterface(aIID, aResult); + res = inst->QueryInterface(aIID, aResult); NS_RELEASE(inst); // Destabilize and avoid leaks. Avoid calling delete diff --git a/gfx/tests/btest/BitTest.cpp b/gfx/tests/btest/BitTest.cpp index 3dae0d925685..2798067af590 100644 --- a/gfx/tests/btest/BitTest.cpp +++ b/gfx/tests/btest/BitTest.cpp @@ -44,6 +44,7 @@ #include "nsWidgetsCID.h" #include "nsITextWidget.h" #include "nsIBlender.h" +#include "nsIServiceManager.h" // widget interface static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); @@ -55,11 +56,13 @@ static NS_DEFINE_IID(kIImageObserverIID, NS_IIMAGEREQUESTOBSERVER_IID); static NS_DEFINE_IID(kCWindowIID, NS_WINDOW_CID); static NS_DEFINE_IID(kCChildWindowIID, NS_CHILD_CID); static NS_DEFINE_IID(kCScrollbarIID, NS_VERTSCROLLBAR_CID); +static NS_DEFINE_IID(kImageManagerCID, NS_IMAGEMANAGER_CID); + static char* class1Name = "ImageTest"; static HINSTANCE gInstance; -static nsIImageManager *gImageManager = nsnull; +static nsCOMPtr gImageManager; static nsIImageGroup *gImageGroup = nsnull; static nsIImageRequest *gImageReq = nsnull; static HWND gHwnd; @@ -1060,11 +1063,15 @@ PRUint32 size; case WM_CREATE: // Initialize image library - if (NS_NewImageManager(&gImageManager) != NS_OK||gImageManager->Init() != NS_OK) - { - ::MessageBox(NULL, "Can't initialize the image library",class1Name, MB_OK); - } - gImageManager->SetCacheSize(1024*1024); + { nsresult result; + gImageManager = do_GetService(kImageManagerCID, &result); + if ((NS_FAILED(result)) || gImageManager->Init() != NS_OK) + { + ::MessageBox(NULL, "Can't initialize the image library",class1Name, MB_OK); + } + else + gImageManager->SetCacheSize(1024*1024); + } break; case WM_DESTROY: MyInterrupt(); @@ -1075,10 +1082,7 @@ PRUint32 size; { NS_RELEASE(gImageGroup); } - if (gImageManager != nsnull) - { - NS_RELEASE(gImageManager); - } + gImageManager = nsnull; if (gBlendImage) { NS_RELEASE(gBlendImage); @@ -1174,6 +1178,8 @@ WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam, int nCmdShow nsComponentManager::RegisterComponent(kCFontMetricsIID, NULL, NULL, GFXWIN_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponent(kCImageIID, NULL, NULL, GFXWIN_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponent(kCBlenderIID, NULL, NULL, GFXWIN_DLL, PR_FALSE, PR_FALSE); + nsComponentManager::RegisterComponentLib(kCTextFieldCID, NULL, NULL, WIDGET_DLL, PR_FALSE, PR_FALSE); + nsComponentManager::RegisterComponentLib(kImageManagerCID, "Image Manager", "component://netscape/gfx/imagemanager", GFXWIN_DLL, PR_FALSE, PR_FALSE); if (!prevInstance) { WNDCLASS wndClass; diff --git a/webshell/tests/imgtest/ImageTest.cpp b/webshell/tests/imgtest/ImageTest.cpp index 2e0b574d9564..9085ade71d88 100644 --- a/webshell/tests/imgtest/ImageTest.cpp +++ b/webshell/tests/imgtest/ImageTest.cpp @@ -40,7 +40,9 @@ #include "nsRect.h" #include "nsWidgetsCID.h" #include "nsGfxCIID.h" + #include "nsIDeviceContext.h" +#include "nsIServiceManager.h" static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); static NS_DEFINE_IID(kIImageObserverIID, NS_IIMAGEREQUESTOBSERVER_IID); @@ -48,11 +50,12 @@ static NS_DEFINE_IID(kIImageObserverIID, NS_IIMAGEREQUESTOBSERVER_IID); static NS_DEFINE_IID(kCWindowIID, NS_WINDOW_CID); static NS_DEFINE_IID(kCChildWindowIID, NS_CHILD_CID); static NS_DEFINE_IID(kCScrollbarIID, NS_VERTSCROLLBAR_CID); +static NS_DEFINE_IID(kImageManagerCID, NS_IMAGEMANAGER_CID); static char* class1Name = "ImageTest"; static HINSTANCE gInstance, gPrevInstance; -static nsIImageManager *gImageManager = nsnull; +static nsCOMPtr gImageManager; static nsIImageGroup *gImageGroup = nsnull; static nsIImageRequest *gImageReq = nsnull; static HWND gHwnd; @@ -300,12 +303,15 @@ WndProc(HWND hWnd, UINT msg, WPARAM param, LPARAM lparam) case WM_CREATE: // Initialize image library - if (NS_NewImageManager(&gImageManager) != NS_OK || - gImageManager->Init() != NS_OK) { - ::MessageBox(NULL, "Can't initialize the image library", - class1Name, MB_OK); - } - gImageManager->SetCacheSize(1024*1024); + { nsresult result; + gImageManager = do_GetService(kImageManagerCID, &result); + if ((NS_FAILED(result)) || gImageManager->Init() != NS_OK) + { + ::MessageBox(NULL, "Can't initialize the image library",class1Name, MB_OK); + } + else + gImageManager->SetCacheSize(1024*1024); + } break; case WM_DESTROY: @@ -314,9 +320,7 @@ WndProc(HWND hWnd, UINT msg, WPARAM param, LPARAM lparam) if (gImageGroup != nsnull) { NS_RELEASE(gImageGroup); } - if (gImageManager != nsnull) { - NS_RELEASE(gImageManager); - } + gImageManager = nsnull; PostQuitMessage(0); break; @@ -375,6 +379,7 @@ WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam, int nCmdShow nsComponentManager::RegisterComponent(kCDeviceContextIID, NULL, NULL, GFXWIN_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponent(kCFontMetricsIID, NULL, NULL, GFXWIN_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponent(kCImageIID, NULL, NULL, GFXWIN_DLL, PR_FALSE, PR_FALSE); + nsComponentManager::RegisterComponentLib(kImageManagerCID, "Image Manager", "component://netscape/gfx/imagemanager", GFXWIN_DLL, PR_FALSE, PR_FALSE); if (!prevInstance) { WNDCLASS wndClass; diff --git a/webshell/tests/viewer/nsSetupRegistry.cpp b/webshell/tests/viewer/nsSetupRegistry.cpp index 9a77b76cf7b0..1f7b7ed886ca 100644 --- a/webshell/tests/viewer/nsSetupRegistry.cpp +++ b/webshell/tests/viewer/nsSetupRegistry.cpp @@ -145,7 +145,7 @@ static NS_DEFINE_CID(kCScriptableRegionCID, NS_SCRIPTABLE_REGION_CID); static NS_DEFINE_CID(kCBlenderCID, NS_BLENDER_CID); static NS_DEFINE_CID(kCDeviceContextSpecCID, NS_DEVICE_CONTEXT_SPEC_CID); static NS_DEFINE_CID(kCDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); - +static NS_DEFINE_CID(kImageManagerCID, NS_IMAGEMANAGER_CID); // VIEW static NS_DEFINE_IID(kCViewManagerCID, NS_VIEW_MANAGER_CID); @@ -335,6 +335,7 @@ NS_SetupRegistry() nsComponentManager::RegisterComponentLib(kCBlenderCID, "Blender", "component://netscape/gfx/blender", GFXWIN_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponentLib(kCDeviceContextSpecCID, "Device Context Spec", "component://netscape/gfx/devicecontextspec", GFXWIN_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponentLib(kCDeviceContextSpecFactoryCID, "Device Context Spec Factory", "component://netscape/gfx/devicecontextspecfactory", GFXWIN_DLL, PR_FALSE, PR_FALSE); + nsComponentManager::RegisterComponentLib(kImageManagerCID, "Image Manager", "component://netscape/gfx/imagemanager", GFXWIN_DLL, PR_FALSE, PR_FALSE); // VIEW nsComponentManager::RegisterComponentLib(kCViewManagerCID, NULL, NULL, VIEW_DLL, PR_FALSE, PR_FALSE); diff --git a/webshell/tests/viewer/unix/gtk/nsGtkMain.cpp b/webshell/tests/viewer/unix/gtk/nsGtkMain.cpp index 3c58148fe3db..32c8cbd5d0c6 100644 --- a/webshell/tests/viewer/unix/gtk/nsGtkMain.cpp +++ b/webshell/tests/viewer/unix/gtk/nsGtkMain.cpp @@ -166,9 +166,7 @@ int main(int argc, char **argv) gTheApp->Run(); delete gTheApp; - NS_FreeImageManager(); - - // Shutdown XPCOM + // Shutdown XPCOM rv = NS_ShutdownXPCOM(nsnull); NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); diff --git a/webshell/tests/viewer/unix/motif/nsMotifMain.cpp b/webshell/tests/viewer/unix/motif/nsMotifMain.cpp index c6207378a9b8..3d373bae584e 100644 --- a/webshell/tests/viewer/unix/motif/nsMotifMain.cpp +++ b/webshell/tests/viewer/unix/motif/nsMotifMain.cpp @@ -24,6 +24,10 @@ #include "nsBrowserWindow.h" #include "nsMotifMenu.h" #include "nsIImageManager.h" +#include "nsIServiceManager.h" +#include "nsGfxCIID.h" + +static NS_DEFINE_IID(kImageManagerCID, NS_IMAGEMANAGER_CID); static nsNativeViewerApp* gTheApp; @@ -99,9 +103,24 @@ nsNativeBrowserWindow::DispatchMenuItem(PRInt32 aID) int main(int argc, char **argv) { + nsresult result; // Hack to get il_ss set so it doesn't fail in xpcompat.c - nsIImageManager *manager; - NS_NewImageManager(&manager); + nsCOMPtr manager; + + manager = do_GetService(kImageManagerCID, &result); + if (NS_FAILED(result)) { + /* This is just to provide backwards compatibility, until the ImageManagerImpl + can be converted to a service on all platforms. Once, we havedone the conversion + on all platforms, we should be removing the call to NS_NewImageManager(...) + */ + if ((result = NS_NewImageManager(getter_AddRefs(manager))) != NS_OK) { + return result; + } + // WARNING Extra addref to simulate older be + nsIImageManager *aManager = manager.get(); + NS_ADDREF(aManager); + + } gTheApp = new nsNativeViewerApp(); diff --git a/webshell/tests/viewer/unix/qt/nsQtMain.cpp b/webshell/tests/viewer/unix/qt/nsQtMain.cpp index 7707d47a2a6e..221e885189df 100644 --- a/webshell/tests/viewer/unix/qt/nsQtMain.cpp +++ b/webshell/tests/viewer/unix/qt/nsQtMain.cpp @@ -28,6 +28,10 @@ #include "nsQtMenu.h" #include #include "plevent.h" +#include "nsIServiceManager.h" +#include "nsGfxCIID.h" + +static NS_DEFINE_IID(kImageManagerCID, NS_IMAGEMANAGER_CID); static nsNativeViewerApp* gTheApp; @@ -105,9 +109,25 @@ nsNativeBrowserWindow::DispatchMenuItem(PRInt32 aID) int main(int argc, char **argv) { + nsresult result; // Hack to get il_ss set so it doesn't fail in xpcompat.c - nsIImageManager *manager; - NS_NewImageManager(&manager); + nsCOMPtr manager; + + manager = do_GetService(kImageManagerCID, &result); + if (NS_FAILED(result)) { + /* This is just to provide backwards compatibility, until the ImageManagerImpl + can be converted to a service on all platforms. Once, we havedone the conversion + on all platforms, we should be removing the call to NS_NewImageManager(...) + */ + if ((result = NS_NewImageManager(getter_AddRefs(manager))) != NS_OK) { + return result; + } + // WARNING Extra addref to simulate older be + nsIImageManager *aManager = manager.get(); + NS_ADDREF(aManager); + + } + gTheApp = new nsNativeViewerApp();