Index: content/browser/indexed_db/indexed_db_dispatcher_host.cc |
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc |
index 37ab7717e5c437ac0d42a5d7f9a9c8712ae5a280..a750d551e8a4b1b0c4b84e77c2bb292e7b9f6a05 100644 |
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc |
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc |
@@ -15,6 +15,7 @@ |
#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_metadata.h" |
+#include "content/browser/indexed_db/indexed_db_value.h" |
#include "content/browser/renderer_host/render_message_filter.h" |
#include "content/common/indexed_db/indexed_db_messages.h" |
#include "content/public/browser/browser_thread.h" |
@@ -23,6 +24,7 @@ |
#include "content/public/common/result_codes.h" |
#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h" |
#include "url/gurl.h" |
+#include "webkit/browser/blob/blob_storage_context.h" |
#include "webkit/browser/database/database_util.h" |
#include "webkit/common/database/database_identifier.h" |
@@ -32,14 +34,52 @@ using blink::WebIDBKey; |
namespace content { |
IndexedDBDispatcherHost::IndexedDBDispatcherHost( |
- IndexedDBContextImpl* indexed_db_context) |
- : indexed_db_context_(indexed_db_context), |
+ int ipc_process_id, |
+ net::URLRequestContextGetter* request_context_getter, |
+ IndexedDBContextImpl* indexed_db_context, |
+ ChromeBlobStorageContext* blob_storage_context) |
+ : request_context_getter_(request_context_getter), |
+ request_context_(NULL), |
+ indexed_db_context_(indexed_db_context), |
+ blob_storage_context_(blob_storage_context), |
database_dispatcher_host_(new DatabaseDispatcherHost(this)), |
- cursor_dispatcher_host_(new CursorDispatcherHost(this)) { |
+ cursor_dispatcher_host_(new CursorDispatcherHost(this)), |
+ ipc_process_id_(ipc_process_id_) { |
DCHECK(indexed_db_context_); |
} |
-IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {} |
+IndexedDBDispatcherHost::IndexedDBDispatcherHost( |
+ int ipc_process_id, |
+ net::URLRequestContext* request_context, |
+ IndexedDBContextImpl* indexed_db_context, |
+ ChromeBlobStorageContext* blob_storage_context) |
+ : request_context_(request_context), |
+ indexed_db_context_(indexed_db_context), |
+ blob_storage_context_(blob_storage_context), |
+ database_dispatcher_host_(new DatabaseDispatcherHost(this)), |
+ cursor_dispatcher_host_(new CursorDispatcherHost(this)), |
+ ipc_process_id_(ipc_process_id) { |
+ DCHECK(indexed_db_context_); |
+} |
+ |
+IndexedDBDispatcherHost::~IndexedDBDispatcherHost() { |
+ BlobDataHandleMap::iterator iter = blob_data_handle_map_.begin(); |
+ for (; iter != blob_data_handle_map_.end(); ++iter) { |
+ delete iter->second; |
+ } |
+ blob_data_handle_map_.clear(); |
+} |
+ |
+void IndexedDBDispatcherHost::OnChannelConnected(int32 peer_pid) { |
+ BrowserMessageFilter::OnChannelConnected(peer_pid); |
+ |
+ if (request_context_getter_.get()) { |
+ DCHECK(!request_context_); |
+ request_context_ = request_context_getter_->GetURLRequestContext(); |
+ request_context_getter_ = NULL; |
+ DCHECK(request_context_); |
+ } |
+} |
void IndexedDBDispatcherHost::OnChannelClosing() { |
bool success = indexed_db_context_->TaskRunner()->PostTask( |
@@ -76,8 +116,10 @@ void IndexedDBDispatcherHost::ResetDispatcherHosts() { |
base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage( |
const IPC::Message& message) { |
- if (IPC_MESSAGE_CLASS(message) == IndexedDBMsgStart) |
- return indexed_db_context_->TaskRunner(); |
+ if (IPC_MESSAGE_CLASS(message) == IndexedDBMsgStart) { |
+ if (message.type() != IndexedDBHostMsg_DatabasePut::ID) |
+ return indexed_db_context_->TaskRunner(); |
+ } |
return NULL; |
} |
@@ -86,7 +128,8 @@ bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message, |
if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart) |
return false; |
- DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
+ DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread() || |
+ message.type() == IndexedDBHostMsg_DatabasePut::ID); |
bool handled = |
database_dispatcher_host_->OnMessageReceived(message, message_was_ok) || |
@@ -100,6 +143,7 @@ bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message, |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryOpen, OnIDBFactoryOpen) |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryDeleteDatabase, |
OnIDBFactoryDeleteDatabase) |
+ IPC_MESSAGE_HANDLER(IndexedDBHostMsg_AckReceivedBlobs, OnAckReceivedBlobs) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP() |
} |
@@ -166,6 +210,23 @@ uint32 IndexedDBDispatcherHost::TransactionIdToProcessId( |
return (host_transaction_id >> 32) & 0xffffffff; |
} |
+void IndexedDBDispatcherHost::HoldBlobDataHandle( |
+ const std::string& uuid, |
+ scoped_ptr<webkit_blob::BlobDataHandle>& blob_data_handle) { |
+ DCHECK(blob_data_handle_map_.find(uuid) == blob_data_handle_map_.end()); |
+ blob_data_handle_map_[uuid] = blob_data_handle.release(); |
+} |
+ |
+void IndexedDBDispatcherHost::DropBlobDataHandle( |
+ const std::string& uuid) { |
+ BlobDataHandleMap::iterator iter = blob_data_handle_map_.find(uuid); |
+ if (iter != blob_data_handle_map_.end()) { |
+ delete iter->second; |
+ blob_data_handle_map_.erase(iter); |
+ } else { |
+ DLOG(FATAL) << "Failed to find blob UUID in map:" << uuid; |
+ } |
+} |
IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(int32 ipc_cursor_id) { |
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
@@ -226,7 +287,8 @@ void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames( |
new IndexedDBCallbacks( |
this, params.ipc_thread_id, params.ipc_callbacks_id), |
origin_url, |
- indexed_db_path); |
+ indexed_db_path, |
+ Context()->TaskRunner()); |
} |
void IndexedDBDispatcherHost::OnIDBFactoryOpen( |
@@ -253,11 +315,14 @@ void IndexedDBDispatcherHost::OnIDBFactoryOpen( |
this, params.ipc_thread_id, params.ipc_database_callbacks_id); |
Context()->GetIDBFactory()->Open(params.name, |
params.version, |
+ request_context_, |
host_transaction_id, |
callbacks, |
database_callbacks, |
origin_url, |
- indexed_db_path); |
+ indexed_db_path, |
+ ipc_process_id_, |
+ Context()->TaskRunner()); |
} |
void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase( |
@@ -268,10 +333,27 @@ void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase( |
base::FilePath indexed_db_path = indexed_db_context_->data_path(); |
Context()->GetIDBFactory()->DeleteDatabase( |
params.name, |
+ request_context_, |
new IndexedDBCallbacks( |
this, params.ipc_thread_id, params.ipc_callbacks_id), |
origin_url, |
- indexed_db_path); |
+ indexed_db_path, |
+ Context()->TaskRunner()); |
+} |
+ |
+void IndexedDBDispatcherHost::OnAckReceivedBlobs( |
+ const std::vector<std::string>& uuids) { |
+ DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
+ std::vector<std::string>::const_iterator iter; |
+ for (iter = uuids.begin(); iter != uuids.end(); ++iter) { |
+ DropBlobDataHandle(*iter); |
+ } |
+} |
+ |
+void IndexedDBDispatcherHost::OnPutHelper( |
+ const IndexedDBHostMsg_DatabasePut_Params& params, |
+ std::vector<webkit_blob::BlobDataHandle*> handles) { |
+ database_dispatcher_host_->OnPut(params, handles); |
} |
void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id, |
@@ -383,8 +465,10 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() { |
bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( |
const IPC::Message& message, |
bool* msg_is_ok) { |
- DCHECK( |
+ |
+ DCHECK((message.type() == IndexedDBHostMsg_DatabasePut::ID) || |
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
+ |
bool handled = true; |
IPC_BEGIN_MESSAGE_MAP_EX( |
IndexedDBDispatcherHost::DatabaseDispatcherHost, message, *msg_is_ok) |
@@ -397,7 +481,7 @@ bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClose, OnClose) |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDestroyed, OnDestroyed) |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGet, OnGet) |
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabasePut, OnPut) |
+ IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabasePut, OnPutWrapper) |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexKeys, OnSetIndexKeys) |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexesReady, |
OnSetIndexesReady) |
@@ -411,6 +495,7 @@ bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCommit, OnCommit) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP() |
+ |
return handled; |
} |
@@ -518,30 +603,68 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet( |
callbacks); |
} |
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut( |
+void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPutWrapper( |
const IndexedDBHostMsg_DatabasePut_Params& params) { |
+ std::vector<webkit_blob::BlobDataHandle*> handles; |
+ for (size_t i=0; i < params.blob_or_file_info.size(); ++i) { |
+ const IndexedDBMsg_BlobOrFileInfo& info = params.blob_or_file_info[i]; |
+ handles.push_back( |
+ parent_->blob_storage_context_->context()->GetBlobDataFromUUID( |
+ info.uuid).release()); |
+ } |
+ parent_->indexed_db_context_->TaskRunner()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&IndexedDBDispatcherHost::OnPutHelper, parent_, |
+ params, handles)); |
+} |
+ |
+void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut( |
+ const IndexedDBHostMsg_DatabasePut_Params& params, |
+ std::vector<webkit_blob::BlobDataHandle*> handles) { |
+ |
DCHECK( |
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
IndexedDBConnection* connection = |
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); |
+ // TODO(ericu): Do we need to delete handles here? |
if (!connection || !connection->IsConnected()) |
return; |
scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks( |
parent_, params.ipc_thread_id, params.ipc_callbacks_id)); |
int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); |
+ |
+ std::vector<IndexedDBBlobInfo> blob_info(params.blob_or_file_info.size()); |
+ |
+ for (size_t i=0; i < params.blob_or_file_info.size(); ++i) { |
+ const IndexedDBMsg_BlobOrFileInfo& info = params.blob_or_file_info[i]; |
+ if (info.is_file) |
+ blob_info[i] = |
+ IndexedDBBlobInfo(base::FilePath::FromUTF16Unsafe(info.file_path), |
+ info.file_name, info.mime_type); |
+ else |
+ blob_info[i] = IndexedDBBlobInfo(info.uuid, info.mime_type, info.size); |
+ } |
// TODO(alecflett): Avoid a copy here. |
- std::string value_copy(params.value); |
+ IndexedDBValue value; |
+ value.bits = params.value; |
+ value.blob_info.swap(blob_info); |
connection->database()->Put( |
host_transaction_id, |
params.object_store_id, |
- &value_copy, |
+ &value, |
+ &handles, |
make_scoped_ptr(new IndexedDBKey(params.key)), |
static_cast<IndexedDBDatabase::PutMode>(params.put_mode), |
callbacks, |
params.index_ids, |
params.index_keys); |
+ if (handles.size()) { // Put failed before transferring ownership of handles. |
+ std::vector<webkit_blob::BlobDataHandle*>::iterator iter; |
+ for (iter = handles.begin(); iter != handles.end(); ++iter) |
+ delete *iter; |
+ } |
TransactionIDToSizeMap* map = |
&parent_->database_dispatcher_host_->transaction_size_map_; |
// Size can't be big enough to overflow because it represents the |
@@ -764,9 +887,6 @@ IndexedDBDispatcherHost::CursorDispatcherHost::~CursorDispatcherHost() {} |
bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived( |
const IPC::Message& message, |
bool* msg_is_ok) { |
- DCHECK( |
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
- |
bool handled = true; |
IPC_BEGIN_MESSAGE_MAP_EX( |
IndexedDBDispatcherHost::CursorDispatcherHost, message, *msg_is_ok) |
@@ -777,6 +897,10 @@ bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived( |
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDestroyed, OnDestroyed) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP() |
+ |
+ DCHECK(!handled || |
+ parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
+ |
return handled; |
} |