| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/command_line.h" | |
| 11 #include "base/files/file_path.h" | |
| 12 #include "base/process.h" | |
| 13 #include "base/process_util.h" | |
| 14 #include "base/strings/utf_string_conversions.h" | |
| 15 #include "content/browser/in_process_webkit/indexed_db_callbacks.h" | |
| 16 #include "content/browser/in_process_webkit/indexed_db_database_callbacks.h" | |
| 17 #include "content/browser/indexed_db/indexed_db_context_impl.h" | |
| 18 #include "content/browser/indexed_db/indexed_db_metadata.h" | |
| 19 #include "content/browser/indexed_db/webidbcursor_impl.h" | |
| 20 #include "content/browser/indexed_db/webidbcursor_impl.h" | |
| 21 #include "content/browser/indexed_db/webidbdatabase_impl.h" | |
| 22 #include "content/browser/renderer_host/render_message_filter.h" | |
| 23 #include "content/common/indexed_db/indexed_db_messages.h" | |
| 24 #include "content/public/browser/browser_thread.h" | |
| 25 #include "content/public/browser/user_metrics.h" | |
| 26 #include "content/public/common/content_switches.h" | |
| 27 #include "content/public/common/result_codes.h" | |
| 28 #include "googleurl/src/gurl.h" | |
| 29 #include "third_party/WebKit/public/platform/WebIDBDatabase.h" | |
| 30 #include "third_party/WebKit/public/platform/WebIDBDatabaseError.h" | |
| 31 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h" | |
| 32 #include "webkit/browser/database/database_util.h" | |
| 33 #include "webkit/common/database/database_identifier.h" | |
| 34 | |
| 35 using webkit_database::DatabaseUtil; | |
| 36 using WebKit::WebIDBDatabaseError; | |
| 37 using WebKit::WebIDBKey; | |
| 38 | |
| 39 namespace content { | |
| 40 | |
| 41 IndexedDBDispatcherHost::IndexedDBDispatcherHost( | |
| 42 int ipc_process_id, | |
| 43 IndexedDBContextImpl* indexed_db_context) | |
| 44 : indexed_db_context_(indexed_db_context), | |
| 45 database_dispatcher_host_(new DatabaseDispatcherHost(this)), | |
| 46 cursor_dispatcher_host_(new CursorDispatcherHost(this)), | |
| 47 ipc_process_id_(ipc_process_id) { | |
| 48 DCHECK(indexed_db_context_.get()); | |
| 49 } | |
| 50 | |
| 51 IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {} | |
| 52 | |
| 53 void IndexedDBDispatcherHost::OnChannelClosing() { | |
| 54 BrowserMessageFilter::OnChannelClosing(); | |
| 55 | |
| 56 bool success = indexed_db_context_->TaskRunner()->PostTask( | |
| 57 FROM_HERE, | |
| 58 base::Bind(&IndexedDBDispatcherHost::ResetDispatcherHosts, this)); | |
| 59 | |
| 60 if (!success) | |
| 61 ResetDispatcherHosts(); | |
| 62 } | |
| 63 | |
| 64 void IndexedDBDispatcherHost::OnDestruct() const { | |
| 65 // The last reference to the dispatcher may be a posted task, which would | |
| 66 // be destructed on the IndexedDB thread. Without this override, that would | |
| 67 // take the dispatcher with it. Since the dispatcher may be keeping the | |
| 68 // IndexedDBContext alive, it might be destructed to on its own thread, | |
| 69 // which is not supported. Ensure destruction runs on the IO thread instead. | |
| 70 BrowserThread::DeleteOnIOThread::Destruct(this); | |
| 71 } | |
| 72 | |
| 73 void IndexedDBDispatcherHost::ResetDispatcherHosts() { | |
| 74 // It is important that the various *_dispatcher_host_ members are reset | |
| 75 // on the IndexedDB thread, since there might be incoming messages on that | |
| 76 // thread, and we must not reset the dispatcher hosts until after those | |
| 77 // messages are processed. | |
| 78 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 79 | |
| 80 // Note that we explicitly separate CloseAll() from destruction of the | |
| 81 // DatabaseDispatcherHost, since CloseAll() can invoke callbacks which need to | |
| 82 // be dispatched through database_dispatcher_host_. | |
| 83 database_dispatcher_host_->CloseAll(); | |
| 84 database_dispatcher_host_.reset(); | |
| 85 cursor_dispatcher_host_.reset(); | |
| 86 } | |
| 87 | |
| 88 base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage( | |
| 89 const IPC::Message& message) { | |
| 90 if (IPC_MESSAGE_CLASS(message) == IndexedDBMsgStart) | |
| 91 return indexed_db_context_->TaskRunner(); | |
| 92 return NULL; | |
| 93 } | |
| 94 | |
| 95 bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message, | |
| 96 bool* message_was_ok) { | |
| 97 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart) | |
| 98 return false; | |
| 99 | |
| 100 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 101 | |
| 102 bool handled = | |
| 103 database_dispatcher_host_->OnMessageReceived(message, message_was_ok) || | |
| 104 cursor_dispatcher_host_->OnMessageReceived(message, message_was_ok); | |
| 105 | |
| 106 if (!handled) { | |
| 107 handled = true; | |
| 108 IPC_BEGIN_MESSAGE_MAP_EX(IndexedDBDispatcherHost, message, *message_was_ok) | |
| 109 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryGetDatabaseNames, | |
| 110 OnIDBFactoryGetDatabaseNames) | |
| 111 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryOpen, OnIDBFactoryOpen) | |
| 112 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryDeleteDatabase, | |
| 113 OnIDBFactoryDeleteDatabase) | |
| 114 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 115 IPC_END_MESSAGE_MAP() | |
| 116 } | |
| 117 return handled; | |
| 118 } | |
| 119 | |
| 120 int32 IndexedDBDispatcherHost::Add(WebIDBCursorImpl* idb_cursor) { | |
| 121 if (!cursor_dispatcher_host_) { | |
| 122 delete idb_cursor; | |
| 123 return 0; | |
| 124 } | |
| 125 return cursor_dispatcher_host_->map_.Add(idb_cursor); | |
| 126 } | |
| 127 | |
| 128 int32 IndexedDBDispatcherHost::Add(WebIDBDatabaseImpl* idb_database, | |
| 129 int32 ipc_thread_id, | |
| 130 const GURL& origin_url) { | |
| 131 if (!database_dispatcher_host_) { | |
| 132 delete idb_database; | |
| 133 return 0; | |
| 134 } | |
| 135 int32 ipc_database_id = database_dispatcher_host_->map_.Add(idb_database); | |
| 136 Context()->ConnectionOpened(origin_url, idb_database); | |
| 137 database_dispatcher_host_->database_url_map_[ipc_database_id] = origin_url; | |
| 138 return ipc_database_id; | |
| 139 } | |
| 140 | |
| 141 void IndexedDBDispatcherHost::RegisterTransactionId(int64 host_transaction_id, | |
| 142 const GURL& url) { | |
| 143 if (!database_dispatcher_host_) | |
| 144 return; | |
| 145 database_dispatcher_host_->transaction_url_map_[host_transaction_id] = url; | |
| 146 } | |
| 147 | |
| 148 int64 IndexedDBDispatcherHost::HostTransactionId(int64 transaction_id) { | |
| 149 // Inject the renderer process id into the transaction id, to | |
| 150 // uniquely identify this transaction, and effectively bind it to | |
| 151 // the renderer that initiated it. The lower 32 bits of | |
| 152 // transaction_id are guaranteed to be unique within that renderer. | |
| 153 base::ProcessId pid = base::GetProcId(peer_handle()); | |
| 154 DCHECK(!(transaction_id >> 32)) << "Transaction ids can only be 32 bits"; | |
| 155 COMPILE_ASSERT(sizeof(base::ProcessId) <= sizeof(int32), | |
| 156 Process_ID_must_fit_in_32_bits); | |
| 157 | |
| 158 return transaction_id | (static_cast<uint64>(pid) << 32); | |
| 159 } | |
| 160 | |
| 161 int64 IndexedDBDispatcherHost::RendererTransactionId( | |
| 162 int64 host_transaction_id) { | |
| 163 DCHECK(host_transaction_id >> 32 == base::GetProcId(peer_handle())) | |
| 164 << "Invalid renderer target for transaction id"; | |
| 165 return host_transaction_id & 0xffffffff; | |
| 166 } | |
| 167 | |
| 168 WebIDBCursorImpl* IndexedDBDispatcherHost::GetCursorFromId( | |
| 169 int32 ipc_cursor_id) { | |
| 170 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 171 return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id); | |
| 172 } | |
| 173 | |
| 174 ::IndexedDBDatabaseMetadata IndexedDBDispatcherHost::ConvertMetadata( | |
| 175 const content::IndexedDBDatabaseMetadata& web_metadata) { | |
| 176 ::IndexedDBDatabaseMetadata metadata; | |
| 177 metadata.id = web_metadata.id; | |
| 178 metadata.name = web_metadata.name; | |
| 179 metadata.version = web_metadata.version; | |
| 180 metadata.int_version = web_metadata.int_version; | |
| 181 metadata.max_object_store_id = web_metadata.max_object_store_id; | |
| 182 | |
| 183 for (content::IndexedDBDatabaseMetadata::ObjectStoreMap::const_iterator iter = | |
| 184 web_metadata.object_stores.begin(); | |
| 185 iter != web_metadata.object_stores.end(); | |
| 186 ++iter) { | |
| 187 | |
| 188 const content::IndexedDBObjectStoreMetadata& web_store_metadata = | |
| 189 iter->second; | |
| 190 ::IndexedDBObjectStoreMetadata idb_store_metadata; | |
| 191 idb_store_metadata.id = web_store_metadata.id; | |
| 192 idb_store_metadata.name = web_store_metadata.name; | |
| 193 idb_store_metadata.keyPath = web_store_metadata.key_path; | |
| 194 idb_store_metadata.autoIncrement = web_store_metadata.auto_increment; | |
| 195 idb_store_metadata.max_index_id = web_store_metadata.max_index_id; | |
| 196 | |
| 197 for (content::IndexedDBObjectStoreMetadata::IndexMap::const_iterator | |
| 198 index_iter = web_store_metadata.indexes.begin(); | |
| 199 index_iter != web_store_metadata.indexes.end(); | |
| 200 ++index_iter) { | |
| 201 const content::IndexedDBIndexMetadata& web_index_metadata = | |
| 202 index_iter->second; | |
| 203 ::IndexedDBIndexMetadata idb_index_metadata; | |
| 204 idb_index_metadata.id = web_index_metadata.id; | |
| 205 idb_index_metadata.name = web_index_metadata.name; | |
| 206 idb_index_metadata.keyPath = web_index_metadata.key_path; | |
| 207 idb_index_metadata.unique = web_index_metadata.unique; | |
| 208 idb_index_metadata.multiEntry = web_index_metadata.multi_entry; | |
| 209 idb_store_metadata.indexes.push_back(idb_index_metadata); | |
| 210 } | |
| 211 metadata.object_stores.push_back(idb_store_metadata); | |
| 212 } | |
| 213 return metadata; | |
| 214 } | |
| 215 | |
| 216 void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames( | |
| 217 const IndexedDBHostMsg_FactoryGetDatabaseNames_Params& params) { | |
| 218 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 219 base::FilePath indexed_db_path = indexed_db_context_->data_path(); | |
| 220 | |
| 221 Context()->GetIDBFactory()->getDatabaseNames( | |
| 222 new IndexedDBCallbacks<std::vector<string16> >( | |
| 223 this, params.ipc_thread_id, params.ipc_callbacks_id), | |
| 224 WebKit::WebString::fromUTF8(params.database_identifier), | |
| 225 indexed_db_path.AsUTF16Unsafe()); | |
| 226 } | |
| 227 | |
| 228 void IndexedDBDispatcherHost::OnIDBFactoryOpen( | |
| 229 const IndexedDBHostMsg_FactoryOpen_Params& params) { | |
| 230 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 231 base::FilePath indexed_db_path = indexed_db_context_->data_path(); | |
| 232 | |
| 233 GURL origin_url = | |
| 234 webkit_database::GetOriginFromIdentifier(params.database_identifier); | |
| 235 | |
| 236 int64 host_transaction_id = HostTransactionId(params.transaction_id); | |
| 237 | |
| 238 // TODO(dgrogan): Don't let a non-existing database be opened (and therefore | |
| 239 // created) if this origin is already over quota. | |
| 240 Context()->GetIDBFactory() | |
| 241 ->open(params.name, | |
| 242 params.version, | |
| 243 host_transaction_id, | |
| 244 new IndexedDBCallbacksDatabase(this, | |
| 245 params.ipc_thread_id, | |
| 246 params.ipc_callbacks_id, | |
| 247 params.ipc_database_callbacks_id, | |
| 248 host_transaction_id, | |
| 249 origin_url), | |
| 250 new IndexedDBDatabaseCallbacks( | |
| 251 this, params.ipc_thread_id, params.ipc_database_callbacks_id), | |
| 252 WebKit::WebString::fromUTF8(params.database_identifier), | |
| 253 indexed_db_path.AsUTF16Unsafe()); | |
| 254 } | |
| 255 | |
| 256 void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase( | |
| 257 const IndexedDBHostMsg_FactoryDeleteDatabase_Params& params) { | |
| 258 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 259 base::FilePath indexed_db_path = indexed_db_context_->data_path(); | |
| 260 | |
| 261 Context()->GetIDBFactory() | |
| 262 ->deleteDatabase(params.name, | |
| 263 new IndexedDBCallbacks<std::vector<char> >( | |
| 264 this, params.ipc_thread_id, params.ipc_callbacks_id), | |
| 265 WebKit::WebString::fromUTF8(params.database_identifier), | |
| 266 indexed_db_path.AsUTF16Unsafe()); | |
| 267 } | |
| 268 | |
| 269 void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id, | |
| 270 bool committed) { | |
| 271 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 272 TransactionIDToURLMap& transaction_url_map = | |
| 273 database_dispatcher_host_->transaction_url_map_; | |
| 274 TransactionIDToSizeMap& transaction_size_map = | |
| 275 database_dispatcher_host_->transaction_size_map_; | |
| 276 TransactionIDToDatabaseIDMap& transaction_database_map = | |
| 277 database_dispatcher_host_->transaction_database_map_; | |
| 278 if (committed) | |
| 279 Context()->TransactionComplete(transaction_url_map[host_transaction_id]); | |
| 280 // It's unclear if std::map::erase(key) has defined behavior if the | |
| 281 // key is not found. | |
| 282 // TODO(alecflett): Remove if it is proven that it is safe. | |
| 283 if (transaction_url_map.find(host_transaction_id) != | |
| 284 transaction_url_map.end()) | |
| 285 transaction_url_map.erase(host_transaction_id); | |
| 286 if (transaction_size_map.find(host_transaction_id) != | |
| 287 transaction_size_map.end()) | |
| 288 transaction_size_map.erase(host_transaction_id); | |
| 289 if (transaction_database_map.find(host_transaction_id) != | |
| 290 transaction_database_map.end()) | |
| 291 transaction_database_map.erase(host_transaction_id); | |
| 292 } | |
| 293 | |
| 294 ////////////////////////////////////////////////////////////////////// | |
| 295 // Helper templates. | |
| 296 // | |
| 297 | |
| 298 template <typename ObjectType> | |
| 299 ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess( | |
| 300 IDMap<ObjectType, IDMapOwnPointer>* map, | |
| 301 int32 ipc_return_object_id) { | |
| 302 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 303 ObjectType* return_object = map->Lookup(ipc_return_object_id); | |
| 304 if (!return_object) { | |
| 305 NOTREACHED() << "Uh oh, couldn't find object with id " | |
| 306 << ipc_return_object_id; | |
| 307 RecordAction(UserMetricsAction("BadMessageTerminate_IDBMF")); | |
| 308 BadMessageReceived(); | |
| 309 } | |
| 310 return return_object; | |
| 311 } | |
| 312 | |
| 313 template <typename ObjectType> | |
| 314 void IndexedDBDispatcherHost::DestroyObject( | |
| 315 IDMap<ObjectType, IDMapOwnPointer>* map, | |
| 316 int32 ipc_object_id) { | |
| 317 GetOrTerminateProcess(map, ipc_object_id); | |
| 318 map->Remove(ipc_object_id); | |
| 319 } | |
| 320 | |
| 321 ////////////////////////////////////////////////////////////////////// | |
| 322 // IndexedDBDispatcherHost::DatabaseDispatcherHost | |
| 323 // | |
| 324 | |
| 325 IndexedDBDispatcherHost::DatabaseDispatcherHost::DatabaseDispatcherHost( | |
| 326 IndexedDBDispatcherHost* parent) | |
| 327 : parent_(parent) { | |
| 328 map_.set_check_on_null_data(true); | |
| 329 } | |
| 330 | |
| 331 IndexedDBDispatcherHost::DatabaseDispatcherHost::~DatabaseDispatcherHost() { | |
| 332 // TODO(alecflett): uncomment these when we find the source of these leaks. | |
| 333 // DCHECK(transaction_size_map_.empty()); | |
| 334 // DCHECK(transaction_url_map_.empty()); | |
| 335 } | |
| 336 | |
| 337 void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() { | |
| 338 DCHECK( | |
| 339 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 340 // Abort outstanding transactions started by connections in the associated | |
| 341 // front-end to unblock later transactions. This should only occur on unclean | |
| 342 // (crash) or abrupt (process-kill) shutdowns. | |
| 343 for (TransactionIDToDatabaseIDMap::iterator iter = | |
| 344 transaction_database_map_.begin(); | |
| 345 iter != transaction_database_map_.end();) { | |
| 346 int64 transaction_id = iter->first; | |
| 347 int32 ipc_database_id = iter->second; | |
| 348 ++iter; | |
| 349 WebIDBDatabaseImpl* database = map_.Lookup(ipc_database_id); | |
| 350 if (database) { | |
| 351 database->abort( | |
| 352 transaction_id, | |
| 353 WebIDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError)); | |
| 354 } | |
| 355 } | |
| 356 DCHECK(transaction_database_map_.empty()); | |
| 357 | |
| 358 for (WebIDBObjectIDToURLMap::iterator iter = database_url_map_.begin(); | |
| 359 iter != database_url_map_.end(); | |
| 360 iter++) { | |
| 361 WebIDBDatabaseImpl* database = map_.Lookup(iter->first); | |
| 362 if (database) { | |
| 363 database->close(); | |
| 364 parent_->Context()->ConnectionClosed(iter->second, database); | |
| 365 } | |
| 366 } | |
| 367 } | |
| 368 | |
| 369 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( | |
| 370 const IPC::Message& message, | |
| 371 bool* msg_is_ok) { | |
| 372 DCHECK( | |
| 373 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 374 bool handled = true; | |
| 375 IPC_BEGIN_MESSAGE_MAP_EX( | |
| 376 IndexedDBDispatcherHost::DatabaseDispatcherHost, message, *msg_is_ok) | |
| 377 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateObjectStore, | |
| 378 OnCreateObjectStore) | |
| 379 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteObjectStore, | |
| 380 OnDeleteObjectStore) | |
| 381 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction, | |
| 382 OnCreateTransaction) | |
| 383 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClose, OnClose) | |
| 384 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDestroyed, OnDestroyed) | |
| 385 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGet, OnGet) | |
| 386 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabasePut, OnPut) | |
| 387 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexKeys, OnSetIndexKeys) | |
| 388 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexesReady, | |
| 389 OnSetIndexesReady) | |
| 390 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseOpenCursor, OnOpenCursor) | |
| 391 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCount, OnCount) | |
| 392 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteRange, OnDeleteRange) | |
| 393 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClear, OnClear) | |
| 394 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateIndex, OnCreateIndex) | |
| 395 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteIndex, OnDeleteIndex) | |
| 396 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseAbort, OnAbort) | |
| 397 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCommit, OnCommit) | |
| 398 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 399 IPC_END_MESSAGE_MAP() | |
| 400 return handled; | |
| 401 } | |
| 402 | |
| 403 void IndexedDBDispatcherHost::DatabaseDispatcherHost::Send( | |
| 404 IPC::Message* message) { | |
| 405 parent_->Send(message); | |
| 406 } | |
| 407 | |
| 408 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateObjectStore( | |
| 409 const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params) { | |
| 410 DCHECK( | |
| 411 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 412 WebIDBDatabaseImpl* database = | |
| 413 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 414 if (!database) | |
| 415 return; | |
| 416 | |
| 417 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
| 418 database->createObjectStore(host_transaction_id, | |
| 419 params.object_store_id, | |
| 420 params.name, | |
| 421 params.key_path, | |
| 422 params.auto_increment); | |
| 423 if (parent_->Context()->IsOverQuota( | |
| 424 database_url_map_[params.ipc_database_id])) { | |
| 425 database->abort( | |
| 426 host_transaction_id, | |
| 427 WebIDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError)); | |
| 428 } | |
| 429 } | |
| 430 | |
| 431 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteObjectStore( | |
| 432 int32 ipc_database_id, | |
| 433 int64 transaction_id, | |
| 434 int64 object_store_id) { | |
| 435 DCHECK( | |
| 436 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 437 WebIDBDatabaseImpl* database = | |
| 438 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
| 439 if (!database) | |
| 440 return; | |
| 441 | |
| 442 database->deleteObjectStore(parent_->HostTransactionId(transaction_id), | |
| 443 object_store_id); | |
| 444 } | |
| 445 | |
| 446 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction( | |
| 447 const IndexedDBHostMsg_DatabaseCreateTransaction_Params& params) { | |
| 448 DCHECK( | |
| 449 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 450 WebIDBDatabaseImpl* database = | |
| 451 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 452 if (!database) | |
| 453 return; | |
| 454 | |
| 455 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
| 456 | |
| 457 database->createTransaction( | |
| 458 host_transaction_id, | |
| 459 new IndexedDBDatabaseCallbacks( | |
| 460 parent_, params.ipc_thread_id, params.ipc_database_callbacks_id), | |
| 461 params.object_store_ids, | |
| 462 params.mode); | |
| 463 transaction_database_map_[host_transaction_id] = params.ipc_database_id; | |
| 464 parent_->RegisterTransactionId(host_transaction_id, | |
| 465 database_url_map_[params.ipc_database_id]); | |
| 466 } | |
| 467 | |
| 468 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose( | |
| 469 int32 ipc_database_id) { | |
| 470 DCHECK( | |
| 471 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 472 WebIDBDatabaseImpl* database = | |
| 473 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
| 474 if (!database) | |
| 475 return; | |
| 476 database->close(); | |
| 477 } | |
| 478 | |
| 479 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed( | |
| 480 int32 ipc_object_id) { | |
| 481 DCHECK( | |
| 482 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 483 WebIDBDatabaseImpl* database = map_.Lookup(ipc_object_id); | |
| 484 parent_->Context() | |
| 485 ->ConnectionClosed(database_url_map_[ipc_object_id], database); | |
| 486 database_url_map_.erase(ipc_object_id); | |
| 487 parent_->DestroyObject(&map_, ipc_object_id); | |
| 488 } | |
| 489 | |
| 490 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet( | |
| 491 const IndexedDBHostMsg_DatabaseGet_Params& params) { | |
| 492 DCHECK( | |
| 493 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 494 WebIDBDatabaseImpl* database = | |
| 495 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 496 if (!database) | |
| 497 return; | |
| 498 | |
| 499 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
| 500 new IndexedDBCallbacks<std::vector<char> >( | |
| 501 parent_, params.ipc_thread_id, params.ipc_callbacks_id)); | |
| 502 database->get(parent_->HostTransactionId(params.transaction_id), | |
| 503 params.object_store_id, | |
| 504 params.index_id, | |
| 505 params.key_range, | |
| 506 params.key_only, | |
| 507 callbacks.release()); | |
| 508 } | |
| 509 | |
| 510 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut( | |
| 511 const IndexedDBHostMsg_DatabasePut_Params& params) { | |
| 512 DCHECK( | |
| 513 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 514 | |
| 515 WebIDBDatabaseImpl* database = | |
| 516 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 517 if (!database) | |
| 518 return; | |
| 519 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
| 520 new IndexedDBCallbacks<IndexedDBKey>( | |
| 521 parent_, params.ipc_thread_id, params.ipc_callbacks_id)); | |
| 522 | |
| 523 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
| 524 // TODO(alecflett): Avoid a copy here. | |
| 525 std::vector<char> value_copy = params.value; | |
| 526 database->put(host_transaction_id, | |
| 527 params.object_store_id, | |
| 528 &value_copy, | |
| 529 params.key, | |
| 530 params.put_mode, | |
| 531 callbacks.release(), | |
| 532 params.index_ids, | |
| 533 params.index_keys); | |
| 534 TransactionIDToSizeMap* map = | |
| 535 &parent_->database_dispatcher_host_->transaction_size_map_; | |
| 536 // Size can't be big enough to overflow because it represents the | |
| 537 // actual bytes passed through IPC. | |
| 538 (*map)[host_transaction_id] += params.value.size(); | |
| 539 } | |
| 540 | |
| 541 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexKeys( | |
| 542 const IndexedDBHostMsg_DatabaseSetIndexKeys_Params& params) { | |
| 543 DCHECK( | |
| 544 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 545 WebIDBDatabaseImpl* database = | |
| 546 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 547 if (!database) | |
| 548 return; | |
| 549 | |
| 550 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
| 551 if (params.index_ids.size() != params.index_keys.size()) { | |
| 552 database->abort( | |
| 553 host_transaction_id, | |
| 554 WebIDBDatabaseError( | |
| 555 WebKit::WebIDBDatabaseExceptionUnknownError, | |
| 556 "Malformed IPC message: index_ids.size() != index_keys.size()")); | |
| 557 return; | |
| 558 } | |
| 559 | |
| 560 database->setIndexKeys(host_transaction_id, | |
| 561 params.object_store_id, | |
| 562 params.primary_key, | |
| 563 params.index_ids, | |
| 564 params.index_keys); | |
| 565 } | |
| 566 | |
| 567 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexesReady( | |
| 568 int32 ipc_database_id, | |
| 569 int64 transaction_id, | |
| 570 int64 object_store_id, | |
| 571 const std::vector<int64>& index_ids) { | |
| 572 DCHECK( | |
| 573 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 574 WebIDBDatabaseImpl* database = | |
| 575 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
| 576 if (!database) | |
| 577 return; | |
| 578 | |
| 579 database->setIndexesReady( | |
| 580 parent_->HostTransactionId(transaction_id), object_store_id, index_ids); | |
| 581 } | |
| 582 | |
| 583 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnOpenCursor( | |
| 584 const IndexedDBHostMsg_DatabaseOpenCursor_Params& params) { | |
| 585 DCHECK( | |
| 586 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 587 WebIDBDatabaseImpl* database = | |
| 588 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 589 if (!database) | |
| 590 return; | |
| 591 | |
| 592 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
| 593 new IndexedDBCallbacks<WebIDBCursorImpl>( | |
| 594 parent_, params.ipc_thread_id, params.ipc_callbacks_id, -1)); | |
| 595 database->openCursor(parent_->HostTransactionId(params.transaction_id), | |
| 596 params.object_store_id, | |
| 597 params.index_id, | |
| 598 params.key_range, | |
| 599 params.direction, | |
| 600 params.key_only, | |
| 601 params.task_type, | |
| 602 callbacks.release()); | |
| 603 } | |
| 604 | |
| 605 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCount( | |
| 606 const IndexedDBHostMsg_DatabaseCount_Params& params) { | |
| 607 DCHECK( | |
| 608 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 609 WebIDBDatabaseImpl* database = | |
| 610 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 611 if (!database) | |
| 612 return; | |
| 613 | |
| 614 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
| 615 new IndexedDBCallbacks<std::vector<char> >( | |
| 616 parent_, params.ipc_thread_id, params.ipc_callbacks_id)); | |
| 617 database->count(parent_->HostTransactionId(params.transaction_id), | |
| 618 params.object_store_id, | |
| 619 params.index_id, | |
| 620 params.key_range, | |
| 621 callbacks.release()); | |
| 622 } | |
| 623 | |
| 624 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteRange( | |
| 625 const IndexedDBHostMsg_DatabaseDeleteRange_Params& params) { | |
| 626 DCHECK( | |
| 627 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 628 WebIDBDatabaseImpl* database = | |
| 629 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 630 if (!database) | |
| 631 return; | |
| 632 | |
| 633 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
| 634 new IndexedDBCallbacks<std::vector<char> >( | |
| 635 parent_, params.ipc_thread_id, params.ipc_callbacks_id)); | |
| 636 database->deleteRange(parent_->HostTransactionId(params.transaction_id), | |
| 637 params.object_store_id, | |
| 638 params.key_range, | |
| 639 callbacks.release()); | |
| 640 } | |
| 641 | |
| 642 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClear( | |
| 643 int32 ipc_thread_id, | |
| 644 int32 ipc_callbacks_id, | |
| 645 int32 ipc_database_id, | |
| 646 int64 transaction_id, | |
| 647 int64 object_store_id) { | |
| 648 DCHECK( | |
| 649 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 650 WebIDBDatabaseImpl* database = | |
| 651 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
| 652 if (!database) | |
| 653 return; | |
| 654 | |
| 655 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
| 656 new IndexedDBCallbacks<std::vector<char> >( | |
| 657 parent_, ipc_thread_id, ipc_callbacks_id)); | |
| 658 | |
| 659 database->clear(parent_->HostTransactionId(transaction_id), | |
| 660 object_store_id, | |
| 661 callbacks.release()); | |
| 662 } | |
| 663 | |
| 664 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnAbort( | |
| 665 int32 ipc_database_id, | |
| 666 int64 transaction_id) { | |
| 667 DCHECK( | |
| 668 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 669 WebIDBDatabaseImpl* database = | |
| 670 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
| 671 if (!database) | |
| 672 return; | |
| 673 | |
| 674 database->abort(parent_->HostTransactionId(transaction_id)); | |
| 675 } | |
| 676 | |
| 677 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCommit( | |
| 678 int32 ipc_database_id, | |
| 679 int64 transaction_id) { | |
| 680 DCHECK( | |
| 681 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 682 WebIDBDatabaseImpl* database = | |
| 683 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
| 684 if (!database) | |
| 685 return; | |
| 686 | |
| 687 int64 host_transaction_id = parent_->HostTransactionId(transaction_id); | |
| 688 int64 transaction_size = transaction_size_map_[host_transaction_id]; | |
| 689 if (transaction_size && | |
| 690 parent_->Context()->WouldBeOverQuota( | |
| 691 transaction_url_map_[host_transaction_id], transaction_size)) { | |
| 692 database->abort( | |
| 693 host_transaction_id, | |
| 694 WebIDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError)); | |
| 695 return; | |
| 696 } | |
| 697 | |
| 698 database->commit(host_transaction_id); | |
| 699 } | |
| 700 | |
| 701 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateIndex( | |
| 702 const IndexedDBHostMsg_DatabaseCreateIndex_Params& params) { | |
| 703 DCHECK( | |
| 704 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 705 WebIDBDatabaseImpl* database = | |
| 706 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
| 707 if (!database) | |
| 708 return; | |
| 709 | |
| 710 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
| 711 database->createIndex(host_transaction_id, | |
| 712 params.object_store_id, | |
| 713 params.index_id, | |
| 714 params.name, | |
| 715 params.key_path, | |
| 716 params.unique, | |
| 717 params.multi_entry); | |
| 718 if (parent_->Context()->IsOverQuota( | |
| 719 database_url_map_[params.ipc_database_id])) { | |
| 720 database->abort( | |
| 721 host_transaction_id, | |
| 722 WebIDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError)); | |
| 723 } | |
| 724 } | |
| 725 | |
| 726 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteIndex( | |
| 727 int32 ipc_database_id, | |
| 728 int64 transaction_id, | |
| 729 int64 object_store_id, | |
| 730 int64 index_id) { | |
| 731 DCHECK( | |
| 732 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 733 WebIDBDatabaseImpl* database = | |
| 734 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
| 735 if (!database) | |
| 736 return; | |
| 737 | |
| 738 database->deleteIndex( | |
| 739 parent_->HostTransactionId(transaction_id), object_store_id, index_id); | |
| 740 } | |
| 741 | |
| 742 ////////////////////////////////////////////////////////////////////// | |
| 743 // IndexedDBDispatcherHost::CursorDispatcherHost | |
| 744 // | |
| 745 | |
| 746 IndexedDBDispatcherHost::CursorDispatcherHost::CursorDispatcherHost( | |
| 747 IndexedDBDispatcherHost* parent) | |
| 748 : parent_(parent) { | |
| 749 map_.set_check_on_null_data(true); | |
| 750 } | |
| 751 | |
| 752 IndexedDBDispatcherHost::CursorDispatcherHost::~CursorDispatcherHost() {} | |
| 753 | |
| 754 bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived( | |
| 755 const IPC::Message& message, | |
| 756 bool* msg_is_ok) { | |
| 757 DCHECK( | |
| 758 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 759 | |
| 760 bool handled = true; | |
| 761 IPC_BEGIN_MESSAGE_MAP_EX( | |
| 762 IndexedDBDispatcherHost::CursorDispatcherHost, message, *msg_is_ok) | |
| 763 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorAdvance, OnAdvance) | |
| 764 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorContinue, OnContinue) | |
| 765 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetch, OnPrefetch) | |
| 766 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetchReset, OnPrefetchReset) | |
| 767 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDestroyed, OnDestroyed) | |
| 768 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 769 IPC_END_MESSAGE_MAP() | |
| 770 return handled; | |
| 771 } | |
| 772 | |
| 773 void IndexedDBDispatcherHost::CursorDispatcherHost::Send( | |
| 774 IPC::Message* message) { | |
| 775 parent_->Send(message); | |
| 776 } | |
| 777 | |
| 778 void IndexedDBDispatcherHost::CursorDispatcherHost::OnAdvance( | |
| 779 int32 ipc_cursor_id, | |
| 780 int32 ipc_thread_id, | |
| 781 int32 ipc_callbacks_id, | |
| 782 unsigned long count) { | |
| 783 DCHECK( | |
| 784 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 785 WebIDBCursorImpl* idb_cursor = | |
| 786 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
| 787 if (!idb_cursor) | |
| 788 return; | |
| 789 | |
| 790 idb_cursor->advance( | |
| 791 count, | |
| 792 new IndexedDBCallbacks<WebIDBCursorImpl>( | |
| 793 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id)); | |
| 794 } | |
| 795 | |
| 796 void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue( | |
| 797 int32 ipc_cursor_id, | |
| 798 int32 ipc_thread_id, | |
| 799 int32 ipc_callbacks_id, | |
| 800 const IndexedDBKey& key) { | |
| 801 DCHECK( | |
| 802 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 803 WebIDBCursorImpl* idb_cursor = | |
| 804 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
| 805 if (!idb_cursor) | |
| 806 return; | |
| 807 | |
| 808 idb_cursor->continueFunction( | |
| 809 key, | |
| 810 new IndexedDBCallbacks<WebIDBCursorImpl>( | |
| 811 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id)); | |
| 812 } | |
| 813 | |
| 814 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetch( | |
| 815 int32 ipc_cursor_id, | |
| 816 int32 ipc_thread_id, | |
| 817 int32 ipc_callbacks_id, | |
| 818 int n) { | |
| 819 DCHECK( | |
| 820 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 821 WebIDBCursorImpl* idb_cursor = | |
| 822 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
| 823 if (!idb_cursor) | |
| 824 return; | |
| 825 | |
| 826 idb_cursor->prefetchContinue( | |
| 827 n, | |
| 828 new IndexedDBCallbacks<WebIDBCursorImpl>( | |
| 829 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id)); | |
| 830 } | |
| 831 | |
| 832 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset( | |
| 833 int32 ipc_cursor_id, | |
| 834 int used_prefetches, | |
| 835 int unused_prefetches) { | |
| 836 DCHECK( | |
| 837 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 838 WebIDBCursorImpl* idb_cursor = | |
| 839 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
| 840 if (!idb_cursor) | |
| 841 return; | |
| 842 | |
| 843 idb_cursor->prefetchReset(used_prefetches, unused_prefetches); | |
| 844 } | |
| 845 | |
| 846 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed( | |
| 847 int32 ipc_object_id) { | |
| 848 DCHECK( | |
| 849 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 850 parent_->DestroyObject(&map_, ipc_object_id); | |
| 851 } | |
| 852 | |
| 853 } // namespace content | |
| OLD | NEW |