| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/indexed_db_factory_impl.h" | 5 #include "content/browser/indexed_db/indexed_db_factory_impl.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 15 #include "content/browser/indexed_db/indexed_db_backing_store.h" | 15 #include "content/browser/indexed_db/indexed_db_backing_store.h" |
| 16 #include "content/browser/indexed_db/indexed_db_context_impl.h" | 16 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| 17 #include "content/browser/indexed_db/indexed_db_database_error.h" | 17 #include "content/browser/indexed_db/indexed_db_database_error.h" |
| 18 #include "content/browser/indexed_db/indexed_db_pending_connection.h" |
| 19 #include "content/browser/indexed_db/indexed_db_pending_delete.h" |
| 18 #include "content/browser/indexed_db/indexed_db_tracing.h" | 20 #include "content/browser/indexed_db/indexed_db_tracing.h" |
| 19 #include "content/browser/indexed_db/indexed_db_transaction_coordinator.h" | 21 #include "content/browser/indexed_db/indexed_db_transaction_coordinator.h" |
| 22 #include "net/url_request/url_request_context_getter.h" |
| 20 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" | 23 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" |
| 21 #include "third_party/leveldatabase/env_chromium.h" | 24 #include "third_party/leveldatabase/env_chromium.h" |
| 22 | 25 |
| 23 using base::ASCIIToUTF16; | 26 using base::ASCIIToUTF16; |
| 24 using url::Origin; | 27 using url::Origin; |
| 25 | 28 |
| 26 namespace content { | 29 namespace content { |
| 27 | 30 |
| 28 const int64_t kBackingStoreGracePeriodMs = 2000; | 31 const int64_t kBackingStoreGracePeriodMs = 2000; |
| 29 | 32 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 } else { | 165 } else { |
| 163 const auto& it = backing_stores_with_active_blobs_.find(origin); | 166 const auto& it = backing_stores_with_active_blobs_.find(origin); |
| 164 if (it != backing_stores_with_active_blobs_.end()) { | 167 if (it != backing_stores_with_active_blobs_.end()) { |
| 165 backing_stores_with_active_blobs_.erase(it); | 168 backing_stores_with_active_blobs_.erase(it); |
| 166 ReleaseBackingStore(origin, false /* immediate */); | 169 ReleaseBackingStore(origin, false /* immediate */); |
| 167 } | 170 } |
| 168 } | 171 } |
| 169 } | 172 } |
| 170 | 173 |
| 171 void IndexedDBFactoryImpl::GetDatabaseNames( | 174 void IndexedDBFactoryImpl::GetDatabaseNames( |
| 172 scoped_refptr<IndexedDBCallbacks> callbacks, | |
| 173 const Origin& origin, | 175 const Origin& origin, |
| 174 const base::FilePath& data_directory, | 176 const base::FilePath& data_directory, |
| 175 scoped_refptr<net::URLRequestContextGetter> request_context_getter) { | 177 scoped_refptr<net::URLRequestContextGetter> request_context_getter) { |
| 176 IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseNames"); | 178 IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseNames"); |
| 177 // TODO(dgrogan): Plumb data_loss back to script eventually? | 179 // TODO(dgrogan): Plumb data_loss back to script eventually? |
| 178 IndexedDBDataLossInfo data_loss_info; | 180 IndexedDBDataLossInfo data_loss_info; |
| 179 bool disk_full; | 181 bool disk_full; |
| 180 leveldb::Status s; | 182 leveldb::Status s; |
| 181 // TODO(cmumford): Handle this error | 183 // TODO(cmumford): Handle this error |
| 182 scoped_refptr<IndexedDBBackingStore> backing_store = | 184 scoped_refptr<IndexedDBBackingStore> backing_store = |
| 183 OpenBackingStore(origin, data_directory, request_context_getter, | 185 OpenBackingStore(origin, data_directory, request_context_getter, |
| 184 &data_loss_info, &disk_full, &s); | 186 &data_loss_info, &disk_full, &s); |
| 185 if (!backing_store.get()) { | 187 if (!backing_store.get()) { |
| 188 #ifdef CJM_NEED_CALLBACK |
| 186 callbacks->OnError( | 189 callbacks->OnError( |
| 187 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | 190 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
| 188 "Internal error opening backing store for " | 191 "Internal error opening backing store for " |
| 189 "indexedDB.webkitGetDatabaseNames.")); | 192 "indexedDB.webkitGetDatabaseNames.")); |
| 193 #endif |
| 190 return; | 194 return; |
| 191 } | 195 } |
| 192 | 196 |
| 193 std::vector<base::string16> names = backing_store->GetDatabaseNames(&s); | 197 std::vector<base::string16> names = backing_store->GetDatabaseNames(&s); |
| 194 if (!s.ok()) { | 198 if (!s.ok()) { |
| 195 DLOG(ERROR) << "Internal error getting database names"; | 199 DLOG(ERROR) << "Internal error getting database names"; |
| 196 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 200 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 197 "Internal error opening backing store for " | 201 "Internal error opening backing store for " |
| 198 "indexedDB.webkitGetDatabaseNames."); | 202 "indexedDB.webkitGetDatabaseNames."); |
| 203 #ifdef CJM_NEED_CALLBACK |
| 199 callbacks->OnError(error); | 204 callbacks->OnError(error); |
| 205 #endif |
| 200 backing_store = NULL; | 206 backing_store = NULL; |
| 201 if (s.IsCorruption()) | 207 if (s.IsCorruption()) |
| 202 HandleBackingStoreCorruption(origin, error); | 208 HandleBackingStoreCorruption(origin, error); |
| 203 return; | 209 return; |
| 204 } | 210 } |
| 211 #ifdef CJM_NEED_CALLBACK |
| 205 callbacks->OnSuccess(names); | 212 callbacks->OnSuccess(names); |
| 213 #endif |
| 206 backing_store = NULL; | 214 backing_store = NULL; |
| 207 ReleaseBackingStore(origin, false /* immediate */); | 215 ReleaseBackingStore(origin, false /* immediate */); |
| 208 } | 216 } |
| 209 | 217 |
| 210 void IndexedDBFactoryImpl::DeleteDatabase( | 218 void IndexedDBFactoryImpl::DeleteDatabase( |
| 211 const base::string16& name, | 219 const base::string16& name, |
| 212 scoped_refptr<net::URLRequestContextGetter> request_context_getter, | 220 scoped_refptr<net::URLRequestContextGetter> request_context_getter, |
| 213 scoped_refptr<IndexedDBCallbacks> callbacks, | 221 std::unique_ptr<IndexedDBPendingDelete> pending_delete, |
| 214 const Origin& origin, | 222 const Origin& origin, |
| 215 const base::FilePath& data_directory) { | 223 const base::FilePath& data_directory) { |
| 216 IDB_TRACE("IndexedDBFactoryImpl::DeleteDatabase"); | 224 IDB_TRACE("IndexedDBFactoryImpl::DeleteDatabase"); |
| 217 IndexedDBDatabase::Identifier unique_identifier(origin, name); | 225 IndexedDBDatabase::Identifier unique_identifier(origin, name); |
| 218 const auto& it = database_map_.find(unique_identifier); | 226 const auto& it = database_map_.find(unique_identifier); |
| 219 if (it != database_map_.end()) { | 227 if (it != database_map_.end()) { |
| 220 // If there are any connections to the database, directly delete the | 228 // If there are any connections to the database, directly delete the |
| 221 // database. | 229 // database. |
| 222 it->second->DeleteDatabase(callbacks); | 230 it->second->DeleteDatabase(std::move(pending_delete)); |
| 223 return; | 231 return; |
| 224 } | 232 } |
| 225 | 233 |
| 226 // TODO(dgrogan): Plumb data_loss back to script eventually? | 234 // TODO(dgrogan): Plumb data_loss back to script eventually? |
| 227 IndexedDBDataLossInfo data_loss_info; | 235 IndexedDBDataLossInfo data_loss_info; |
| 228 bool disk_full = false; | 236 bool disk_full = false; |
| 229 leveldb::Status s; | 237 leveldb::Status s; |
| 230 scoped_refptr<IndexedDBBackingStore> backing_store = | 238 scoped_refptr<IndexedDBBackingStore> backing_store = |
| 231 OpenBackingStore(origin, data_directory, request_context_getter, | 239 OpenBackingStore(origin, data_directory, request_context_getter, |
| 232 &data_loss_info, &disk_full, &s); | 240 &data_loss_info, &disk_full, &s); |
| 233 if (!backing_store.get()) { | 241 if (!backing_store.get()) { |
| 234 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 242 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 235 ASCIIToUTF16( | 243 ASCIIToUTF16( |
| 236 "Internal error opening backing store " | 244 "Internal error opening backing store " |
| 237 "for indexedDB.deleteDatabase.")); | 245 "for indexedDB.deleteDatabase.")); |
| 238 callbacks->OnError(error); | 246 pending_delete->OnError(error); |
| 239 if (s.IsCorruption()) { | 247 if (s.IsCorruption()) { |
| 240 HandleBackingStoreCorruption(origin, error); | 248 HandleBackingStoreCorruption(origin, error); |
| 241 } | 249 } |
| 242 return; | 250 return; |
| 243 } | 251 } |
| 244 | 252 |
| 245 std::vector<base::string16> names = backing_store->GetDatabaseNames(&s); | 253 std::vector<base::string16> names = backing_store->GetDatabaseNames(&s); |
| 246 if (!s.ok()) { | 254 if (!s.ok()) { |
| 247 DLOG(ERROR) << "Internal error getting database names"; | 255 DLOG(ERROR) << "Internal error getting database names"; |
| 248 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 256 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 249 "Internal error opening backing store for " | 257 "Internal error opening backing store for " |
| 250 "indexedDB.deleteDatabase."); | 258 "indexedDB.deleteDatabase."); |
| 251 callbacks->OnError(error); | 259 pending_delete->OnError(error); |
| 252 backing_store = NULL; | 260 backing_store = NULL; |
| 253 if (s.IsCorruption()) | 261 if (s.IsCorruption()) |
| 254 HandleBackingStoreCorruption(origin, error); | 262 HandleBackingStoreCorruption(origin, error); |
| 255 return; | 263 return; |
| 256 } | 264 } |
| 257 if (!base::ContainsValue(names, name)) { | 265 if (!base::ContainsValue(names, name)) { |
| 266 #ifdef CJM_NEED_CALLBACK |
| 258 const int64_t version = 0; | 267 const int64_t version = 0; |
| 259 callbacks->OnSuccess(version); | 268 pending_delete->OnSuccess(version); |
| 269 #endif |
| 260 backing_store = NULL; | 270 backing_store = NULL; |
| 261 ReleaseBackingStore(origin, false /* immediate */); | 271 ReleaseBackingStore(origin, false /* immediate */); |
| 262 return; | 272 return; |
| 263 } | 273 } |
| 264 | 274 |
| 265 scoped_refptr<IndexedDBDatabase> database = IndexedDBDatabase::Create( | 275 scoped_refptr<IndexedDBDatabase> database = IndexedDBDatabase::Create( |
| 266 name, backing_store.get(), this, unique_identifier, &s); | 276 name, backing_store.get(), this, unique_identifier, &s); |
| 267 if (!database.get()) { | 277 if (!database.get()) { |
| 268 IndexedDBDatabaseError error( | 278 IndexedDBDatabaseError error( |
| 269 blink::WebIDBDatabaseExceptionUnknownError, | 279 blink::WebIDBDatabaseExceptionUnknownError, |
| 270 ASCIIToUTF16( | 280 ASCIIToUTF16( |
| 271 "Internal error creating database backend for " | 281 "Internal error creating database backend for " |
| 272 "indexedDB.deleteDatabase.")); | 282 "indexedDB.deleteDatabase.")); |
| 273 callbacks->OnError(error); | 283 pending_delete->OnError(error); |
| 274 if (s.IsCorruption()) { | 284 if (s.IsCorruption()) { |
| 275 backing_store = NULL; | 285 backing_store = NULL; |
| 276 HandleBackingStoreCorruption(origin, error); | 286 HandleBackingStoreCorruption(origin, error); |
| 277 } | 287 } |
| 278 return; | 288 return; |
| 279 } | 289 } |
| 280 | 290 |
| 281 database_map_[unique_identifier] = database.get(); | 291 database_map_[unique_identifier] = database.get(); |
| 282 origin_dbs_.insert(std::make_pair(origin, database.get())); | 292 origin_dbs_.insert(std::make_pair(origin, database.get())); |
| 283 database->DeleteDatabase(callbacks); | 293 database->DeleteDatabase(std::move(pending_delete)); |
| 284 RemoveDatabaseFromMaps(unique_identifier); | 294 RemoveDatabaseFromMaps(unique_identifier); |
| 285 database = NULL; | 295 database = NULL; |
| 286 backing_store = NULL; | 296 backing_store = NULL; |
| 287 ReleaseBackingStore(origin, false /* immediate */); | 297 ReleaseBackingStore(origin, false /* immediate */); |
| 288 } | 298 } |
| 289 | 299 |
| 290 void IndexedDBFactoryImpl::DatabaseDeleted( | 300 void IndexedDBFactoryImpl::DatabaseDeleted( |
| 291 const IndexedDBDatabase::Identifier& identifier) { | 301 const IndexedDBDatabase::Identifier& identifier) { |
| 292 // NULL after ContextDestroyed() called, and in some unit tests. | 302 // NULL after ContextDestroyed() called, and in some unit tests. |
| 293 if (!context_) | 303 if (!context_) |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 IndexedDBDataLossInfo data_loss_info; | 422 IndexedDBDataLossInfo data_loss_info; |
| 413 bool disk_full = false; | 423 bool disk_full = false; |
| 414 bool was_open = (it != database_map_.end()); | 424 bool was_open = (it != database_map_.end()); |
| 415 if (!was_open) { | 425 if (!was_open) { |
| 416 leveldb::Status s; | 426 leveldb::Status s; |
| 417 scoped_refptr<IndexedDBBackingStore> backing_store = | 427 scoped_refptr<IndexedDBBackingStore> backing_store = |
| 418 OpenBackingStore(origin, data_directory, request_context_getter, | 428 OpenBackingStore(origin, data_directory, request_context_getter, |
| 419 &data_loss_info, &disk_full, &s); | 429 &data_loss_info, &disk_full, &s); |
| 420 if (!backing_store.get()) { | 430 if (!backing_store.get()) { |
| 421 if (disk_full) { | 431 if (disk_full) { |
| 422 connection->callbacks->OnError(IndexedDBDatabaseError( | 432 connection->OnError(IndexedDBDatabaseError( |
| 423 blink::WebIDBDatabaseExceptionQuotaError, | 433 blink::WebIDBDatabaseExceptionQuotaError, |
| 424 ASCIIToUTF16("Encountered full disk while opening " | 434 ASCIIToUTF16("Encountered full disk while opening " |
| 425 "backing store for indexedDB.open."))); | 435 "backing store for indexedDB.open."))); |
| 426 return; | 436 return; |
| 427 } | 437 } |
| 428 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 438 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 429 ASCIIToUTF16( | 439 ASCIIToUTF16( |
| 430 "Internal error opening backing store" | 440 "Internal error opening backing store" |
| 431 " for indexedDB.open.")); | 441 " for indexedDB.open.")); |
| 432 connection->callbacks->OnError(error); | 442 connection->OnError(error); |
| 433 if (s.IsCorruption()) { | 443 if (s.IsCorruption()) { |
| 434 HandleBackingStoreCorruption(origin, error); | 444 HandleBackingStoreCorruption(origin, error); |
| 435 } | 445 } |
| 436 return; | 446 return; |
| 437 } | 447 } |
| 438 | 448 |
| 439 database = IndexedDBDatabase::Create( | 449 database = IndexedDBDatabase::Create( |
| 440 name, backing_store.get(), this, unique_identifier, &s); | 450 name, backing_store.get(), this, unique_identifier, &s); |
| 441 if (!database.get()) { | 451 if (!database.get()) { |
| 442 DLOG(ERROR) << "Unable to create the database"; | 452 DLOG(ERROR) << "Unable to create the database"; |
| 443 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 453 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 444 ASCIIToUTF16( | 454 ASCIIToUTF16( |
| 445 "Internal error creating " | 455 "Internal error creating " |
| 446 "database backend for " | 456 "database backend for " |
| 447 "indexedDB.open.")); | 457 "indexedDB.open.")); |
| 448 connection->callbacks->OnError(error); | 458 connection->OnError(error); |
| 449 if (s.IsCorruption()) { | 459 if (s.IsCorruption()) { |
| 450 backing_store = NULL; // Closes the LevelDB so that it can be deleted | 460 backing_store = NULL; // Closes the LevelDB so that it can be deleted |
| 451 HandleBackingStoreCorruption(origin, error); | 461 HandleBackingStoreCorruption(origin, error); |
| 452 } | 462 } |
| 453 return; | 463 return; |
| 454 } | 464 } |
| 455 } else { | 465 } else { |
| 456 database = it->second; | 466 database = it->second; |
| 457 } | 467 } |
| 458 | 468 |
| 459 connection->data_loss_info = data_loss_info; | 469 connection->SetDataLossInfo(data_loss_info); |
| 460 | 470 |
| 461 database->OpenConnection(std::move(connection)); | 471 database->OpenConnection(std::move(connection)); |
| 462 | 472 |
| 463 if (!was_open && database->ConnectionCount() > 0) { | 473 if (!was_open && database->ConnectionCount() > 0) { |
| 464 database_map_[unique_identifier] = database.get(); | 474 database_map_[unique_identifier] = database.get(); |
| 465 origin_dbs_.insert(std::make_pair(origin, database.get())); | 475 origin_dbs_.insert(std::make_pair(origin, database.get())); |
| 466 } | 476 } |
| 467 } | 477 } |
| 468 | 478 |
| 469 std::pair<IndexedDBFactoryImpl::OriginDBMapIterator, | 479 std::pair<IndexedDBFactoryImpl::OriginDBMapIterator, |
| 470 IndexedDBFactoryImpl::OriginDBMapIterator> | 480 IndexedDBFactoryImpl::OriginDBMapIterator> |
| 471 IndexedDBFactoryImpl::GetOpenDatabasesForOrigin(const Origin& origin) const { | 481 IndexedDBFactoryImpl::GetOpenDatabasesForOrigin(const Origin& origin) const { |
| 472 return origin_dbs_.equal_range(origin); | 482 return origin_dbs_.equal_range(origin); |
| 473 } | 483 } |
| 474 | 484 |
| 475 size_t IndexedDBFactoryImpl::GetConnectionCount(const Origin& origin) const { | 485 size_t IndexedDBFactoryImpl::GetConnectionCount(const Origin& origin) const { |
| 476 size_t count(0); | 486 size_t count(0); |
| 477 | 487 |
| 478 OriginDBs range = GetOpenDatabasesForOrigin(origin); | 488 OriginDBs range = GetOpenDatabasesForOrigin(origin); |
| 479 for (OriginDBMapIterator it = range.first; it != range.second; ++it) | 489 for (OriginDBMapIterator it = range.first; it != range.second; ++it) |
| 480 count += it->second->ConnectionCount(); | 490 count += it->second->ConnectionCount(); |
| 481 | 491 |
| 482 return count; | 492 return count; |
| 483 } | 493 } |
| 484 | 494 |
| 495 IndexedDBContext* IndexedDBFactoryImpl::context() const { |
| 496 return context_; |
| 497 } |
| 498 |
| 485 } // namespace content | 499 } // namespace content |
| OLD | NEW |