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 23 matching lines...) Expand all Loading... | |
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 // Only close if this is the last reference. | 43 // Only close if this is the last reference. |
44 if (!HasLastBackingStoreReference(origin_url)) | 44 if (!HasLastBackingStoreReference(origin_url, immediate)) |
45 return; | 45 return; |
46 | 46 |
47 // If this factory does hold the last reference to the backing store, it can | 47 // 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 | 48 // be closed - but unless requested to close it immediately, keep it around |
49 // for a short period so that a re-open is fast. | 49 // for a short period so that a re-open is fast. |
50 if (immediate) { | 50 if (immediate) { |
51 CloseBackingStore(origin_url); | 51 CloseBackingStore(origin_url); |
52 return; | 52 return; |
53 } | 53 } |
54 | 54 |
55 // Start a timer to close the backing store, unless something else opens it | 55 // Start a timer to close the backing store, unless something else opens it |
56 // in the mean time. | 56 // in the mean time. |
57 DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning()); | 57 DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning()); |
58 backing_store_map_[origin_url]->close_timer()->Start( | 58 backing_store_map_[origin_url]->close_timer()->Start( |
59 FROM_HERE, | 59 FROM_HERE, |
60 base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs), | 60 base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs), |
61 base::Bind(&IndexedDBFactory::MaybeCloseBackingStore, this, origin_url)); | 61 base::Bind(&IndexedDBFactory::MaybeCloseBackingStore, this, origin_url)); |
62 } | 62 } |
63 | 63 |
64 void IndexedDBFactory::MaybeCloseBackingStore(const GURL& origin_url) { | 64 void IndexedDBFactory::MaybeCloseBackingStore(const GURL& origin_url) { |
65 // Another reference may have opened since the maybe-close was posted, so it | 65 // Another reference may have opened since the maybe-close was posted, so it |
66 // is necessary to check again. | 66 // is necessary to check again. |
67 if (HasLastBackingStoreReference(origin_url)) | 67 if (HasLastBackingStoreReference(origin_url, false)) |
68 CloseBackingStore(origin_url); | 68 CloseBackingStore(origin_url); |
69 } | 69 } |
70 | 70 |
71 void IndexedDBFactory::CloseBackingStore(const GURL& origin_url) { | 71 void IndexedDBFactory::CloseBackingStore(const GURL& origin_url) { |
72 IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url); | 72 IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url); |
73 DCHECK(it != backing_store_map_.end()); | 73 DCHECK(it != backing_store_map_.end()); |
74 // Stop the timer (if it's running) - this may happen if the timer was started | 74 // Stop the timer (if it's running) - this may happen if the timer was started |
75 // and then a forced close occurs. | 75 // and then a forced close occurs. |
76 it->second->close_timer()->Stop(); | 76 it->second->close_timer()->Stop(); |
77 backing_store_map_.erase(it); | 77 backing_store_map_.erase(it); |
78 } | 78 } |
79 | 79 |
80 bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url) | 80 bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url, |
81 const { | 81 bool forcedClose) const { |
82 IndexedDBBackingStore* ptr; | 82 IndexedDBBackingStore* ptr; |
83 { | 83 { |
84 // Scope so that the implicit scoped_refptr<> is freed. | 84 // Scope so that the implicit scoped_refptr<> is freed. |
85 IndexedDBBackingStoreMap::const_iterator it = | 85 IndexedDBBackingStoreMap::const_iterator it = |
86 backing_store_map_.find(origin_url); | 86 backing_store_map_.find(origin_url); |
87 DCHECK(it != backing_store_map_.end()); | 87 DCHECK(it != backing_store_map_.end()); |
88 ptr = it->second.get(); | 88 ptr = it->second.get(); |
89 } | 89 } |
90 if (ptr->HasOneRef()) | |
91 return true; | |
92 if (!forcedClose) | |
93 return false; | |
94 ptr->active_blob_registry()->ForceShutdown(); | |
jsbell
2013/12/03 00:10:03
Hrm, unfortunate placement (in a Has.... method).
jsbell
2013/12/03 00:11:24
ISTM this is a good reason to move away from relyi
ericu
2013/12/03 02:03:55
It's idempotent, but currently assumes that once i
ericu
2013/12/03 02:03:55
I'm fine with that too; this code I've put in feel
| |
90 return ptr->HasOneRef(); | 95 return ptr->HasOneRef(); |
91 } | 96 } |
92 | 97 |
93 void IndexedDBFactory::ContextDestroyed() { | 98 void IndexedDBFactory::ContextDestroyed() { |
94 // Timers on backing stores hold a reference to this factory. When the | 99 // Timers on backing stores hold a reference to this factory. When the |
95 // context (which nominally owns this factory) is destroyed during thread | 100 // context (which nominally owns this factory) is destroyed during thread |
96 // termination the timers must be stopped so that this factory and the | 101 // termination the timers must be stopped so that this factory and the |
97 // stores can be disposed of. | 102 // stores can be disposed of. |
98 for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin(); | 103 for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin(); |
99 it != backing_store_map_.end(); | 104 it != backing_store_map_.end(); |
100 ++it) | 105 ++it) |
101 it->second->close_timer()->Stop(); | 106 it->second->close_timer()->Stop(); |
102 backing_store_map_.clear(); | 107 backing_store_map_.clear(); |
103 context_ = NULL; | 108 context_ = NULL; |
104 } | 109 } |
105 | 110 |
106 void IndexedDBFactory::GetDatabaseNames( | 111 void IndexedDBFactory::GetDatabaseNames( |
107 scoped_refptr<IndexedDBCallbacks> callbacks, | 112 scoped_refptr<IndexedDBCallbacks> callbacks, |
108 const GURL& origin_url, | 113 const GURL& origin_url, |
109 const base::FilePath& data_directory) { | 114 const base::FilePath& data_directory, |
115 base::TaskRunner* task_runner) { | |
110 IDB_TRACE("IndexedDBFactory::GetDatabaseNames"); | 116 IDB_TRACE("IndexedDBFactory::GetDatabaseNames"); |
111 // TODO(dgrogan): Plumb data_loss back to script eventually? | 117 // TODO(dgrogan): Plumb data_loss back to script eventually? |
112 blink::WebIDBDataLoss data_loss; | 118 blink::WebIDBDataLoss data_loss; |
113 std::string data_loss_message; | 119 std::string data_loss_message; |
114 bool disk_full; | 120 bool disk_full; |
115 scoped_refptr<IndexedDBBackingStore> backing_store = | 121 scoped_refptr<IndexedDBBackingStore> backing_store = |
116 OpenBackingStore(origin_url, | 122 OpenBackingStore(origin_url, |
117 data_directory, | 123 data_directory, |
124 NULL, | |
118 &data_loss, | 125 &data_loss, |
119 &data_loss_message, | 126 &data_loss_message, |
120 &disk_full); | 127 &disk_full, |
128 task_runner); | |
121 if (!backing_store) { | 129 if (!backing_store) { |
122 callbacks->OnError( | 130 callbacks->OnError( |
123 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | 131 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
124 "Internal error opening backing store for " | 132 "Internal error opening backing store for " |
125 "indexedDB.webkitGetDatabaseNames.")); | 133 "indexedDB.webkitGetDatabaseNames.")); |
126 return; | 134 return; |
127 } | 135 } |
128 | 136 |
129 callbacks->OnSuccess(backing_store->GetDatabaseNames()); | 137 callbacks->OnSuccess(backing_store->GetDatabaseNames()); |
130 } | 138 } |
131 | 139 |
132 void IndexedDBFactory::DeleteDatabase( | 140 void IndexedDBFactory::DeleteDatabase( |
133 const string16& name, | 141 const string16& name, |
142 net::URLRequestContext* request_context, | |
134 scoped_refptr<IndexedDBCallbacks> callbacks, | 143 scoped_refptr<IndexedDBCallbacks> callbacks, |
135 const GURL& origin_url, | 144 const GURL& origin_url, |
136 const base::FilePath& data_directory) { | 145 const base::FilePath& data_directory, |
146 base::TaskRunner* task_runner) { | |
137 IDB_TRACE("IndexedDBFactory::DeleteDatabase"); | 147 IDB_TRACE("IndexedDBFactory::DeleteDatabase"); |
138 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); | 148 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); |
139 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); | 149 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); |
140 if (it != database_map_.end()) { | 150 if (it != database_map_.end()) { |
141 // If there are any connections to the database, directly delete the | 151 // If there are any connections to the database, directly delete the |
142 // database. | 152 // database. |
143 it->second->DeleteDatabase(callbacks); | 153 it->second->DeleteDatabase(callbacks); |
144 return; | 154 return; |
145 } | 155 } |
146 | 156 |
147 // TODO(dgrogan): Plumb data_loss back to script eventually? | 157 // TODO(dgrogan): Plumb data_loss back to script eventually? |
148 blink::WebIDBDataLoss data_loss; | 158 blink::WebIDBDataLoss data_loss; |
149 std::string data_loss_message; | 159 std::string data_loss_message; |
150 bool disk_full = false; | 160 bool disk_full = false; |
151 scoped_refptr<IndexedDBBackingStore> backing_store = | 161 scoped_refptr<IndexedDBBackingStore> backing_store = |
152 OpenBackingStore(origin_url, | 162 OpenBackingStore(origin_url, |
153 data_directory, | 163 data_directory, |
164 request_context, | |
154 &data_loss, | 165 &data_loss, |
155 &data_loss_message, | 166 &data_loss_message, |
156 &disk_full); | 167 &disk_full, |
168 task_runner); | |
157 if (!backing_store) { | 169 if (!backing_store) { |
158 callbacks->OnError( | 170 callbacks->OnError( |
159 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | 171 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
160 ASCIIToUTF16( | 172 ASCIIToUTF16( |
161 "Internal error opening backing store " | 173 "Internal error opening backing store " |
162 "for indexedDB.deleteDatabase."))); | 174 "for indexedDB.deleteDatabase."))); |
163 return; | 175 return; |
164 } | 176 } |
165 | 177 |
166 scoped_refptr<IndexedDBDatabase> database = | 178 scoped_refptr<IndexedDBDatabase> database = |
(...skipping 20 matching lines...) Expand all Loading... | |
187 } | 199 } |
188 | 200 |
189 bool IndexedDBFactory::IsBackingStoreOpenForTesting(const GURL& origin_url) | 201 bool IndexedDBFactory::IsBackingStoreOpenForTesting(const GURL& origin_url) |
190 const { | 202 const { |
191 return backing_store_map_.find(origin_url) != backing_store_map_.end(); | 203 return backing_store_map_.find(origin_url) != backing_store_map_.end(); |
192 } | 204 } |
193 | 205 |
194 scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore( | 206 scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore( |
195 const GURL& origin_url, | 207 const GURL& origin_url, |
196 const base::FilePath& data_directory, | 208 const base::FilePath& data_directory, |
209 net::URLRequestContext* request_context, | |
197 blink::WebIDBDataLoss* data_loss, | 210 blink::WebIDBDataLoss* data_loss, |
198 std::string* data_loss_message, | 211 std::string* data_loss_message, |
199 bool* disk_full) { | 212 bool* disk_full, |
213 base::TaskRunner* task_runner) { | |
200 const bool open_in_memory = data_directory.empty(); | 214 const bool open_in_memory = data_directory.empty(); |
201 | 215 |
202 IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url); | 216 IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url); |
203 if (it2 != backing_store_map_.end()) { | 217 if (it2 != backing_store_map_.end()) { |
204 it2->second->close_timer()->Stop(); | 218 it2->second->close_timer()->Stop(); |
205 return it2->second; | 219 return it2->second; |
206 } | 220 } |
207 | 221 |
208 scoped_refptr<IndexedDBBackingStore> backing_store; | 222 scoped_refptr<IndexedDBBackingStore> backing_store; |
223 bool first_time = false; | |
209 if (open_in_memory) { | 224 if (open_in_memory) { |
225 // TODO(ericu): Support blobs in in-memory backends. | |
210 backing_store = IndexedDBBackingStore::OpenInMemory(origin_url); | 226 backing_store = IndexedDBBackingStore::OpenInMemory(origin_url); |
211 } else { | 227 } else { |
212 backing_store = IndexedDBBackingStore::Open(origin_url, | 228 first_time = !backends_opened_since_boot_.count(origin_url); |
229 backing_store = IndexedDBBackingStore::Open(this, | |
230 origin_url, | |
213 data_directory, | 231 data_directory, |
232 request_context, | |
214 data_loss, | 233 data_loss, |
215 data_loss_message, | 234 data_loss_message, |
216 disk_full); | 235 disk_full, |
236 task_runner, | |
237 first_time); | |
217 } | 238 } |
218 | 239 |
219 if (backing_store.get()) { | 240 if (backing_store.get()) { |
241 if (first_time) | |
242 backends_opened_since_boot_.insert(origin_url); | |
220 backing_store_map_[origin_url] = backing_store; | 243 backing_store_map_[origin_url] = backing_store; |
221 // If an in-memory database, bind lifetime to this factory instance. | 244 // If an in-memory database, bind lifetime to this factory instance. |
222 if (open_in_memory) | 245 if (open_in_memory) |
223 session_only_backing_stores_.insert(backing_store); | 246 session_only_backing_stores_.insert(backing_store); |
224 | 247 |
225 // All backing stores associated with this factory should be of the same | 248 // All backing stores associated with this factory should be of the same |
226 // type. | 249 // type. |
227 DCHECK(session_only_backing_stores_.empty() || open_in_memory); | 250 DCHECK(session_only_backing_stores_.empty() != open_in_memory); |
228 | 251 |
229 return backing_store; | 252 return backing_store; |
230 } | 253 } |
231 | 254 |
232 return 0; | 255 return 0; |
233 } | 256 } |
234 | 257 |
235 void IndexedDBFactory::Open( | 258 void IndexedDBFactory::Open( |
236 const string16& name, | 259 const string16& name, |
237 int64 version, | 260 int64 version, |
261 net::URLRequestContext* request_context, | |
238 int64 transaction_id, | 262 int64 transaction_id, |
239 scoped_refptr<IndexedDBCallbacks> callbacks, | 263 scoped_refptr<IndexedDBCallbacks> callbacks, |
240 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, | 264 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, |
241 const GURL& origin_url, | 265 const GURL& origin_url, |
242 const base::FilePath& data_directory) { | 266 const base::FilePath& data_directory, |
267 int child_process_id, | |
268 base::TaskRunner* task_runner) { | |
243 IDB_TRACE("IndexedDBFactory::Open"); | 269 IDB_TRACE("IndexedDBFactory::Open"); |
244 scoped_refptr<IndexedDBDatabase> database; | 270 scoped_refptr<IndexedDBDatabase> database; |
245 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); | 271 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); |
246 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); | 272 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); |
247 blink::WebIDBDataLoss data_loss = | 273 blink::WebIDBDataLoss data_loss = |
248 blink::WebIDBDataLossNone; | 274 blink::WebIDBDataLossNone; |
249 std::string data_loss_message; | 275 std::string data_loss_message; |
250 bool disk_full = false; | 276 bool disk_full = false; |
251 if (it == database_map_.end()) { | 277 if (it == database_map_.end()) { |
252 scoped_refptr<IndexedDBBackingStore> backing_store = | 278 scoped_refptr<IndexedDBBackingStore> backing_store = |
253 OpenBackingStore(origin_url, | 279 OpenBackingStore(origin_url, |
254 data_directory, | 280 data_directory, |
281 request_context, | |
255 &data_loss, | 282 &data_loss, |
256 &data_loss_message, | 283 &data_loss_message, |
257 &disk_full); | 284 &disk_full, |
285 task_runner); | |
258 if (!backing_store) { | 286 if (!backing_store) { |
259 if (disk_full) { | 287 if (disk_full) { |
260 callbacks->OnError( | 288 callbacks->OnError( |
261 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError, | 289 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError, |
262 ASCIIToUTF16( | 290 ASCIIToUTF16( |
263 "Encountered full disk while opening " | 291 "Encountered full disk while opening " |
264 "backing store for indexedDB.open."))); | 292 "backing store for indexedDB.open."))); |
265 return; | 293 return; |
266 } | 294 } |
267 callbacks->OnError(IndexedDBDatabaseError( | 295 callbacks->OnError(IndexedDBDatabaseError( |
(...skipping 13 matching lines...) Expand all Loading... | |
281 return; | 309 return; |
282 } | 310 } |
283 | 311 |
284 database_map_[unique_identifier] = database; | 312 database_map_[unique_identifier] = database; |
285 } else { | 313 } else { |
286 database = it->second; | 314 database = it->second; |
287 } | 315 } |
288 | 316 |
289 database->OpenConnection(callbacks, | 317 database->OpenConnection(callbacks, |
290 database_callbacks, | 318 database_callbacks, |
319 child_process_id, | |
291 transaction_id, | 320 transaction_id, |
292 version, | 321 version, |
293 data_loss, | 322 data_loss, |
294 data_loss_message); | 323 data_loss_message); |
295 } | 324 } |
296 | 325 |
297 std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin( | 326 std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin( |
298 const GURL& origin_url) const { | 327 const GURL& origin_url) const { |
299 std::vector<IndexedDBDatabase*> result; | 328 std::vector<IndexedDBDatabase*> result; |
300 for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin(); | 329 for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin(); |
301 it != database_map_.end(); | 330 it != database_map_.end(); |
302 ++it) { | 331 ++it) { |
303 if (it->first.first == origin_url) | 332 if (it->first.first == origin_url) |
304 result.push_back(it->second.get()); | 333 result.push_back(it->second.get()); |
305 } | 334 } |
306 return result; | 335 return result; |
307 } | 336 } |
308 | 337 |
309 } // namespace content | 338 } // namespace content |
OLD | NEW |