Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / indexed_db / indexed_db_active_blob_registry.cc
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 storage::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