Chromium Code Reviews| 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 22bc31535876f6893841dbb35712eda358fc3dda..8293ca6a05155b0f90a09fda7a750901df54f61d 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. |
| +using CallbacksList = std::vector<std::unique_ptr<WebIDBCallbacksImpl>>; |
|
dcheng
2016/10/17 05:33:44
Inside Blink, we should probably be using WTF::Vec
|
| +static ThreadSpecific<CallbacksList>& outstandingCallbacks() { |
|
haraken
2016/10/18 19:01:29
It's not really nice to use ThreadSpecific to keep
Reilly Grant (use Gerrit)
2016/10/19 00:36:51
The only per-worker object I know of that could ho
|
| + DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<CallbacksList>, callbacks, |
| + new ThreadSpecific<CallbacksList>); |
| + return callbacks; |
| +} |
| + |
| // static |
| std::unique_ptr<WebIDBCallbacksImpl> WebIDBCallbacksImpl::create( |
| IDBRequest* request) { |
| @@ -64,20 +76,41 @@ 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(), |
|
haraken
2016/10/18 19:01:29
To avoid the O(N) search, would it be better to us
Reilly Grant (use Gerrit)
2016/10/19 00:36:51
The number of outstanding requests is expected to
|
| + [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) { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| m_request->onError(DOMException::create(error.code(), error.message())); |
| } |
| void WebIDBCallbacksImpl::onSuccess(const WebVector<WebString>& webStringList) { |
| + if (!m_request) |
| + return; |
| + |
| Vector<String> stringList; |
| for (size_t i = 0; i < webStringList.size(); ++i) |
| stringList.append(webStringList[i]); |
| @@ -90,6 +123,9 @@ void WebIDBCallbacksImpl::onSuccess(WebIDBCursor* cursor, |
| const WebIDBKey& key, |
| const WebIDBKey& primaryKey, |
| const WebIDBValue& value) { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| m_request->onSuccess(wrapUnique(cursor), key, primaryKey, |
| @@ -98,24 +134,38 @@ void WebIDBCallbacksImpl::onSuccess(WebIDBCursor* cursor, |
| 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 if (db) { |
| + db->close(); |
| + } |
| } |
| void WebIDBCallbacksImpl::onSuccess(const WebIDBKey& key) { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| m_request->onSuccess(key); |
| } |
| void WebIDBCallbacksImpl::onSuccess(const WebIDBValue& value) { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| m_request->onSuccess(IDBValue::create(value)); |
| } |
| void WebIDBCallbacksImpl::onSuccess(const WebVector<WebIDBValue>& values) { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| Vector<RefPtr<IDBValue>> idbValues(values.size()); |
| @@ -125,12 +175,18 @@ void WebIDBCallbacksImpl::onSuccess(const WebVector<WebIDBValue>& values) { |
| } |
| void WebIDBCallbacksImpl::onSuccess(long long value) { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| m_request->onSuccess(value); |
| } |
| void WebIDBCallbacksImpl::onSuccess() { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| m_request->onSuccess(); |
| @@ -139,12 +195,18 @@ void WebIDBCallbacksImpl::onSuccess() { |
| void WebIDBCallbacksImpl::onSuccess(const WebIDBKey& key, |
| const WebIDBKey& primaryKey, |
| const WebIDBValue& value) { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| m_request->onSuccess(key, primaryKey, IDBValue::create(value)); |
| } |
| void WebIDBCallbacksImpl::onBlocked(long long oldVersion) { |
| + if (!m_request) |
| + return; |
| + |
| InspectorInstrumentation::AsyncTask asyncTask( |
| m_request->getExecutionContext(), this); |
| m_request->onBlocked(oldVersion); |
| @@ -155,11 +217,20 @@ void WebIDBCallbacksImpl::onUpgradeNeeded(long long oldVersion, |
| 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 |