Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / indexed_db / indexed_db_dispatcher_host.cc
index b627393..4f49b0e 100644 (file)
@@ -7,9 +7,11 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
+#include "base/memory/scoped_vector.h"
 #include "base/process/process.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/indexed_db/indexed_db_callbacks.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
@@ -26,6 +28,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"
 
@@ -35,11 +38,33 @@ using blink::WebIDBKey;
 namespace content {
 
 IndexedDBDispatcherHost::IndexedDBDispatcherHost(
-    IndexedDBContextImpl* indexed_db_context)
+    int ipc_process_id,
+    net::URLRequestContextGetter* request_context_getter,
+    IndexedDBContextImpl* indexed_db_context,
+    ChromeBlobStorageContext* blob_storage_context)
     : BrowserMessageFilter(IndexedDBMsgStart),
+      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(
+    int ipc_process_id,
+    net::URLRequestContext* request_context,
+    IndexedDBContextImpl* indexed_db_context,
+    ChromeBlobStorageContext* blob_storage_context)
+    : BrowserMessageFilter(IndexedDBMsgStart),
+      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_);
 }
 
@@ -47,6 +72,17 @@ IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {
   STLDeleteValues(&blob_data_handle_map_);
 }
 
+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(
       FROM_HERE,
@@ -82,7 +118,8 @@ void IndexedDBDispatcherHost::ResetDispatcherHosts() {
 
 base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage(
     const IPC::Message& message) {
-  if (IPC_MESSAGE_CLASS(message) == IndexedDBMsgStart)
+  if (IPC_MESSAGE_CLASS(message) == IndexedDBMsgStart &&
+      message.type() != IndexedDBHostMsg_DatabasePut::ID)
     return indexed_db_context_->TaskRunner();
   return NULL;
 }
@@ -92,7 +129,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) ||
@@ -176,7 +214,7 @@ uint32 IndexedDBDispatcherHost::TransactionIdToProcessId(
 void IndexedDBDispatcherHost::HoldBlobDataHandle(
     const std::string& uuid,
     scoped_ptr<webkit_blob::BlobDataHandle>& blob_data_handle) {
-  DCHECK(ContainsKey(blob_data_handle_map_, uuid));
+  DCHECK(!ContainsKey(blob_data_handle_map_, uuid));
   blob_data_handle_map_[uuid] = blob_data_handle.release();
 }
 
@@ -249,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,
+      request_context_);
 }
 
 void IndexedDBDispatcherHost::OnIDBFactoryOpen(
@@ -276,11 +315,12 @@ void IndexedDBDispatcherHost::OnIDBFactoryOpen(
           this, params.ipc_thread_id, params.ipc_database_callbacks_id);
   IndexedDBPendingConnection connection(callbacks,
                                         database_callbacks,
-                                        0 /* TODO(ericu) ipc_process_id */,
+                                        ipc_process_id_,
                                         host_transaction_id,
                                         params.version);
+  DCHECK(request_context_);
   Context()->GetIDBFactory()->Open(
-      params.name, connection, origin_url, indexed_db_path);
+      params.name, connection, request_context_, origin_url, indexed_db_path);
 }
 
 void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
@@ -289,14 +329,24 @@ void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
   GURL origin_url =
       webkit_database::GetOriginFromIdentifier(params.database_identifier);
   base::FilePath indexed_db_path = indexed_db_context_->data_path();
+  DCHECK(request_context_);
   Context()->GetIDBFactory()->DeleteDatabase(
       params.name,
+      request_context_,
       new IndexedDBCallbacks(
           this, params.ipc_thread_id, params.ipc_callbacks_id),
       origin_url,
       indexed_db_path);
 }
 
+// OnPutHelper exists only to allow us to hop threads while holding a reference
+// to the IndexedDBDispatcherHost.
+void IndexedDBDispatcherHost::OnPutHelper(
+    const IndexedDBHostMsg_DatabasePut_Params& params,
+    std::vector<webkit_blob::BlobDataHandle*> handles) {
+  database_dispatcher_host_->OnPut(params, handles);
+}
+
 void IndexedDBDispatcherHost::OnAckReceivedBlobs(
     const std::vector<std::string>& uuids) {
   DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
@@ -414,8 +464,11 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() {
 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
     const IPC::Message& message,
     bool* msg_is_ok) {
+
   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)
@@ -428,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)
@@ -442,6 +495,7 @@ bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCommit, OnCommit)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
+
   return handled;
 }
 
@@ -551,11 +605,31 @@ 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());
 
+  ScopedVector<webkit_blob::BlobDataHandle> scoped_handles;
+  scoped_handles.swap(handles);
+
   IndexedDBConnection* connection =
       parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
   if (!connection || !connection->IsConnected())
@@ -564,13 +638,36 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut(
       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());
+
+  ChildProcessSecurityPolicyImpl* policy =
+      ChildProcessSecurityPolicyImpl::GetInstance();
+
+  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) {
+      base::FilePath path = base::FilePath::FromUTF16Unsafe(info.file_path);
+      if (!policy->CanReadFile(parent_->ipc_process_id_, path)) {
+        parent_->BadMessageReceived();
+        return;
+      }
+      blob_info[i] =
+          IndexedDBBlobInfo(info.uuid, 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.
   IndexedDBValue value;
   value.bits = params.value;
+  value.blob_info.swap(blob_info);
   connection->database()->Put(
       host_transaction_id,
       params.object_store_id,
       &value,
+      &scoped_handles,
       make_scoped_ptr(new IndexedDBKey(params.key)),
       static_cast<IndexedDBDatabase::PutMode>(params.put_mode),
       callbacks,
@@ -787,9 +884,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)
@@ -800,6 +894,11 @@ 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;
 }
 
@@ -872,7 +971,11 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset(
   if (!idb_cursor)
     return;
 
-  idb_cursor->PrefetchReset(used_prefetches, unused_prefetches);
+  leveldb::Status s =
+      idb_cursor->PrefetchReset(used_prefetches, unused_prefetches);
+  // TODO(cmumford): Handle this error (crbug.com/363397)
+  if (!s.ok())
+    DLOG(ERROR) << "Unable to reset prefetch";
 }
 
 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed(