Index: third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp |
diff --git a/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp b/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp |
index f8a3fa44c9e8c17f3da31d21739e7ebb19da4284..bc0c454ebfd1706f81c0bb413b5c33f7478bbf00 100644 |
--- a/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp |
+++ b/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp |
@@ -41,6 +41,7 @@ |
#include "public/platform/modules/indexeddb/WebIDBKey.h" |
#include "public/platform/modules/indexeddb/WebIDBValue.h" |
#include "wtf/PtrUtil.h" |
+#include "wtf/ThreadSpecific.h" |
#include <memory> |
using blink::WebIDBCursor; |
@@ -54,6 +55,17 @@ using blink::WebVector; |
namespace blink { |
+// This thread-specific list keeps track of instances of WebIDBCallbacksImpl |
+// 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<WebIDBCallbacksImpl>> CallbacksList; |
+static ThreadSpecific<CallbacksList>& outstandingCallbacks() |
+{ |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<CallbacksList>, callbacks, new ThreadSpecific<CallbacksList>); |
+ return callbacks; |
+} |
+ |
// static |
std::unique_ptr<WebIDBCallbacksImpl> WebIDBCallbacksImpl::create(IDBRequest* request) |
{ |
@@ -64,89 +76,140 @@ WebIDBCallbacksImpl::WebIDBCallbacksImpl(IDBRequest* request) |
: m_request(request) |
{ |
InspectorInstrumentation::asyncTaskScheduled(m_request->getExecutionContext(), IndexedDBNames::IndexedDB, this, true); |
+ outstandingCallbacks()->push_back(wrapUnique(this)); |
} |
WebIDBCallbacksImpl::~WebIDBCallbacksImpl() |
{ |
- InspectorInstrumentation::asyncTaskCanceled(m_request->getExecutionContext(), this); |
+ if (m_request) { |
+ InspectorInstrumentation::asyncTaskCanceled(m_request->getExecutionContext(), this); |
+ m_request->webCallbacksDestroyed(); |
+ } |
+ |
+ CallbacksList& callbacks = *outstandingCallbacks(); |
+ auto it = std::find_if( |
+ callbacks.begin(), callbacks.end(), |
+ [this](const std::unique_ptr<WebIDBCallbacksImpl>& element) |
+ { |
+ return element.get() == this; |
+ }); |
+ if (it != callbacks.end()) { |
+ it->release(); |
+ callbacks.erase(it); |
+ } |
} |
void WebIDBCallbacksImpl::onError(const WebIDBDatabaseError& error) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onError(DOMException::create(error.code(), error.message())); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onError(DOMException::create(error.code(), error.message())); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess(const WebVector<WebString>& webStringList) |
{ |
- Vector<String> stringList; |
- for (size_t i = 0; i < webStringList.size(); ++i) |
- stringList.append(webStringList[i]); |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onSuccess(stringList); |
+ if (m_request) { |
+ Vector<String> stringList; |
+ for (size_t i = 0; i < webStringList.size(); ++i) |
+ stringList.append(webStringList[i]); |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onSuccess(stringList); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess(WebIDBCursor* cursor, const WebIDBKey& key, const WebIDBKey& primaryKey, const WebIDBValue& value) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onSuccess(wrapUnique(cursor), key, primaryKey, IDBValue::create(value)); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onSuccess(wrapUnique(cursor), key, primaryKey, IDBValue::create(value)); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess(WebIDBDatabase* backend, const WebIDBMetadata& metadata) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onSuccess(wrapUnique(backend), IDBDatabaseMetadata(metadata)); |
+ std::unique_ptr<WebIDBDatabase> db = wrapUnique(backend); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onSuccess(std::move(db), IDBDatabaseMetadata(metadata)); |
+ } else { |
+ db->close(); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess(const WebIDBKey& key) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onSuccess(key); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onSuccess(key); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess(const WebIDBValue& value) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onSuccess(IDBValue::create(value)); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onSuccess(IDBValue::create(value)); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess(const WebVector<WebIDBValue>& values) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- Vector<RefPtr<IDBValue>> idbValues(values.size()); |
- for (size_t i = 0; i < values.size(); ++i) |
- idbValues[i] = IDBValue::create(values[i]); |
- m_request->onSuccess(idbValues); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ Vector<RefPtr<IDBValue>> idbValues(values.size()); |
+ for (size_t i = 0; i < values.size(); ++i) |
+ idbValues[i] = IDBValue::create(values[i]); |
+ m_request->onSuccess(idbValues); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess(long long value) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onSuccess(value); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onSuccess(value); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess() |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onSuccess(); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onSuccess(); |
+ } |
} |
void WebIDBCallbacksImpl::onSuccess(const WebIDBKey& key, const WebIDBKey& primaryKey, const WebIDBValue& value) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onSuccess(key, primaryKey, IDBValue::create(value)); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onSuccess(key, primaryKey, IDBValue::create(value)); |
+ } |
} |
void WebIDBCallbacksImpl::onBlocked(long long oldVersion) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onBlocked(oldVersion); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onBlocked(oldVersion); |
+ } |
} |
void WebIDBCallbacksImpl::onUpgradeNeeded(long long oldVersion, WebIDBDatabase* database, const WebIDBMetadata& metadata, unsigned short dataLoss, WebString dataLossMessage) |
{ |
- InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
- m_request->onUpgradeNeeded(oldVersion, wrapUnique(database), IDBDatabaseMetadata(metadata), static_cast<WebIDBDataLoss>(dataLoss), dataLossMessage); |
+ std::unique_ptr<WebIDBDatabase> db = wrapUnique(database); |
+ if (m_request) { |
+ InspectorInstrumentation::AsyncTask asyncTask(m_request->getExecutionContext(), this); |
+ m_request->onUpgradeNeeded(oldVersion, std::move(db), IDBDatabaseMetadata(metadata), static_cast<WebIDBDataLoss>(dataLoss), dataLossMessage); |
+ } else { |
+ db->close(); |
+ } |
+} |
+ |
+void WebIDBCallbacksImpl::detach() |
+{ |
+ m_request.clear(); |
} |
} // namespace blink |