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

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

Issue 238043007: Complete registration of blobs before sending back an indexed DB value that contains them. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Ran clang-format Created 6 years, 8 months 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
« no previous file with comments | « content/browser/indexed_db/indexed_db_callbacks.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 f4c348765b3495e32af1580d0b84e330629131c8..ad5551f388417da4d261297fc6fa0111183b034b 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -6,7 +6,14 @@
#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"
@@ -14,7 +21,12 @@
#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 {
@@ -169,6 +181,119 @@ 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) {
+ DCHECK_EQ(blob_info.size(), blob_or_file_info->size());
+ 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;
+}
+
+template <class ParamType, class MsgType>
+static void CreateBlobsAndSend(
+ ParamType* 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 MsgType(*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_EQ(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,
@@ -182,18 +307,32 @@ void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
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->bits);
+ 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(
+ CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params,
+ IndexedDBMsg_CallbacksSuccessIDBCursor>,
+ base::Owned(params.release()),
+ dispatcher_host_,
+ value->blob_info,
+ base::Unretained(&p->blob_or_file_info)));
+ }
dispatcher_host_ = NULL;
}
@@ -214,25 +353,41 @@ 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->bits);
+ 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(CreateBlobsAndSend<
+ IndexedDBMsg_CallbacksSuccessCursorContinue_Params,
+ IndexedDBMsg_CallbacksSuccessCursorContinue>,
+ 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<IndexedDBValue>& values) {
+ std::vector<IndexedDBValue>& values) {
DCHECK_EQ(keys.size(), primary_keys.size());
DCHECK_EQ(keys.size(), values.size());
@@ -252,17 +407,48 @@ 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;
- std::vector<IndexedDBValue>::const_iterator iter;
- for (iter = values.begin(); iter != values.end(); ++iter)
- params.values.push_back(iter->bits);
- 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 = params->values;
+ values_bits.resize(values.size());
+ std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >& values_blob_infos =
+ params->blob_or_file_infos;
+ values_blob_infos.resize(values.size());
+
+ bool found_blob_info = false;
+ std::vector<IndexedDBValue>::iterator iter = values.begin();
+ 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();
+ }
+ }
+ }
+
+ 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;
}
@@ -277,34 +463,61 @@ void IndexedDBCallbacks::OnSuccess(IndexedDBValue* value,
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
- IndexedDBMsg_CallbacksSuccessValueWithKey_Params params;
- params.ipc_thread_id = ipc_thread_id_;
- params.ipc_callbacks_id = ipc_callbacks_id_;
- params.primary_key = key;
- params.key_path = key_path;
+ 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(params.value, value->bits);
-
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValueWithKey(params));
+ 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(
+ CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValueWithKey_Params,
+ IndexedDBMsg_CallbacksSuccessValueWithKey>,
+ base::Owned(params.release()),
+ dispatcher_host_,
+ value->blob_info,
+ base::Unretained(&p->blob_or_file_info)));
+ }
dispatcher_host_ = NULL;
}
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_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
- IndexedDBMsg_CallbacksSuccessValue_Params params;
- params.ipc_thread_id = ipc_thread_id_;
- params.ipc_callbacks_id = ipc_callbacks_id_;
+ 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(params.value, value->bits);
-
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(params));
+ 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(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params,
+ IndexedDBMsg_CallbacksSuccessValue>,
+ base::Owned(params.release()),
+ dispatcher_host_,
+ value->blob_info,
+ base::Unretained(&p->blob_or_file_info)));
+ }
dispatcher_host_ = NULL;
}
« no previous file with comments | « content/browser/indexed_db/indexed_db_callbacks.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698