From 8635aeb5cf62454f77b17a76afd3a2158be621f9 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Sat, 26 Sep 2009 01:22:33 +0000 Subject: [PATCH] libcef: - Fix a leak of CachedResource objects due to the Cache never being cleared (issue #15). - Fix a crash when the main application exits while popup windows exist due to a race condition when deleting CefBrowser objects. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@49 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- libcef/browser_impl_win.cc | 7 +++++++ libcef/browser_webkit_glue.cc | 8 ++++++++ libcef/browser_webkit_glue.h | 3 +++ libcef/context.cc | 30 ++++++++++++++++++++++++++---- libcef/context.h | 1 + 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/libcef/browser_impl_win.cc b/libcef/browser_impl_win.cc index bdeee27ab..8445ea281 100644 --- a/libcef/browser_impl_win.cc +++ b/libcef/browser_impl_win.cc @@ -64,6 +64,11 @@ LRESULT CALLBACK CefBrowserImpl::WndProc(HWND hwnd, UINT message, // Clean up anything associated with the WebViewHost widget. browser->GetWebViewHost()->webwidget()->close(); + // Clear the user data pointer. + win_util::SetWindowUserData(hwnd, NULL); + // Remove the reference added in UIT_CreateBrowser(). + browser->Release(); + // Remove the browser from the list maintained by the context _Context->RemoveBrowser(browser); } @@ -255,6 +260,8 @@ void CefBrowserImpl::UIT_CreateBrowser(const std::wstring& url) // Set window user data to this object for future reference from the window // procedure win_util::SetWindowUserData(window_info_.m_hWnd, this); + // Add a reference that will be released on WM_DESTROY. + AddRef(); // Add the new browser to the list maintained by the context _Context->AddBrowser(this); diff --git a/libcef/browser_webkit_glue.cc b/libcef/browser_webkit_glue.cc index 297881a97..a2c3f58c8 100644 --- a/libcef/browser_webkit_glue.cc +++ b/libcef/browser_webkit_glue.cc @@ -11,6 +11,7 @@ #undef LOG #include "config.h" MSVC_PUSH_WARNING_LEVEL(0); +#include "Cache.h" #include "TextEncoding.h" #include "webkit/glue/webframe_impl.h" MSVC_POP_WARNING(); @@ -204,4 +205,11 @@ void SetCacheMode(bool enabled) { // Used in benchmarking, Ignored for CEF. } +void ClearCache() +{ + // Clear the cache by disabling it and then re-enabling it. + WebCore::cache()->setDisabled(true); + WebCore::cache()->setDisabled(false); +} + } // namespace webkit_glue diff --git a/libcef/browser_webkit_glue.h b/libcef/browser_webkit_glue.h index 6c8105d6e..21a56d25d 100644 --- a/libcef/browser_webkit_glue.h +++ b/libcef/browser_webkit_glue.h @@ -35,4 +35,7 @@ base::StringPiece NetResourceProvider(int key); // Retrieve the V8 context associated with the frame. v8::Handle GetV8Context(WebKit::WebFrame* frame); +// Clear all cached data. +void ClearCache(); + } // namespace webkit_glue diff --git a/libcef/context.cc b/libcef/context.cc index 737d1af4f..77328e64e 100644 --- a/libcef/context.cc +++ b/libcef/context.cc @@ -398,6 +398,7 @@ bool CefContext::Initialize(bool multi_threaded_message_loop, void CefContext::Shutdown() { bool shutdown = false, intransition = false; + BrowserList browserlist; Lock(); @@ -411,8 +412,8 @@ void CefContext::Shutdown() // We are now in a transitional state in_transition_ = true; - if(browserlist_.size() > 0) - browserlist_.clear(); + browserlist = browserlist_; + browserlist_.empty(); if(webprefs_) { delete webprefs_; @@ -429,6 +430,14 @@ void CefContext::Shutdown() Unlock(); if(shutdown) { + if (browserlist.size() > 0) { + // Close any remaining browser windows + BrowserList::const_iterator it = browserlist.begin(); + for (; it != browserlist.end(); ++it) + PostMessage((*it)->GetWindowHandle(), WM_CLOSE, 0, 0); + browserlist.empty(); + } + if (hthreadui_) { // Wait for the UI thread to exit WaitForSingleObject(hthreadui_, INFINITE); @@ -483,9 +492,15 @@ bool CefContext::AddBrowser(CefRefPtr browser) return !found; } +void CefContext::UIT_ClearCache() +{ + webkit_glue::ClearCache(); +} + bool CefContext::RemoveBrowser(CefRefPtr browser) { bool deleted = false; + bool empty = false; Lock(); @@ -498,11 +513,18 @@ bool CefContext::RemoveBrowser(CefRefPtr browser) } } - if (browserlist_.empty()) + if (browserlist_.empty()) { next_browser_id_ = 1; + empty = true; + } Unlock(); - + + if (empty) { + PostTask(FROM_HERE, NewRunnableMethod(_Context.get(), + &CefContext::UIT_ClearCache)); + } + return deleted; } diff --git a/libcef/context.h b/libcef/context.h index 4f07fdfc3..62dd02923 100644 --- a/libcef/context.h +++ b/libcef/context.h @@ -53,6 +53,7 @@ public: void UIT_RegisterPlugin(struct CefPluginInfo* plugin_info); void UIT_UnregisterPlugin(struct CefPluginInfo* plugin_info); + void UIT_ClearCache(); bool DoWork(); bool DoDelayedWork();