Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(816)

Unified Diff: content/browser/indexed_db/indexed_db_callbacks.cc

Issue 18023022: Blob support for IDB [Chromium] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use ScopedVector and stl_utils for BlobDataHandles. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/indexed_db/indexed_db_callbacks.cc
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc
index 587b66f0668e09bedbdc29f84d98f32fdd065beb..df7da8adce064229bff83ed465a3ba65eaf3019f 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -6,14 +6,27 @@
#include <algorithm>
+#include "base/guid.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/fileapi/fileapi_message_filter.h"
+#include "content/browser/indexed_db/indexed_db_blob_info.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_metadata.h"
+#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/common/indexed_db/indexed_db_constants.h"
#include "content/common/indexed_db/indexed_db_messages.h"
+#include "webkit/browser/blob/blob_storage_context.h"
#include "webkit/browser/quota/quota_manager.h"
+#include "webkit/common/blob/blob_data.h"
+#include "webkit/common/blob/shareable_file_reference.h"
+
+using webkit_blob::ShareableFileReference;
namespace content {
@@ -159,10 +172,151 @@ void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
dispatcher_host_ = NULL;
}
+static std::string CreateBlobData(
+ const IndexedDBBlobInfo& blob_info,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
+ webkit_blob::BlobStorageContext* blob_storage_context,
+ base::TaskRunner* task_runner) {
+ scoped_refptr<ShareableFileReference> shareable_file =
+ ShareableFileReference::Get(blob_info.file_path());
+ if (!shareable_file.get()) {
+ shareable_file = ShareableFileReference::GetOrCreate(
+ blob_info.file_path(),
+ ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
+ task_runner);
+ shareable_file->AddFinalReleaseCallback(blob_info.release_callback());
+ }
+
+ std::string uuid(base::GenerateGUID());
+ scoped_refptr<webkit_blob::BlobData> blob_data =
+ new webkit_blob::BlobData(uuid);
+ blob_data->AppendFile(blob_info.file_path(), 0, blob_info.size(),
+ blob_info.last_modified());
+ scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle(
+ blob_storage_context->AddFinishedBlob(blob_data.get()));
+ dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle);
+
+ return uuid;
+}
+
+static bool CreateAllBlobs(
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host) {
+ size_t i;
+ if (!dispatcher_host->blob_storage_context())
+ return false;
+ for (i = 0; i < blob_info.size(); ++i) {
+ (*blob_or_file_info)[i].uuid =
+ CreateBlobData(blob_info[i], dispatcher_host,
+ dispatcher_host->blob_storage_context(),
+ dispatcher_host->Context()->TaskRunner());
+ }
+ return true;
+}
+
+static void BlobLookupForIDBCursor(
+ IndexedDBMsg_CallbacksSuccessIDBCursor_Params* params,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host))
+ dispatcher_host->Send(
+ new IndexedDBMsg_CallbacksSuccessIDBCursor(*params));
+}
+
+static void BlobLookupForCursorContinue(
+ IndexedDBMsg_CallbacksSuccessCursorContinue_Params* params,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host))
+ dispatcher_host->Send(
+ new IndexedDBMsg_CallbacksSuccessCursorContinue(*params));
+}
+
+static void BlobLookupForValueWithKey(
+ IndexedDBMsg_CallbacksSuccessValueWithKey_Params* params,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host))
+ dispatcher_host->Send(
+ new IndexedDBMsg_CallbacksSuccessValueWithKey(*params));
+}
+
+static void BlobLookupForValue(
+ IndexedDBMsg_CallbacksSuccessValue_Params* params,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host))
+ dispatcher_host->Send(new IndexedDBMsg_CallbacksSuccessValue(*params));
+}
+
+static void BlobLookupForCursorPrefetch(
+ IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params* params,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
+ const std::vector<IndexedDBValue>& values,
+ std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >*
+ blob_or_file_infos) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(values.size() == blob_or_file_infos->size());
+
+ std::vector<IndexedDBValue>::const_iterator value_iter;
+ std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >::iterator blob_iter;
+ for (value_iter = values.begin(), blob_iter = blob_or_file_infos->begin();
+ value_iter != values.end(); ++value_iter, ++blob_iter) {
+ if (!CreateAllBlobs(value_iter->blob_info, &*blob_iter, dispatcher_host))
+ return;
+ }
+ dispatcher_host->Send(
+ new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params));
+}
+
+static void FillInBlobData(
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
+ for (std::vector<IndexedDBBlobInfo>::const_iterator iter = blob_info.begin();
+ iter != blob_info.end(); ++iter) {
+ if (iter->is_file()) {
+ IndexedDBMsg_BlobOrFileInfo info;
+ info.is_file = true;
+ info.mime_type = iter->type();
+ info.file_name = iter->file_name();
+ info.file_path = iter->file_path().AsUTF16Unsafe();
+ DCHECK_NE(-1, iter->size());
+ info.size = iter->size();
+ info.last_modified = iter->last_modified().ToDoubleT();
+ blob_or_file_info->push_back(info);
+ } else {
+ IndexedDBMsg_BlobOrFileInfo info;
+ info.mime_type = iter->type();
+ info.size = iter->size();
+ blob_or_file_info->push_back(info);
+ }
+ }
+}
+
+void IndexedDBCallbacks::RegisterBlobsAndSend(
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ const base::Closure& callback) {
+ std::vector<IndexedDBBlobInfo>::const_iterator iter;
+ for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
+ iter->mark_used_callback().Run();
+ }
+ DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
+}
+
void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- std::string* value) {
+ IndexedDBValue* value) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
@@ -171,24 +325,34 @@ void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
int32 ipc_object_id = dispatcher_host_->Add(cursor.get());
- IndexedDBMsg_CallbacksSuccessIDBCursor_Params params;
- params.ipc_thread_id = ipc_thread_id_;
- params.ipc_callbacks_id = ipc_callbacks_id_;
- params.ipc_cursor_id = ipc_object_id;
- params.key = key;
- params.primary_key = primary_key;
+ scoped_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params(
+ new IndexedDBMsg_CallbacksSuccessIDBCursor_Params());
+ params->ipc_thread_id = ipc_thread_id_;
+ params->ipc_callbacks_id = ipc_callbacks_id_;
+ params->ipc_cursor_id = ipc_object_id;
+ params->key = key;
+ params->primary_key = primary_key;
if (value && !value->empty())
- std::swap(params.value, *value);
+ std::swap(params->value, value->bits);
// TODO(alecflett): Avoid a copy here: the whole params object is
// being copied into the message.
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(params));
-
+ if (!value || value->blob_info.empty()) {
+ dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params));
+ } else {
+ IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get();
+ FillInBlobData(value->blob_info, &p->blob_or_file_info);
+ RegisterBlobsAndSend(
+ value->blob_info,
+ base::Bind(BlobLookupForIDBCursor, base::Owned(params.release()),
+ dispatcher_host_, value->blob_info,
+ base::Unretained(&p->blob_or_file_info)));
+ }
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
const IndexedDBKey& primary_key,
- std::string* value) {
+ IndexedDBValue* value) {
DCHECK(dispatcher_host_.get());
DCHECK_NE(kNoCursor, ipc_cursor_id_);
@@ -202,25 +366,37 @@ void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
DCHECK(idb_cursor);
if (!idb_cursor)
return;
- IndexedDBMsg_CallbacksSuccessCursorContinue_Params params;
- params.ipc_thread_id = ipc_thread_id_;
- params.ipc_callbacks_id = ipc_callbacks_id_;
- params.ipc_cursor_id = ipc_cursor_id_;
- params.key = key;
- params.primary_key = primary_key;
+
+ scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorContinue_Params> params(
+ new IndexedDBMsg_CallbacksSuccessCursorContinue_Params());
+ params->ipc_thread_id = ipc_thread_id_;
+ params->ipc_callbacks_id = ipc_callbacks_id_;
+ params->ipc_cursor_id = ipc_cursor_id_;
+ params->key = key;
+ params->primary_key = primary_key;
if (value && !value->empty())
- std::swap(params.value, *value);
+ std::swap(params->value, value->bits);
// TODO(alecflett): Avoid a copy here: the whole params object is
// being copied into the message.
- dispatcher_host_->Send(
- new IndexedDBMsg_CallbacksSuccessCursorContinue(params));
+ if (!value || value->blob_info.empty()) {
+ dispatcher_host_->Send(
+ new IndexedDBMsg_CallbacksSuccessCursorContinue(*params));
+ } else {
+ IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get();
+ FillInBlobData(value->blob_info, &p->blob_or_file_info);
+ RegisterBlobsAndSend(
+ value->blob_info,
+ base::Bind(BlobLookupForCursorContinue, base::Owned(params.release()),
+ dispatcher_host_, value->blob_info,
+ base::Unretained(&p->blob_or_file_info)));
+ }
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccessWithPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
- const std::vector<std::string>& values) {
+ std::vector<IndexedDBValue>& values) {
DCHECK_EQ(keys.size(), primary_keys.size());
DCHECK_EQ(keys.size(), values.size());
@@ -239,19 +415,47 @@ void IndexedDBCallbacks::OnSuccessWithPrefetch(
msgPrimaryKeys.push_back(primary_keys[i]);
}
- IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params params;
- params.ipc_thread_id = ipc_thread_id_;
- params.ipc_callbacks_id = ipc_callbacks_id_;
- params.ipc_cursor_id = ipc_cursor_id_;
- params.keys = msgKeys;
- params.primary_keys = msgPrimaryKeys;
- params.values = values;
- dispatcher_host_->Send(
- new IndexedDBMsg_CallbacksSuccessCursorPrefetch(params));
+ scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params> params(
+ new IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params());
+ params->ipc_thread_id = ipc_thread_id_;
+ params->ipc_callbacks_id = ipc_callbacks_id_;
+ params->ipc_cursor_id = ipc_cursor_id_;
+ params->keys = msgKeys;
+ params->primary_keys = msgPrimaryKeys;
+ std::vector<std::string> values_bits(values.size());
+ std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >
+ values_blob_infos(values.size());
+ std::vector<IndexedDBValue>::iterator iter = values.begin();
+
+ bool found_blob_info = false;
+ for (size_t i = 0; iter != values.end(); ++iter, ++i) {
+ values_bits[i].swap(iter->bits);
+ if (iter->blob_info.size()) {
+ found_blob_info = true;
+ FillInBlobData(iter->blob_info, &values_blob_infos[i]);
+ std::vector<IndexedDBBlobInfo>::const_iterator blob_iter;
+ for (blob_iter = iter->blob_info.begin();
+ blob_iter != iter->blob_info.end(); ++blob_iter) {
+ blob_iter->mark_used_callback().Run();
+ }
+ }
+ }
+
+ params->values.swap(values_bits);
+ params->blob_or_file_infos.swap(values_blob_infos);
+ if (found_blob_info) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(BlobLookupForCursorPrefetch, base::Owned(params.release()),
+ dispatcher_host_, values,
+ base::Unretained(&params->blob_or_file_infos)));
+ } else {
+ dispatcher_host_->Send(
+ new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get()));
+ }
dispatcher_host_ = NULL;
}
-void IndexedDBCallbacks::OnSuccess(std::string* value,
+void IndexedDBCallbacks::OnSuccess(IndexedDBValue* value,
const IndexedDBKey& key,
const IndexedDBKeyPath& key_path) {
DCHECK(dispatcher_host_.get());
@@ -261,37 +465,54 @@ void IndexedDBCallbacks::OnSuccess(std::string* value,
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
- std::string value_copy;
+ scoped_ptr<IndexedDBMsg_CallbacksSuccessValueWithKey_Params> params(new
+ IndexedDBMsg_CallbacksSuccessValueWithKey_Params());
+ params->ipc_thread_id = ipc_thread_id_;
+ params->ipc_callbacks_id = ipc_callbacks_id_;
+ params->primary_key = key;
+ params->key_path = key_path;
if (value && !value->empty())
- std::swap(value_copy, *value);
-
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValueWithKey(
- ipc_thread_id_,
- ipc_callbacks_id_,
- // TODO(alecflett): Avoid a copy here.
- value_copy,
- key,
- key_path));
+ std::swap(params->value, value->bits);
+ if (!value || value->blob_info.empty()) {
+ dispatcher_host_->Send(
+ new IndexedDBMsg_CallbacksSuccessValueWithKey(*params));
+ } else {
+ IndexedDBMsg_CallbacksSuccessValueWithKey_Params* p = params.get();
+ FillInBlobData(value->blob_info, &p->blob_or_file_info);
+ RegisterBlobsAndSend(
+ value->blob_info,
+ base::Bind(BlobLookupForValueWithKey, base::Owned(params.release()),
+ dispatcher_host_, value->blob_info,
+ base::Unretained(&p->blob_or_file_info)));
+ }
dispatcher_host_ = NULL;
}
-void IndexedDBCallbacks::OnSuccess(std::string* value) {
+void IndexedDBCallbacks::OnSuccess(IndexedDBValue* value) {
DCHECK(dispatcher_host_.get());
-
DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
- std::string value_copy;
+ scoped_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params(new
+ IndexedDBMsg_CallbacksSuccessValue_Params());
+ params->ipc_thread_id = ipc_thread_id_;
+ params->ipc_callbacks_id = ipc_callbacks_id_;
if (value && !value->empty())
- std::swap(value_copy, *value);
-
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(
- ipc_thread_id_,
- ipc_callbacks_id_,
- // TODO(alecflett): avoid a copy here.
- value_copy));
+ std::swap(params->value, value->bits);
+ if (!value || value->blob_info.empty()) {
+ dispatcher_host_->Send(
+ new IndexedDBMsg_CallbacksSuccessValue(*params));
+ } else {
+ IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get();
+ FillInBlobData(value->blob_info, &p->blob_or_file_info);
+ RegisterBlobsAndSend(
+ value->blob_info,
+ base::Bind(BlobLookupForValue, base::Owned(params.release()),
+ dispatcher_host_, value->blob_info,
+ base::Unretained(&p->blob_or_file_info)));
+ }
dispatcher_host_ = NULL;
}

Powered by Google App Engine
This is Rietveld 408576698