Chromium Code Reviews| 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 4b6b8e87603ccf4e2b756924583d64539efe6c18..55dfd32ff01e2e88bcfc03c9c451a43c32512b2e 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. |
| +using CallbacksList = std::vector<std::unique_ptr<WebIDBDatabaseCallbacksImpl>>; |
| +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) { |
| @@ -39,27 +51,52 @@ WebIDBDatabaseCallbacksImpl::create(IDBDatabaseCallbacks* callbacks) { |
| WebIDBDatabaseCallbacksImpl::WebIDBDatabaseCallbacksImpl( |
| IDBDatabaseCallbacks* callbacks) |
| - : m_callbacks(callbacks) {} |
| + : m_callbacks(callbacks) { |
| + outstandingCallbacks()->push_back(wrapUnique(this)); |
| +} |
| -WebIDBDatabaseCallbacksImpl::~WebIDBDatabaseCallbacksImpl() {} |
| +WebIDBDatabaseCallbacksImpl::~WebIDBDatabaseCallbacksImpl() { |
|
haraken
2016/10/18 19:01:29
Maybe we want to share the code with WebIDBCallbac
Reilly Grant (use Gerrit)
2016/10/19 00:36:51
I've moved this logic into IndexedDBDispatcher whe
|
| + 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 |