 Chromium Code Reviews
 Chromium Code Reviews Issue 18023022:
  Blob support for IDB [Chromium]  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 18023022:
  Blob support for IDB [Chromium]  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| 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.h" | 5 #include "content/browser/indexed_db/indexed_db_factory.h" | 
| 6 | 6 | 
| 7 #include "base/logging.h" | 7 #include "base/logging.h" | 
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" | 
| 9 #include "base/time/time.h" | 9 #include "base/time/time.h" | 
| 10 #include "content/browser/indexed_db/indexed_db_backing_store.h" | 10 #include "content/browser/indexed_db/indexed_db_backing_store.h" | 
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 database_map_.erase(it); | 33 database_map_.erase(it); | 
| 34 | 34 | 
| 35 // No grace period on a forced-close, as the initiator is | 35 // No grace period on a forced-close, as the initiator is | 
| 36 // assuming the backing store will be released once all | 36 // assuming the backing store will be released once all | 
| 37 // connections are closed. | 37 // connections are closed. | 
| 38 ReleaseBackingStore(origin_url, forcedClose); | 38 ReleaseBackingStore(origin_url, forcedClose); | 
| 39 } | 39 } | 
| 40 | 40 | 
| 41 void IndexedDBFactory::ReleaseBackingStore(const GURL& origin_url, | 41 void IndexedDBFactory::ReleaseBackingStore(const GURL& origin_url, | 
| 42 bool immediate) { | 42 bool immediate) { | 
| 43 if (immediate) { | |
| 44 IndexedDBBackingStoreMap::iterator it = | |
| 45 backing_stores_with_active_blobs_.find(origin_url); | |
| 46 if (it != backing_stores_with_active_blobs_.end()) { | |
| 47 it->second->active_blob_registry()->ForceShutdown(); | |
| 48 backing_stores_with_active_blobs_.erase(it); | |
| 49 } | |
| 50 } | |
| 51 | |
| 43 // Only close if this is the last reference. | 52 // Only close if this is the last reference. | 
| 44 if (!HasLastBackingStoreReference(origin_url)) | 53 if (!HasLastBackingStoreReference(origin_url)) | 
| 45 return; | 54 return; | 
| 46 | 55 | 
| 47 // If this factory does hold the last reference to the backing store, it can | 56 // If this factory does hold the last reference to the backing store, it can | 
| 48 // be closed - but unless requested to close it immediately, keep it around | 57 // be closed - but unless requested to close it immediately, keep it around | 
| 49 // for a short period so that a re-open is fast. | 58 // for a short period so that a re-open is fast. | 
| 50 if (immediate) { | 59 if (immediate) { | 
| 51 CloseBackingStore(origin_url); | 60 CloseBackingStore(origin_url); | 
| 52 return; | 61 return; | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 void IndexedDBFactory::ContextDestroyed() { | 102 void IndexedDBFactory::ContextDestroyed() { | 
| 94 // Timers on backing stores hold a reference to this factory. When the | 103 // Timers on backing stores hold a reference to this factory. When the | 
| 95 // context (which nominally owns this factory) is destroyed during thread | 104 // context (which nominally owns this factory) is destroyed during thread | 
| 96 // termination the timers must be stopped so that this factory and the | 105 // termination the timers must be stopped so that this factory and the | 
| 97 // stores can be disposed of. | 106 // stores can be disposed of. | 
| 98 for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin(); | 107 for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin(); | 
| 99 it != backing_store_map_.end(); | 108 it != backing_store_map_.end(); | 
| 100 ++it) | 109 ++it) | 
| 101 it->second->close_timer()->Stop(); | 110 it->second->close_timer()->Stop(); | 
| 102 backing_store_map_.clear(); | 111 backing_store_map_.clear(); | 
| 112 backing_stores_with_active_blobs_.clear(); | |
| 103 context_ = NULL; | 113 context_ = NULL; | 
| 104 } | 114 } | 
| 105 | 115 | 
| 116 void IndexedDBFactory::ReportOutstandingBlobs(const GURL& origin_url, | |
| 
jsbell
2013/12/20 00:44:20
To untangle this spaghetti, I'd like to turn the f
 | |
| 117 bool blobs_outstanding) { | |
| 118 if (!context_) | |
| 119 return; | |
| 120 if (blobs_outstanding) { | |
| 121 DCHECK(!backing_stores_with_active_blobs_.count(origin_url)); | |
| 122 IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url); | |
| 123 if (it != backing_store_map_.end()) | |
| 124 backing_stores_with_active_blobs_.insert(*it); | |
| 125 else | |
| 126 DCHECK(false); | |
| 127 } else { | |
| 128 IndexedDBBackingStoreMap::iterator it = | |
| 129 backing_stores_with_active_blobs_.find(origin_url); | |
| 130 if (it != backing_stores_with_active_blobs_.end()) { | |
| 131 backing_stores_with_active_blobs_.erase(it); | |
| 132 ReleaseBackingStore(origin_url, false); | |
| 133 } | |
| 134 } | |
| 135 } | |
| 136 | |
| 106 void IndexedDBFactory::GetDatabaseNames( | 137 void IndexedDBFactory::GetDatabaseNames( | 
| 107 scoped_refptr<IndexedDBCallbacks> callbacks, | 138 scoped_refptr<IndexedDBCallbacks> callbacks, | 
| 108 const GURL& origin_url, | 139 const GURL& origin_url, | 
| 109 const base::FilePath& data_directory) { | 140 const base::FilePath& data_directory, | 
| 141 base::TaskRunner* task_runner) { | |
| 110 IDB_TRACE("IndexedDBFactory::GetDatabaseNames"); | 142 IDB_TRACE("IndexedDBFactory::GetDatabaseNames"); | 
| 111 // TODO(dgrogan): Plumb data_loss back to script eventually? | 143 // TODO(dgrogan): Plumb data_loss back to script eventually? | 
| 112 blink::WebIDBDataLoss data_loss; | 144 blink::WebIDBDataLoss data_loss; | 
| 113 std::string data_loss_message; | 145 std::string data_loss_message; | 
| 114 bool disk_full; | 146 bool disk_full; | 
| 115 scoped_refptr<IndexedDBBackingStore> backing_store = | 147 scoped_refptr<IndexedDBBackingStore> backing_store = | 
| 116 OpenBackingStore(origin_url, | 148 OpenBackingStore(origin_url, | 
| 117 data_directory, | 149 data_directory, | 
| 150 NULL, | |
| 118 &data_loss, | 151 &data_loss, | 
| 119 &data_loss_message, | 152 &data_loss_message, | 
| 120 &disk_full); | 153 &disk_full, | 
| 154 task_runner); | |
| 121 if (!backing_store) { | 155 if (!backing_store) { | 
| 122 callbacks->OnError( | 156 callbacks->OnError( | 
| 123 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | 157 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | 
| 124 "Internal error opening backing store for " | 158 "Internal error opening backing store for " | 
| 125 "indexedDB.webkitGetDatabaseNames.")); | 159 "indexedDB.webkitGetDatabaseNames.")); | 
| 126 return; | 160 return; | 
| 127 } | 161 } | 
| 128 | 162 | 
| 129 callbacks->OnSuccess(backing_store->GetDatabaseNames()); | 163 callbacks->OnSuccess(backing_store->GetDatabaseNames()); | 
| 130 } | 164 } | 
| 131 | 165 | 
| 132 void IndexedDBFactory::DeleteDatabase( | 166 void IndexedDBFactory::DeleteDatabase( | 
| 133 const string16& name, | 167 const string16& name, | 
| 168 net::URLRequestContext* request_context, | |
| 134 scoped_refptr<IndexedDBCallbacks> callbacks, | 169 scoped_refptr<IndexedDBCallbacks> callbacks, | 
| 135 const GURL& origin_url, | 170 const GURL& origin_url, | 
| 136 const base::FilePath& data_directory) { | 171 const base::FilePath& data_directory, | 
| 172 base::TaskRunner* task_runner) { | |
| 137 IDB_TRACE("IndexedDBFactory::DeleteDatabase"); | 173 IDB_TRACE("IndexedDBFactory::DeleteDatabase"); | 
| 138 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); | 174 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); | 
| 139 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); | 175 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); | 
| 140 if (it != database_map_.end()) { | 176 if (it != database_map_.end()) { | 
| 141 // If there are any connections to the database, directly delete the | 177 // If there are any connections to the database, directly delete the | 
| 142 // database. | 178 // database. | 
| 143 it->second->DeleteDatabase(callbacks); | 179 it->second->DeleteDatabase(callbacks); | 
| 144 return; | 180 return; | 
| 145 } | 181 } | 
| 146 | 182 | 
| 147 // TODO(dgrogan): Plumb data_loss back to script eventually? | 183 // TODO(dgrogan): Plumb data_loss back to script eventually? | 
| 148 blink::WebIDBDataLoss data_loss; | 184 blink::WebIDBDataLoss data_loss; | 
| 149 std::string data_loss_message; | 185 std::string data_loss_message; | 
| 150 bool disk_full = false; | 186 bool disk_full = false; | 
| 151 scoped_refptr<IndexedDBBackingStore> backing_store = | 187 scoped_refptr<IndexedDBBackingStore> backing_store = | 
| 152 OpenBackingStore(origin_url, | 188 OpenBackingStore(origin_url, | 
| 153 data_directory, | 189 data_directory, | 
| 190 request_context, | |
| 154 &data_loss, | 191 &data_loss, | 
| 155 &data_loss_message, | 192 &data_loss_message, | 
| 156 &disk_full); | 193 &disk_full, | 
| 194 task_runner); | |
| 157 if (!backing_store) { | 195 if (!backing_store) { | 
| 158 callbacks->OnError( | 196 callbacks->OnError( | 
| 159 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | 197 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | 
| 160 ASCIIToUTF16( | 198 ASCIIToUTF16( | 
| 161 "Internal error opening backing store " | 199 "Internal error opening backing store " | 
| 162 "for indexedDB.deleteDatabase."))); | 200 "for indexedDB.deleteDatabase."))); | 
| 163 return; | 201 return; | 
| 164 } | 202 } | 
| 165 | 203 | 
| 166 scoped_refptr<IndexedDBDatabase> database = | 204 scoped_refptr<IndexedDBDatabase> database = | 
| (...skipping 17 matching lines...) Expand all Loading... | |
| 184 if (!context_) | 222 if (!context_) | 
| 185 return; | 223 return; | 
| 186 context_->ForceClose(origin_url); | 224 context_->ForceClose(origin_url); | 
| 187 } | 225 } | 
| 188 | 226 | 
| 189 bool IndexedDBFactory::IsBackingStoreOpenForTesting(const GURL& origin_url) | 227 bool IndexedDBFactory::IsBackingStoreOpenForTesting(const GURL& origin_url) | 
| 190 const { | 228 const { | 
| 191 return backing_store_map_.find(origin_url) != backing_store_map_.end(); | 229 return backing_store_map_.find(origin_url) != backing_store_map_.end(); | 
| 192 } | 230 } | 
| 193 | 231 | 
| 232 scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStoreHelper( | |
| 233 const GURL& origin_url, | |
| 234 const base::FilePath& data_directory, | |
| 235 net::URLRequestContext* request_context, | |
| 236 blink::WebIDBDataLoss* data_loss, | |
| 237 std::string* data_loss_message, | |
| 238 bool* disk_full, | |
| 239 base::TaskRunner* task_runner, | |
| 240 bool first_time) { | |
| 241 return IndexedDBBackingStore::Open(this, | |
| 242 origin_url, | |
| 243 data_directory, | |
| 244 request_context, | |
| 245 data_loss, | |
| 246 data_loss_message, | |
| 247 disk_full, | |
| 248 task_runner, | |
| 249 first_time); | |
| 250 } | |
| 251 | |
| 194 scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore( | 252 scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore( | 
| 195 const GURL& origin_url, | 253 const GURL& origin_url, | 
| 196 const base::FilePath& data_directory, | 254 const base::FilePath& data_directory, | 
| 255 net::URLRequestContext* request_context, | |
| 197 blink::WebIDBDataLoss* data_loss, | 256 blink::WebIDBDataLoss* data_loss, | 
| 198 std::string* data_loss_message, | 257 std::string* data_loss_message, | 
| 199 bool* disk_full) { | 258 bool* disk_full, | 
| 259 base::TaskRunner* task_runner) { | |
| 200 const bool open_in_memory = data_directory.empty(); | 260 const bool open_in_memory = data_directory.empty(); | 
| 201 | 261 | 
| 202 IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url); | 262 IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url); | 
| 203 if (it2 != backing_store_map_.end()) { | 263 if (it2 != backing_store_map_.end()) { | 
| 204 it2->second->close_timer()->Stop(); | 264 it2->second->close_timer()->Stop(); | 
| 205 return it2->second; | 265 return it2->second; | 
| 206 } | 266 } | 
| 207 | 267 | 
| 208 scoped_refptr<IndexedDBBackingStore> backing_store; | 268 scoped_refptr<IndexedDBBackingStore> backing_store; | 
| 269 bool first_time = false; | |
| 209 if (open_in_memory) { | 270 if (open_in_memory) { | 
| 210 backing_store = IndexedDBBackingStore::OpenInMemory(origin_url); | 271 // TODO(ericu): Support blobs in in-memory backends. | 
| 272 backing_store = | |
| 273 IndexedDBBackingStore::OpenInMemory(origin_url, task_runner); | |
| 211 } else { | 274 } else { | 
| 212 backing_store = IndexedDBBackingStore::Open(origin_url, | 275 first_time = !backends_opened_since_boot_.count(origin_url); | 
| 213 data_directory, | 276 | 
| 214 data_loss, | 277 backing_store = OpenBackingStoreHelper(origin_url, | 
| 215 data_loss_message, | 278 data_directory, | 
| 216 disk_full); | 279 request_context, | 
| 280 data_loss, | |
| 281 data_loss_message, | |
| 282 disk_full, | |
| 283 task_runner, | |
| 284 first_time); | |
| 217 } | 285 } | 
| 218 | 286 | 
| 219 if (backing_store.get()) { | 287 if (backing_store.get()) { | 
| 288 if (first_time) | |
| 289 backends_opened_since_boot_.insert(origin_url); | |
| 220 backing_store_map_[origin_url] = backing_store; | 290 backing_store_map_[origin_url] = backing_store; | 
| 221 // If an in-memory database, bind lifetime to this factory instance. | 291 // If an in-memory database, bind lifetime to this factory instance. | 
| 222 if (open_in_memory) | 292 if (open_in_memory) | 
| 223 session_only_backing_stores_.insert(backing_store); | 293 session_only_backing_stores_.insert(backing_store); | 
| 224 | 294 | 
| 225 // All backing stores associated with this factory should be of the same | 295 // All backing stores associated with this factory should be of the same | 
| 226 // type. | 296 // type. | 
| 227 DCHECK(session_only_backing_stores_.empty() || open_in_memory); | 297 DCHECK(session_only_backing_stores_.empty() != open_in_memory); | 
| 228 | 298 | 
| 229 return backing_store; | 299 return backing_store; | 
| 230 } | 300 } | 
| 231 | 301 | 
| 232 return 0; | 302 return 0; | 
| 233 } | 303 } | 
| 234 | 304 | 
| 235 void IndexedDBFactory::Open( | 305 void IndexedDBFactory::Open( | 
| 236 const string16& name, | 306 const string16& name, | 
| 237 int64 version, | 307 int64 version, | 
| 308 net::URLRequestContext* request_context, | |
| 238 int64 transaction_id, | 309 int64 transaction_id, | 
| 239 scoped_refptr<IndexedDBCallbacks> callbacks, | 310 scoped_refptr<IndexedDBCallbacks> callbacks, | 
| 240 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, | 311 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, | 
| 241 const GURL& origin_url, | 312 const GURL& origin_url, | 
| 242 const base::FilePath& data_directory) { | 313 const base::FilePath& data_directory, | 
| 314 int child_process_id, | |
| 315 base::TaskRunner* task_runner) { | |
| 243 IDB_TRACE("IndexedDBFactory::Open"); | 316 IDB_TRACE("IndexedDBFactory::Open"); | 
| 244 scoped_refptr<IndexedDBDatabase> database; | 317 scoped_refptr<IndexedDBDatabase> database; | 
| 245 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); | 318 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); | 
| 246 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); | 319 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); | 
| 247 blink::WebIDBDataLoss data_loss = | 320 blink::WebIDBDataLoss data_loss = | 
| 248 blink::WebIDBDataLossNone; | 321 blink::WebIDBDataLossNone; | 
| 249 std::string data_loss_message; | 322 std::string data_loss_message; | 
| 250 bool disk_full = false; | 323 bool disk_full = false; | 
| 251 if (it == database_map_.end()) { | 324 if (it == database_map_.end()) { | 
| 252 scoped_refptr<IndexedDBBackingStore> backing_store = | 325 scoped_refptr<IndexedDBBackingStore> backing_store = | 
| 253 OpenBackingStore(origin_url, | 326 OpenBackingStore(origin_url, | 
| 254 data_directory, | 327 data_directory, | 
| 328 request_context, | |
| 255 &data_loss, | 329 &data_loss, | 
| 256 &data_loss_message, | 330 &data_loss_message, | 
| 257 &disk_full); | 331 &disk_full, | 
| 332 task_runner); | |
| 258 if (!backing_store) { | 333 if (!backing_store) { | 
| 259 if (disk_full) { | 334 if (disk_full) { | 
| 260 callbacks->OnError( | 335 callbacks->OnError( | 
| 261 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError, | 336 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError, | 
| 262 ASCIIToUTF16( | 337 ASCIIToUTF16( | 
| 263 "Encountered full disk while opening " | 338 "Encountered full disk while opening " | 
| 264 "backing store for indexedDB.open."))); | 339 "backing store for indexedDB.open."))); | 
| 265 return; | 340 return; | 
| 266 } | 341 } | 
| 267 callbacks->OnError(IndexedDBDatabaseError( | 342 callbacks->OnError(IndexedDBDatabaseError( | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 281 return; | 356 return; | 
| 282 } | 357 } | 
| 283 | 358 | 
| 284 database_map_[unique_identifier] = database; | 359 database_map_[unique_identifier] = database; | 
| 285 } else { | 360 } else { | 
| 286 database = it->second; | 361 database = it->second; | 
| 287 } | 362 } | 
| 288 | 363 | 
| 289 database->OpenConnection(callbacks, | 364 database->OpenConnection(callbacks, | 
| 290 database_callbacks, | 365 database_callbacks, | 
| 366 child_process_id, | |
| 291 transaction_id, | 367 transaction_id, | 
| 292 version, | 368 version, | 
| 293 data_loss, | 369 data_loss, | 
| 294 data_loss_message); | 370 data_loss_message); | 
| 295 } | 371 } | 
| 296 | 372 | 
| 297 std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin( | 373 std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin( | 
| 298 const GURL& origin_url) const { | 374 const GURL& origin_url) const { | 
| 299 std::vector<IndexedDBDatabase*> result; | 375 std::vector<IndexedDBDatabase*> result; | 
| 300 for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin(); | 376 for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin(); | 
| 301 it != database_map_.end(); | 377 it != database_map_.end(); | 
| 302 ++it) { | 378 ++it) { | 
| 303 if (it->first.first == origin_url) | 379 if (it->first.first == origin_url) | 
| 304 result.push_back(it->second.get()); | 380 result.push_back(it->second.get()); | 
| 305 } | 381 } | 
| 306 return result; | 382 return result; | 
| 307 } | 383 } | 
| 308 | 384 | 
| 309 } // namespace content | 385 } // namespace content | 
| OLD | NEW |