summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
Diffstat (limited to 'content')
-rw-r--r--content/browser/in_process_webkit/indexed_db_browsertest.cc4
-rw-r--r--content/browser/in_process_webkit/indexed_db_callbacks.cc25
-rw-r--r--content/browser/in_process_webkit/indexed_db_callbacks.h4
-rw-r--r--content/browser/in_process_webkit/indexed_db_dispatcher_host.cc28
-rw-r--r--content/browser/in_process_webkit/indexed_db_dispatcher_host.h6
-rw-r--r--content/common/indexed_db_messages.h19
-rw-r--r--content/renderer/indexed_db_dispatcher.cc67
-rw-r--r--content/renderer/indexed_db_dispatcher.h18
-rw-r--r--content/renderer/renderer_webidbcursor_impl.cc100
-rw-r--r--content/renderer/renderer_webidbcursor_impl.h31
10 files changed, 301 insertions, 1 deletions
diff --git a/content/browser/in_process_webkit/indexed_db_browsertest.cc b/content/browser/in_process_webkit/indexed_db_browsertest.cc
index c849a18..759efda 100644
--- a/content/browser/in_process_webkit/indexed_db_browsertest.cc
+++ b/content/browser/in_process_webkit/indexed_db_browsertest.cc
@@ -69,6 +69,10 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTestIncognito) {
true /* incognito */);
}
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorPrefetch) {
+ SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_prefetch.html"))));
+}
+
// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_IndexTest) {
SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
diff --git a/content/browser/in_process_webkit/indexed_db_callbacks.cc b/content/browser/in_process_webkit/indexed_db_callbacks.cc
index 70e79ef..969a430 100644
--- a/content/browser/in_process_webkit/indexed_db_callbacks.cc
+++ b/content/browser/in_process_webkit/indexed_db_callbacks.cc
@@ -59,6 +59,31 @@ void IndexedDBCallbacks<WebKit::WebIDBCursor>::onSuccessWithContinuation() {
content::SerializedScriptValue(idb_cursor->value())));
}
+void IndexedDBCallbacks<WebKit::WebIDBCursor>::onSuccessWithPrefetch(
+ const WebKit::WebVector<WebKit::WebIDBKey>& keys,
+ const WebKit::WebVector<WebKit::WebIDBKey>& primaryKeys,
+ const WebKit::WebVector<WebKit::WebSerializedScriptValue>& values) {
+ DCHECK(cursor_id_ != -1);
+
+ std::vector<IndexedDBKey> msgKeys;
+ std::vector<IndexedDBKey> msgPrimaryKeys;
+ std::vector<content::SerializedScriptValue> msgValues;
+
+ for (size_t i = 0; i < keys.size(); ++i) {
+ msgKeys.push_back(IndexedDBKey(keys[i]));
+ msgPrimaryKeys.push_back(IndexedDBKey(primaryKeys[i]));
+ msgValues.push_back(content::SerializedScriptValue(values[i]));
+ }
+
+ dispatcher_host()->Send(
+ new IndexedDBMsg_CallbacksSuccessCursorPrefetch(
+ response_id(),
+ cursor_id_,
+ msgKeys,
+ msgPrimaryKeys,
+ msgValues));
+}
+
void IndexedDBCallbacks<WebKit::WebIDBKey>::onSuccess(
const WebKit::WebIDBKey& value) {
dispatcher_host()->Send(
diff --git a/content/browser/in_process_webkit/indexed_db_callbacks.h b/content/browser/in_process_webkit/indexed_db_callbacks.h
index 085bfa4..de9edaf 100644
--- a/content/browser/in_process_webkit/indexed_db_callbacks.h
+++ b/content/browser/in_process_webkit/indexed_db_callbacks.h
@@ -93,6 +93,10 @@ class IndexedDBCallbacks<WebKit::WebIDBCursor>
virtual void onSuccess(WebKit::WebIDBCursor* idb_object);
virtual void onSuccess(const WebKit::WebSerializedScriptValue& value);
virtual void onSuccessWithContinuation();
+ virtual void onSuccessWithPrefetch(
+ const WebKit::WebVector<WebKit::WebIDBKey>& keys,
+ const WebKit::WebVector<WebKit::WebIDBKey>& primaryKeys,
+ const WebKit::WebVector<WebKit::WebSerializedScriptValue>& values);
private:
// The id of the cursor this callback concerns, or -1 if the cursor
diff --git a/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc b/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc
index e4abb51..f521667 100644
--- a/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc
+++ b/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc
@@ -886,6 +886,8 @@ bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived(
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDirection, OnDirection)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorUpdate, OnUpdate)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorContinue, OnContinue)
+ IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetch, OnPrefetch)
+ IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetchReset, OnPrefetchReset)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDelete, OnDelete)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDestroyed, OnDestroyed)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -967,6 +969,32 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue(
cursor_id), *ec);
}
+void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetch(
+ int32 cursor_id,
+ int32 response_id,
+ int n,
+ WebKit::WebExceptionCode* ec) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
+ WebIDBCursor* idb_cursor = parent_->GetOrTerminateProcess(&map_, cursor_id);
+ if (!idb_cursor)
+ return;
+
+ *ec = 0;
+ idb_cursor->prefetchContinue(
+ n, new IndexedDBCallbacks<WebIDBCursor>(parent_, response_id,
+ cursor_id), *ec);
+}
+
+void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset(
+ int32 cursor_id, int used_prefetches, int unused_prefetches) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
+ WebIDBCursor* idb_cursor = parent_->GetOrTerminateProcess(&map_, cursor_id);
+ if (!idb_cursor)
+ return;
+
+ idb_cursor->prefetchReset(used_prefetches, unused_prefetches);
+}
+
void IndexedDBDispatcherHost::CursorDispatcherHost::OnDelete(
int32 cursor_id,
int32 response_id,
diff --git a/content/browser/in_process_webkit/indexed_db_dispatcher_host.h b/content/browser/in_process_webkit/indexed_db_dispatcher_host.h
index 4ee03b9..88bff96 100644
--- a/content/browser/in_process_webkit/indexed_db_dispatcher_host.h
+++ b/content/browser/in_process_webkit/indexed_db_dispatcher_host.h
@@ -238,6 +238,12 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
int32 response_id,
const IndexedDBKey& key,
WebKit::WebExceptionCode* ec);
+ void OnPrefetch(int32 idb_cursor_id,
+ int32 response_id,
+ int n,
+ WebKit::WebExceptionCode* ec);
+ void OnPrefetchReset(int32 idb_cursor_id, int used_prefetches,
+ int unused_prefetches);
void OnDelete(int32 idb_object_store_id,
int32 response_id,
WebKit::WebExceptionCode* ec);
diff --git a/content/common/indexed_db_messages.h b/content/common/indexed_db_messages.h
index 118106e..31a0974 100644
--- a/content/common/indexed_db_messages.h
+++ b/content/common/indexed_db_messages.h
@@ -147,6 +147,12 @@ IPC_MESSAGE_CONTROL5(IndexedDBMsg_CallbacksSuccessCursorContinue,
IndexedDBKey /* key */,
IndexedDBKey /* primary key */,
content::SerializedScriptValue /* script_value */)
+IPC_MESSAGE_CONTROL5(IndexedDBMsg_CallbacksSuccessCursorPrefetch,
+ int32 /* response_id */,
+ int32 /* cursor_id */,
+ std::vector<IndexedDBKey> /* keys */,
+ std::vector<IndexedDBKey> /* primary keys */,
+ std::vector<content::SerializedScriptValue> /* values */)
IPC_MESSAGE_CONTROL2(IndexedDBMsg_CallbacksSuccessIDBDatabase,
int32 /* response_id */,
int32 /* idb_database_id */)
@@ -200,6 +206,19 @@ IPC_SYNC_MESSAGE_CONTROL3_1(IndexedDBHostMsg_CursorContinue,
IndexedDBKey, /* key */
WebKit::WebExceptionCode /* ec */)
+// WebIDBCursor::prefetchContinue() message.
+IPC_SYNC_MESSAGE_CONTROL3_1(IndexedDBHostMsg_CursorPrefetch,
+ int32, /* idb_cursor_id */
+ int32, /* response_id */
+ int32, /* n */
+ WebKit::WebExceptionCode /* ec */)
+
+// WebIDBCursor::prefetchReset() message.
+IPC_SYNC_MESSAGE_CONTROL3_0(IndexedDBHostMsg_CursorPrefetchReset,
+ int32, /* idb_cursor_id */
+ int32, /* used_prefetches */
+ int32 /* used_prefetches */)
+
// WebIDBCursor::remove() message.
IPC_SYNC_MESSAGE_CONTROL2_1(IndexedDBHostMsg_CursorDelete,
int32, /* idb_cursor_id */
diff --git a/content/renderer/indexed_db_dispatcher.cc b/content/renderer/indexed_db_dispatcher.cc
index 8b3ddda..2308e8b 100644
--- a/content/renderer/indexed_db_dispatcher.cc
+++ b/content/renderer/indexed_db_dispatcher.cc
@@ -44,6 +44,8 @@ bool IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
OnSuccessOpenCursor)
IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue,
OnSuccessCursorContinue)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch,
+ OnSuccessCursorPrefetch)
IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase,
OnSuccessIDBDatabase)
IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey,
@@ -74,6 +76,7 @@ void IndexedDBDispatcher::RequestIDBCursorUpdate(
WebIDBCallbacks* callbacks_ptr,
int32 idb_cursor_id,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
@@ -88,6 +91,9 @@ void IndexedDBDispatcher::RequestIDBCursorContinue(
WebIDBCallbacks* callbacks_ptr,
int32 idb_cursor_id,
WebExceptionCode* ec) {
+ // Reset all cursor prefetch caches except for this cursor.
+ ResetCursorPrefetchCaches(idb_cursor_id);
+
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
@@ -97,10 +103,32 @@ void IndexedDBDispatcher::RequestIDBCursorContinue(
pending_callbacks_.Remove(response_id);
}
+void IndexedDBDispatcher::RequestIDBCursorPrefetch(
+ int n,
+ WebIDBCallbacks* callbacks_ptr,
+ int32 idb_cursor_id,
+ WebExceptionCode* ec) {
+ scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+
+ int32 response_id = pending_callbacks_.Add(callbacks.release());
+ RenderThreadImpl::current()->Send(
+ new IndexedDBHostMsg_CursorPrefetch(idb_cursor_id, response_id, n, ec));
+ if (*ec)
+ pending_callbacks_.Remove(response_id);
+}
+
+void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(
+ int used_prefetches, int unused_prefetches, int32 idb_cursor_id) {
+ RenderThreadImpl::current()->Send(
+ new IndexedDBHostMsg_CursorPrefetchReset(idb_cursor_id, used_prefetches,
+ unused_prefetches));
+}
+
void IndexedDBDispatcher::RequestIDBCursorDelete(
WebIDBCallbacks* callbacks_ptr,
int32 idb_cursor_id,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
@@ -114,6 +142,7 @@ void IndexedDBDispatcher::RequestIDBFactoryOpen(
WebIDBCallbacks* callbacks_ptr,
const string16& origin,
WebFrame* web_frame) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
if (!web_frame)
@@ -133,6 +162,7 @@ void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
WebIDBCallbacks* callbacks_ptr,
const string16& origin,
WebFrame* web_frame) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
if (!web_frame)
@@ -152,6 +182,7 @@ void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
WebIDBCallbacks* callbacks_ptr,
const string16& origin,
WebFrame* web_frame) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
if (!web_frame)
@@ -168,6 +199,7 @@ void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
}
void IndexedDBDispatcher::RequestIDBDatabaseClose(int32 idb_database_id) {
+ ResetCursorPrefetchCaches();
Send(new IndexedDBHostMsg_DatabaseClose(idb_database_id));
pending_database_callbacks_.Remove(idb_database_id);
}
@@ -175,6 +207,7 @@ void IndexedDBDispatcher::RequestIDBDatabaseClose(int32 idb_database_id) {
void IndexedDBDispatcher::RequestIDBDatabaseOpen(
WebIDBDatabaseCallbacks* callbacks_ptr,
int32 idb_database_id) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBDatabaseCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_database_callbacks_.Add(callbacks.release());
@@ -186,6 +219,7 @@ void IndexedDBDispatcher::RequestIDBDatabaseSetVersion(
WebIDBCallbacks* callbacks_ptr,
int32 idb_database_id,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
@@ -202,6 +236,7 @@ void IndexedDBDispatcher::RequestIDBIndexOpenObjectCursor(
int32 idb_index_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBHostMsg_IndexOpenCursor_Params params;
params.response_id = pending_callbacks_.Add(callbacks.release());
@@ -224,6 +259,7 @@ void IndexedDBDispatcher::RequestIDBIndexOpenKeyCursor(
int32 idb_index_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBHostMsg_IndexOpenCursor_Params params;
params.response_id = pending_callbacks_.Add(callbacks.release());
@@ -247,6 +283,7 @@ void IndexedDBDispatcher::RequestIDBIndexGetObject(
int32 idb_index_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
Send(new IndexedDBHostMsg_IndexGetObject(idb_index_id, response_id, key,
@@ -261,6 +298,7 @@ void IndexedDBDispatcher::RequestIDBIndexGetKey(
int32 idb_index_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
Send(new IndexedDBHostMsg_IndexGetKey(
@@ -276,6 +314,7 @@ void IndexedDBDispatcher::RequestIDBObjectStoreGet(
int32 idb_object_store_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
@@ -294,6 +333,7 @@ void IndexedDBDispatcher::RequestIDBObjectStorePut(
int32 idb_object_store_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBHostMsg_ObjectStorePut_Params params;
params.idb_object_store_id = idb_object_store_id;
@@ -313,6 +353,7 @@ void IndexedDBDispatcher::RequestIDBObjectStoreDelete(
int32 idb_object_store_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
@@ -327,6 +368,7 @@ void IndexedDBDispatcher::RequestIDBObjectStoreClear(
int32 idb_object_store_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32 response_id = pending_callbacks_.Add(callbacks.release());
@@ -343,6 +385,7 @@ void IndexedDBDispatcher::RequestIDBObjectStoreOpenCursor(
int32 idb_object_store_id,
const WebIDBTransaction& transaction,
WebExceptionCode* ec) {
+ ResetCursorPrefetchCaches();
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBHostMsg_ObjectStoreOpenCursor_Params params;
params.response_id = pending_callbacks_.Add(callbacks.release());
@@ -458,6 +501,21 @@ void IndexedDBDispatcher::OnSuccessCursorContinue(
pending_callbacks_.Remove(response_id);
}
+void IndexedDBDispatcher::OnSuccessCursorPrefetch(
+ int32 response_id,
+ int32 cursor_id,
+ const std::vector<IndexedDBKey>& keys,
+ const std::vector<IndexedDBKey>& primary_keys,
+ const std::vector<content::SerializedScriptValue>& values) {
+ RendererWebIDBCursorImpl* cursor = cursors_[cursor_id];
+ DCHECK(cursor);
+ cursor->SetPrefetchData(keys, primary_keys, values);
+
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id);
+ cursor->CachedContinue(callbacks);
+ pending_callbacks_.Remove(response_id);
+}
+
void IndexedDBDispatcher::OnBlocked(int32 response_id) {
WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id);
callbacks->onBlocked();
@@ -500,3 +558,12 @@ void IndexedDBDispatcher::OnVersionChange(int32 database_id,
return;
callbacks->onVersionChange(newVersion);
}
+
+void IndexedDBDispatcher::ResetCursorPrefetchCaches(int32 exception_cursor_id) {
+ typedef std::map<int32, RendererWebIDBCursorImpl*>::iterator Iterator;
+ for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) {
+ if (i->first == exception_cursor_id)
+ continue;
+ i->second->ResetPrefetchCache();
+ }
+}
diff --git a/content/renderer/indexed_db_dispatcher.h b/content/renderer/indexed_db_dispatcher.h
index d2b3f1a..6f7deef 100644
--- a/content/renderer/indexed_db_dispatcher.h
+++ b/content/renderer/indexed_db_dispatcher.h
@@ -70,6 +70,15 @@ class IndexedDBDispatcher : public IPC::Channel::Listener {
int32 idb_cursor_id,
WebKit::WebExceptionCode* ec);
+ void RequestIDBCursorPrefetch(
+ int n,
+ WebKit::WebIDBCallbacks* callbacks_ptr,
+ int32 idb_cursor_id,
+ WebKit::WebExceptionCode* ec);
+
+ void RequestIDBCursorPrefetchReset(int used_prefetches, int unused_prefetches,
+ int32 idb_cursor_id);
+
void RequestIDBCursorDelete(
WebKit::WebIDBCallbacks* callbacks_ptr,
int32 idb_cursor_id,
@@ -174,6 +183,12 @@ class IndexedDBDispatcher : public IPC::Channel::Listener {
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
const content::SerializedScriptValue& value);
+ void OnSuccessCursorPrefetch(
+ int32 response_id,
+ int32 cursor_id,
+ const std::vector<IndexedDBKey>& keys,
+ const std::vector<IndexedDBKey>& primary_keys,
+ const std::vector<content::SerializedScriptValue>& values);
void OnSuccessStringList(int32 response_id,
const std::vector<string16>& value);
void OnSuccessSerializedScriptValue(
@@ -185,6 +200,9 @@ class IndexedDBDispatcher : public IPC::Channel::Listener {
void OnComplete(int32 transaction_id);
void OnVersionChange(int32 database_id, const string16& newVersion);
+ // Reset cursor prefetch caches for all cursors except exception_cursor_id.
+ void ResetCursorPrefetchCaches(int32 exception_cursor_id = -1);
+
// Careful! WebIDBCallbacks wraps non-threadsafe data types. It must be
// destroyed and used on the same thread it was created on.
IDMap<WebKit::WebIDBCallbacks, IDMapOwnPointer> pending_callbacks_;
diff --git a/content/renderer/renderer_webidbcursor_impl.cc b/content/renderer/renderer_webidbcursor_impl.cc
index 5ba7820..58113ad 100644
--- a/content/renderer/renderer_webidbcursor_impl.cc
+++ b/content/renderer/renderer_webidbcursor_impl.cc
@@ -14,7 +14,11 @@ using WebKit::WebIDBKey;
using WebKit::WebSerializedScriptValue;
RendererWebIDBCursorImpl::RendererWebIDBCursorImpl(int32 idb_cursor_id)
- : idb_cursor_id_(idb_cursor_id) {
+ : idb_cursor_id_(idb_cursor_id),
+ continue_count_(0),
+ used_prefetches_(0),
+ pending_onsuccess_callbacks_(0),
+ prefetch_amount_(kMinPrefetchAmount) {
}
RendererWebIDBCursorImpl::~RendererWebIDBCursorImpl() {
@@ -62,6 +66,34 @@ void RendererWebIDBCursorImpl::continueFunction(const WebIDBKey& key,
WebExceptionCode& ec) {
IndexedDBDispatcher* dispatcher =
RenderThreadImpl::current()->indexed_db_dispatcher();
+
+ if (key.type() == WebIDBKey::InvalidType) {
+ // No key, so this would qualify for a prefetch.
+ ++continue_count_;
+
+ if (!prefetch_keys_.empty()) {
+ // We have a prefetch cache, so serve the result from that.
+ CachedContinue(callbacks);
+ return;
+ }
+
+ if (continue_count_ > kPrefetchContinueThreshold) {
+ // Request pre-fetch.
+ dispatcher->RequestIDBCursorPrefetch(prefetch_amount_, callbacks,
+ idb_cursor_id_, &ec);
+
+ // Increase prefetch_amount_ exponentially.
+ prefetch_amount_ *= 2;
+ if (prefetch_amount_ > kMaxPrefetchAmount)
+ prefetch_amount_ = kMaxPrefetchAmount;
+
+ return;
+ }
+ } else {
+ // Key argument supplied. We couldn't prefetch this.
+ ResetPrefetchCache();
+ }
+
dispatcher->RequestIDBCursorContinue(IndexedDBKey(key), callbacks,
idb_cursor_id_, &ec);
}
@@ -73,6 +105,20 @@ void RendererWebIDBCursorImpl::deleteFunction(WebIDBCallbacks* callbacks,
dispatcher->RequestIDBCursorDelete(callbacks, idb_cursor_id_, &ec);
}
+void RendererWebIDBCursorImpl::postSuccessHandlerCallback()
+{
+ pending_onsuccess_callbacks_--;
+
+ // If the onsuccess callback called continue() on the cursor again,
+ // and that continue was served by the prefetch cache, then
+ // pending_onsuccess_callbacks_ would be incremented.
+ // If not, it means the callback did something else, or nothing at all,
+ // in which case we need to reset the cache.
+
+ if (pending_onsuccess_callbacks_ == 0)
+ ResetPrefetchCache();
+}
+
void RendererWebIDBCursorImpl::SetKeyAndValue(
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
@@ -81,3 +127,55 @@ void RendererWebIDBCursorImpl::SetKeyAndValue(
primary_key_ = primary_key;
value_ = value;
}
+
+void RendererWebIDBCursorImpl::SetPrefetchData(
+ const std::vector<IndexedDBKey>& keys,
+ const std::vector<IndexedDBKey>& primary_keys,
+ const std::vector<content::SerializedScriptValue>& values) {
+ prefetch_keys_.assign(keys.begin(), keys.end());
+ prefetch_primary_keys_.assign(primary_keys.begin(), primary_keys.end());
+ prefetch_values_.assign(values.begin(), values.end());
+
+ used_prefetches_ = 0;
+ pending_onsuccess_callbacks_ = 0;
+}
+
+void RendererWebIDBCursorImpl::CachedContinue(
+ WebKit::WebIDBCallbacks* callbacks) {
+ DCHECK(prefetch_keys_.size() > 0);
+ DCHECK(prefetch_primary_keys_.size() == prefetch_keys_.size());
+ DCHECK(prefetch_values_.size() == prefetch_keys_.size());
+
+ key_ = prefetch_keys_.front();
+ primary_key_ = prefetch_primary_keys_.front();
+ value_ = prefetch_values_.front();
+
+ prefetch_keys_.pop_front();
+ prefetch_primary_keys_.pop_front();
+ prefetch_values_.pop_front();
+ used_prefetches_++;
+
+ pending_onsuccess_callbacks_++;
+ callbacks->onSuccessWithContinuation();
+}
+
+void RendererWebIDBCursorImpl::ResetPrefetchCache() {
+ continue_count_ = 0;
+ prefetch_amount_ = kMinPrefetchAmount;
+
+ if (!prefetch_keys_.size()) {
+ // No prefetch cache, so no need to reset the cursor in the back-end.
+ return;
+ }
+
+ IndexedDBDispatcher* dispatcher =
+ RenderThreadImpl::current()->indexed_db_dispatcher();
+ dispatcher->RequestIDBCursorPrefetchReset(used_prefetches_,
+ prefetch_keys_.size(),
+ idb_cursor_id_);
+ prefetch_keys_.clear();
+ prefetch_primary_keys_.clear();
+ prefetch_values_.clear();
+
+ pending_onsuccess_callbacks_ = 0;
+}
diff --git a/content/renderer/renderer_webidbcursor_impl.h b/content/renderer/renderer_webidbcursor_impl.h
index fbca6b2..b033990 100644
--- a/content/renderer/renderer_webidbcursor_impl.h
+++ b/content/renderer/renderer_webidbcursor_impl.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_RENDERER_RENDERER_WEBIDBCURSOR_IMPL_H_
#define CONTENT_RENDERER_RENDERER_WEBIDBCURSOR_IMPL_H_
+#include <deque>
+
#include "base/basictypes.h"
#include "content/common/indexed_db_key.h"
#include "content/public/common/serialized_script_value.h"
@@ -30,15 +32,44 @@ class RendererWebIDBCursorImpl : public WebKit::WebIDBCursor {
WebKit::WebExceptionCode& ec);
virtual void deleteFunction(WebKit::WebIDBCallbacks* callback,
WebKit::WebExceptionCode& ec);
+ virtual void postSuccessHandlerCallback();
void SetKeyAndValue(const IndexedDBKey& key, const IndexedDBKey& primary_key,
const content::SerializedScriptValue& value);
+ void SetPrefetchData(
+ const std::vector<IndexedDBKey>& keys,
+ const std::vector<IndexedDBKey>& primary_keys,
+ const std::vector<content::SerializedScriptValue>& values);
+
+ void CachedContinue(WebKit::WebIDBCallbacks* callbacks);
+ void ResetPrefetchCache();
private:
int32 idb_cursor_id_;
IndexedDBKey key_;
IndexedDBKey primary_key_;
content::SerializedScriptValue value_;
+
+ // Prefetch cache.
+ std::deque<IndexedDBKey> prefetch_keys_;
+ std::deque<IndexedDBKey> prefetch_primary_keys_;
+ std::deque<content::SerializedScriptValue> prefetch_values_;
+
+ // Number of continue calls that would qualify for a pre-fetch.
+ int continue_count_;
+
+ // Number of items used from the last prefetch.
+ int used_prefetches_;
+
+ // Number of onsuccess handlers we are waiting for.
+ int pending_onsuccess_callbacks_;
+
+ // Number of items to request in next prefetch.
+ int prefetch_amount_;
+
+ enum { kPrefetchContinueThreshold = 2 };
+ enum { kMinPrefetchAmount = 5 };
+ enum { kMaxPrefetchAmount = 100 };
};
#endif // CONTENT_RENDERER_RENDERER_WEBIDBCURSOR_IMPL_H_