diff options
author | ericu@chromium.org <ericu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-18 04:58:03 +0000 |
---|---|---|
committer | ericu@chromium.org <ericu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-18 04:58:03 +0000 |
commit | 897519a48c99efae0e07372d807878309dab3f38 (patch) | |
tree | 120b81d56e8f0e5208d9132f029d056ef2f274dc /content/browser/indexed_db/indexed_db_callbacks.cc | |
parent | 9efc4ac50ab7eeefaa8f3e321790329f90996345 (diff) | |
download | chromium_src-897519a48c99efae0e07372d807878309dab3f38.zip chromium_src-897519a48c99efae0e07372d807878309dab3f38.tar.gz chromium_src-897519a48c99efae0e07372d807878309dab3f38.tar.bz2 |
Complete registration of blobs before sending back an indexed DB value that contains them.
BUG=108012
Review URL: https://codereview.chromium.org/238043007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264728 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/indexed_db/indexed_db_callbacks.cc')
-rw-r--r-- | content/browser/indexed_db/indexed_db_callbacks.cc | 303 |
1 files changed, 258 insertions, 45 deletions
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc index f4c3487..ad5551f 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(¶ms->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; } |