Home | History | Annotate | Download | only in indexed_db
      1 // Copyright 2014 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 "base/bind.h"
      6 #include "base/location.h"
      7 #include "base/stl_util.h"
      8 #include "base/task_runner.h"
      9 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
     10 #include "content/browser/indexed_db/indexed_db_backing_store.h"
     11 #include "content/browser/indexed_db/indexed_db_factory.h"
     12 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
     13 
     14 namespace content {
     15 
     16 IndexedDBActiveBlobRegistry::IndexedDBActiveBlobRegistry(
     17     IndexedDBBackingStore* backing_store)
     18     : backing_store_(backing_store), weak_factory_(this) {}
     19 
     20 IndexedDBActiveBlobRegistry::~IndexedDBActiveBlobRegistry() {
     21 }
     22 
     23 void IndexedDBActiveBlobRegistry::AddBlobRef(int64 database_id,
     24                                              int64 blob_key) {
     25   DCHECK(backing_store_);
     26   DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
     27   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
     28   DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
     29   DCHECK(!ContainsKey(deleted_dbs_, database_id));
     30   bool need_ref = use_tracker_.empty();
     31   SingleDBMap& single_db_map = use_tracker_[database_id];
     32   SingleDBMap::iterator iter = single_db_map.find(blob_key);
     33   if (iter == single_db_map.end()) {
     34     single_db_map[blob_key] = false;
     35     if (need_ref) {
     36       backing_store_->factory()->ReportOutstandingBlobs(
     37           backing_store_->origin_url(), true);
     38     }
     39   } else {
     40     DCHECK(!need_ref);
     41     DCHECK(!iter->second);  // You can't add a reference once it's been deleted.
     42   }
     43 }
     44 
     45 void IndexedDBActiveBlobRegistry::ReleaseBlobRef(int64 database_id,
     46                                                  int64 blob_key) {
     47   DCHECK(backing_store_);
     48   DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
     49   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
     50   DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
     51   AllDBsMap::iterator db_pair = use_tracker_.find(database_id);
     52   if (db_pair == use_tracker_.end()) {
     53     NOTREACHED();
     54     return;
     55   }
     56   SingleDBMap& single_db = db_pair->second;
     57   SingleDBMap::iterator blob_pair = single_db.find(blob_key);
     58   if (blob_pair == single_db.end()) {
     59     NOTREACHED();
     60     return;
     61   }
     62   bool delete_in_backend = false;
     63   DeletedDBSet::iterator db_to_delete = deleted_dbs_.find(database_id);
     64   bool db_marked_for_deletion = db_to_delete != deleted_dbs_.end();
     65   // Don't bother deleting the file if we're going to delete its whole
     66   // database directory soon.
     67   delete_in_backend = blob_pair->second && !db_marked_for_deletion;
     68   single_db.erase(blob_pair);
     69   if (single_db.empty()) {
     70     use_tracker_.erase(db_pair);
     71     if (db_marked_for_deletion) {
     72       delete_in_backend = true;
     73       blob_key = DatabaseMetaDataKey::kAllBlobsKey;
     74       deleted_dbs_.erase(db_to_delete);
     75     }
     76   }
     77   if (delete_in_backend)
     78     backing_store_->ReportBlobUnused(database_id, blob_key);
     79   if (use_tracker_.empty()) {
     80     backing_store_->factory()->ReportOutstandingBlobs(
     81         backing_store_->origin_url(), false);
     82   }
     83 }
     84 
     85 bool IndexedDBActiveBlobRegistry::MarkDeletedCheckIfUsed(int64 database_id,
     86                                                          int64 blob_key) {
     87   DCHECK(backing_store_);
     88   DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
     89   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
     90   AllDBsMap::iterator db_pair = use_tracker_.find(database_id);
     91   if (db_pair == use_tracker_.end())
     92     return false;
     93 
     94   if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) {
     95     deleted_dbs_.insert(database_id);
     96     return true;
     97   }
     98 
     99   SingleDBMap& single_db = db_pair->second;
    100   SingleDBMap::iterator iter = single_db.find(blob_key);
    101   if (iter == single_db.end())
    102     return false;
    103 
    104   iter->second = true;
    105   return true;
    106 }
    107 
    108 void IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe(
    109     scoped_refptr<base::TaskRunner> task_runner,
    110     base::WeakPtr<IndexedDBActiveBlobRegistry> weak_ptr,
    111     int64 database_id,
    112     int64 blob_key,
    113     const base::FilePath& unused) {
    114   task_runner->PostTask(FROM_HERE,
    115                         base::Bind(&IndexedDBActiveBlobRegistry::ReleaseBlobRef,
    116                                    weak_ptr,
    117                                    database_id,
    118                                    blob_key));
    119 }
    120 
    121 webkit_blob::ShareableFileReference::FinalReleaseCallback
    122 IndexedDBActiveBlobRegistry::GetFinalReleaseCallback(int64 database_id,
    123                                                      int64 blob_key) {
    124   return base::Bind(
    125       &IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe,
    126       scoped_refptr<base::TaskRunner>(backing_store_->task_runner()),
    127       weak_factory_.GetWeakPtr(),
    128       database_id,
    129       blob_key);
    130 }
    131 
    132 base::Closure IndexedDBActiveBlobRegistry::GetAddBlobRefCallback(
    133     int64 database_id,
    134     int64 blob_key) {
    135   return base::Bind(&IndexedDBActiveBlobRegistry::AddBlobRef,
    136                     weak_factory_.GetWeakPtr(),
    137                     database_id,
    138                     blob_key);
    139 }
    140 
    141 void IndexedDBActiveBlobRegistry::ForceShutdown() {
    142   weak_factory_.InvalidateWeakPtrs();
    143   use_tracker_.clear();
    144   backing_store_ = NULL;
    145 }
    146 
    147 }  // namespace content
    148