Index: third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp |
diff --git a/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp b/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp |
index d134a77f99859b9cfef7d27a5082f621b46cfb8c..c132ef8d4dbc6c2279bc9e7a4ef1115d2febe47a 100644 |
--- a/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp |
+++ b/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp |
@@ -27,10 +27,22 @@ |
#include "core/dom/DOMException.h" |
#include "wtf/PtrUtil.h" |
+#include "wtf/ThreadSpecific.h" |
#include <memory> |
namespace blink { |
+// This thread-specific list keeps track of instances of |
+// WebIDBDatabaseCallbacksImpl created by each thread. If a thread exits |
+// before they are destroyed then they would otherwise be leaked because the IO |
+// thread can no longer post a task to the thread on which they were created. |
+typedef std::vector<std::unique_ptr<WebIDBDatabaseCallbacksImpl>> CallbacksList; |
+static ThreadSpecific<CallbacksList>& outstandingCallbacks() |
+{ |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<CallbacksList>, callbacks, new ThreadSpecific<CallbacksList>); |
+ return callbacks; |
+} |
+ |
// static |
std::unique_ptr<WebIDBDatabaseCallbacksImpl> WebIDBDatabaseCallbacksImpl::create(IDBDatabaseCallbacks* callbacks) |
{ |
@@ -40,30 +52,54 @@ std::unique_ptr<WebIDBDatabaseCallbacksImpl> WebIDBDatabaseCallbacksImpl::create |
WebIDBDatabaseCallbacksImpl::WebIDBDatabaseCallbacksImpl(IDBDatabaseCallbacks* callbacks) |
: m_callbacks(callbacks) |
{ |
+ outstandingCallbacks()->push_back(wrapUnique(this)); |
} |
WebIDBDatabaseCallbacksImpl::~WebIDBDatabaseCallbacksImpl() |
{ |
+ if (m_callbacks) |
+ m_callbacks->webCallbacksDestroyed(); |
+ |
+ CallbacksList& callbacks = *outstandingCallbacks(); |
+ auto it = std::find_if( |
+ callbacks.begin(), callbacks.end(), |
+ [this](const std::unique_ptr<WebIDBDatabaseCallbacksImpl>& element) |
+ { |
+ return element.get() == this; |
+ }); |
+ if (it != callbacks.end()) { |
+ it->release(); |
+ callbacks.erase(it); |
+ } |
} |
void WebIDBDatabaseCallbacksImpl::onForcedClose() |
{ |
- m_callbacks->onForcedClose(); |
+ if (m_callbacks) |
+ m_callbacks->onForcedClose(); |
} |
void WebIDBDatabaseCallbacksImpl::onVersionChange(long long oldVersion, long long newVersion) |
{ |
- m_callbacks->onVersionChange(oldVersion, newVersion); |
+ if (m_callbacks) |
+ m_callbacks->onVersionChange(oldVersion, newVersion); |
} |
void WebIDBDatabaseCallbacksImpl::onAbort(long long transactionId, const WebIDBDatabaseError& error) |
{ |
- m_callbacks->onAbort(transactionId, DOMException::create(error.code(), error.message())); |
+ if (m_callbacks) |
+ m_callbacks->onAbort(transactionId, DOMException::create(error.code(), error.message())); |
} |
void WebIDBDatabaseCallbacksImpl::onComplete(long long transactionId) |
{ |
- m_callbacks->onComplete(transactionId); |
+ if (m_callbacks) |
+ m_callbacks->onComplete(transactionId); |
+} |
+ |
+void WebIDBDatabaseCallbacksImpl::detach() |
+{ |
+ m_callbacks.clear(); |
} |
} // namespace blink |