From: Gabriel Ivăncescu gabrielopcode@gmail.com
This fixes leaks when some Gecko thread events hold refs to the document or other objects.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/nsembed.c | 27 +++++++++++++++++++++++++++ dlls/mshtml/nsiface.idl | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+)
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 9952a553afd..30c0ef513b8 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -46,6 +46,7 @@ WINE_DECLARE_DEBUG_CHANNEL(gecko); #define NS_PREFERENCES_CONTRACTID "@mozilla.org/preferences;1" #define NS_VARIANT_CONTRACTID "@mozilla.org/variant;1" #define NS_CATEGORYMANAGER_CONTRACTID "@mozilla.org/categorymanager;1" +#define NS_THREADMANAGER_CONTRACTID "@mozilla.org/thread-manager;1" #define NS_XMLHTTPREQUEST_CONTRACTID "@mozilla.org/xmlextras/xmlhttprequest;1"
#define PR_UINT32_MAX 0xffffffff @@ -1103,6 +1104,29 @@ nsresult get_nsinterface(nsISupports *iface, REFIID riid, void **ppv) return nsres; }
+static void flush_thread_nsevents(void) +{ + nsIThreadManager *threadmgr; + nsIThread *thread; + nsresult nsres; + cpp_bool b; + + nsres = nsIServiceManager_GetServiceByContractID(pServMgr, NS_THREADMANAGER_CONTRACTID, &IID_nsIThreadManager, (void**)&threadmgr); + if(NS_FAILED(nsres)) + return; + + nsres = nsIThreadManager_GetCurrentThread(threadmgr, &thread); + nsIThreadManager_Release(threadmgr); + if(NS_FAILED(nsres)) + return; + + do { + nsres = nsIThread_ProcessNextEvent(thread, FALSE, &b); + } while(NS_SUCCEEDED(nsres) && b); + + nsIThread_Release(thread); +} + static HRESULT nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode *nsnode, nsAString *str) { nsIDOMNodeList *node_list = NULL; @@ -2398,6 +2422,9 @@ void detach_gecko_browser(GeckoBrowser *This)
nsIWebBrowserChrome_Release(&This->nsIWebBrowserChrome_iface);
+ /* Flush gecko thread events that might be holding refs */ + flush_thread_nsevents(); + /* Force cycle collection */ if(window_utils) { nsIDOMWindowUtils_CycleCollect(window_utils, NULL, 0); diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 5991e0de45b..2189e65a5d5 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -270,6 +270,46 @@ interface nsIRunnable : nsISupports nsresult Run(); }
+[ + object, + uuid(88145945-3278-424e-9f37-d874cbdd9f6f), + local +] +interface nsIEventTarget : nsISupports +{ + nsresult IsOnCurrentThread(bool *aResult); + nsresult Dispatch(nsIRunnable *aEvent, uint32_t aFlags); + nsresult DispatchFromScript(nsIRunnable *aEvent, uint32_t aFlags); +} + +[ + object, + uuid(5801d193-29d1-4964-a6b7-70eb697ddf2b), + local +] +interface nsIThread : nsIEventTarget +{ + nsresult GetPRThread(void /*PRThread*/ **aResult); + nsresult Shutdown(); + nsresult HasPendingEvents(bool *aResult); + nsresult ProcessNextEvent(bool aMayWait, bool *aResult); + nsresult AsyncShutdown(); +} + +[ + object, + uuid(1be89eca-e2f7-453b-8d38-c11ba247f6f3), + local +] +interface nsIThreadManager : nsISupports +{ + nsresult NewThread(uint32_t aCreationFlags, uint32_t aStackSize, nsIThread **aResult); + nsresult GetThreadFromPRThread(void /*PRThread*/ *aThread, nsIThread **aResult); + nsresult GetMainThread(nsIThread **aResult); + nsresult GetCurrentThread(nsIThread **aResult); + nsresult GetIsMainThread(bool *aResult); +} + [ object, uuid(d1899240-f9d2-11d2-bdd6-000064657374),