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
3 // found in the LICENSE file.
5 #ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
6 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
12 #include "base/basictypes.h"
13 #include "base/files/file_path.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/strings/string_piece.h"
17 #include "base/timer/timer.h"
18 #include "content/browser/indexed_db/indexed_db.h"
19 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
20 #include "content/browser/indexed_db/indexed_db_blob_info.h"
21 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
22 #include "content/browser/indexed_db/indexed_db_metadata.h"
23 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
24 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
25 #include "content/common/content_export.h"
26 #include "content/common/indexed_db/indexed_db_key.h"
27 #include "content/common/indexed_db/indexed_db_key_path.h"
28 #include "content/common/indexed_db/indexed_db_key_range.h"
29 #include "third_party/leveldatabase/src/include/leveldb/status.h"
31 #include "webkit/browser/blob/blob_data_handle.h"
38 class FileWriterDelegate
;
42 class URLRequestContext
;
47 class IndexedDBFactory
;
48 class LevelDBComparator
;
49 class LevelDBDatabase
;
50 struct IndexedDBValue
;
52 class LevelDBFactory
{
54 virtual ~LevelDBFactory() {}
55 virtual leveldb::Status
OpenLevelDB(const base::FilePath
& file_name
,
56 const LevelDBComparator
* comparator
,
57 scoped_ptr
<LevelDBDatabase
>* db
,
58 bool* is_disk_full
) = 0;
59 virtual leveldb::Status
DestroyLevelDB(const base::FilePath
& file_name
) = 0;
62 class CONTENT_EXPORT IndexedDBBackingStore
63 : public base::RefCounted
<IndexedDBBackingStore
> {
65 class CONTENT_EXPORT Transaction
;
67 class Comparator
: public LevelDBComparator
{
69 virtual int Compare(const base::StringPiece
& a
,
70 const base::StringPiece
& b
) const OVERRIDE
;
71 virtual const char* Name() const OVERRIDE
;
74 const GURL
& origin_url() const { return origin_url_
; }
75 IndexedDBFactory
* factory() const { return indexed_db_factory_
; }
76 base::TaskRunner
* task_runner() const { return task_runner_
; }
77 base::OneShotTimer
<IndexedDBBackingStore
>* close_timer() {
80 IndexedDBActiveBlobRegistry
* active_blob_registry() {
81 return &active_blob_registry_
;
84 static scoped_refptr
<IndexedDBBackingStore
> Open(
85 IndexedDBFactory
* indexed_db_factory
,
86 const GURL
& origin_url
,
87 const base::FilePath
& path_base
,
88 net::URLRequestContext
* request_context
,
89 blink::WebIDBDataLoss
* data_loss
,
90 std::string
* data_loss_message
,
92 base::TaskRunner
* task_runner
,
94 static scoped_refptr
<IndexedDBBackingStore
> Open(
95 IndexedDBFactory
* indexed_db_factory
,
96 const GURL
& origin_url
,
97 const base::FilePath
& path_base
,
98 net::URLRequestContext
* request_context
,
99 blink::WebIDBDataLoss
* data_loss
,
100 std::string
* data_loss_message
,
102 LevelDBFactory
* leveldb_factory
,
103 base::TaskRunner
* task_runner
,
105 static scoped_refptr
<IndexedDBBackingStore
> OpenInMemory(
106 const GURL
& origin_url
,
107 base::TaskRunner
* task_runner
);
108 static scoped_refptr
<IndexedDBBackingStore
> OpenInMemory(
109 const GURL
& origin_url
,
110 LevelDBFactory
* level_db_factory
,
111 base::TaskRunner
* task_runner
);
113 void GrantChildProcessPermissions(int child_process_id
);
115 // Compact is public for testing.
116 virtual void Compact();
117 virtual std::vector
<base::string16
> GetDatabaseNames(leveldb::Status
*);
118 virtual leveldb::Status
GetIDBDatabaseMetaData(
119 const base::string16
& name
,
120 IndexedDBDatabaseMetadata
* metadata
,
121 bool* success
) WARN_UNUSED_RESULT
;
122 virtual leveldb::Status
CreateIDBDatabaseMetaData(
123 const base::string16
& name
,
124 const base::string16
& version
,
127 virtual bool UpdateIDBDatabaseIntVersion(
128 IndexedDBBackingStore::Transaction
* transaction
,
131 virtual leveldb::Status
DeleteDatabase(const base::string16
& name
);
133 // Assumes caller has already closed the backing store.
134 static leveldb::Status
DestroyBackingStore(const base::FilePath
& path_base
,
135 const GURL
& origin_url
);
136 static bool RecordCorruptionInfo(const base::FilePath
& path_base
,
137 const GURL
& origin_url
,
138 const std::string
& message
);
139 leveldb::Status
GetObjectStores(
141 IndexedDBDatabaseMetadata::ObjectStoreMap
* map
) WARN_UNUSED_RESULT
;
142 virtual leveldb::Status
CreateObjectStore(
143 IndexedDBBackingStore::Transaction
* transaction
,
145 int64 object_store_id
,
146 const base::string16
& name
,
147 const IndexedDBKeyPath
& key_path
,
148 bool auto_increment
);
149 virtual leveldb::Status
DeleteObjectStore(
150 IndexedDBBackingStore::Transaction
* transaction
,
152 int64 object_store_id
) WARN_UNUSED_RESULT
;
154 class CONTENT_EXPORT RecordIdentifier
{
156 RecordIdentifier(const std::string
& primary_key
, int64 version
);
160 const std::string
& primary_key() const { return primary_key_
; }
161 int64
version() const { return version_
; }
162 void Reset(const std::string
& primary_key
, int64 version
) {
163 primary_key_
= primary_key
;
168 // TODO(jsbell): Make it more clear that this is the *encoded* version of
170 std::string primary_key_
;
172 DISALLOW_COPY_AND_ASSIGN(RecordIdentifier
);
175 class BlobWriteCallback
: public base::RefCounted
<BlobWriteCallback
> {
177 virtual void Run(bool succeeded
) = 0;
179 virtual ~BlobWriteCallback() {}
180 friend class base::RefCounted
<BlobWriteCallback
>;
183 virtual leveldb::Status
GetRecord(
184 IndexedDBBackingStore::Transaction
* transaction
,
186 int64 object_store_id
,
187 const IndexedDBKey
& key
,
188 IndexedDBValue
* record
) WARN_UNUSED_RESULT
;
189 virtual leveldb::Status
PutRecord(
190 IndexedDBBackingStore::Transaction
* transaction
,
192 int64 object_store_id
,
193 const IndexedDBKey
& key
,
194 IndexedDBValue
& value
,
195 ScopedVector
<webkit_blob::BlobDataHandle
>* handles
,
196 RecordIdentifier
* record
) WARN_UNUSED_RESULT
;
197 virtual leveldb::Status
ClearObjectStore(
198 IndexedDBBackingStore::Transaction
* transaction
,
200 int64 object_store_id
) WARN_UNUSED_RESULT
;
201 virtual leveldb::Status
DeleteRecord(
202 IndexedDBBackingStore::Transaction
* transaction
,
204 int64 object_store_id
,
205 const RecordIdentifier
& record
) WARN_UNUSED_RESULT
;
206 virtual leveldb::Status
GetKeyGeneratorCurrentNumber(
207 IndexedDBBackingStore::Transaction
* transaction
,
209 int64 object_store_id
,
210 int64
* current_number
) WARN_UNUSED_RESULT
;
211 virtual leveldb::Status
MaybeUpdateKeyGeneratorCurrentNumber(
212 IndexedDBBackingStore::Transaction
* transaction
,
214 int64 object_store_id
,
216 bool check_current
) WARN_UNUSED_RESULT
;
217 virtual leveldb::Status
KeyExistsInObjectStore(
218 IndexedDBBackingStore::Transaction
* transaction
,
220 int64 object_store_id
,
221 const IndexedDBKey
& key
,
222 RecordIdentifier
* found_record_identifier
,
223 bool* found
) WARN_UNUSED_RESULT
;
225 virtual leveldb::Status
CreateIndex(
226 IndexedDBBackingStore::Transaction
* transaction
,
228 int64 object_store_id
,
230 const base::string16
& name
,
231 const IndexedDBKeyPath
& key_path
,
233 bool is_multi_entry
) WARN_UNUSED_RESULT
;
234 virtual leveldb::Status
DeleteIndex(
235 IndexedDBBackingStore::Transaction
* transaction
,
237 int64 object_store_id
,
238 int64 index_id
) WARN_UNUSED_RESULT
;
239 virtual leveldb::Status
PutIndexDataForRecord(
240 IndexedDBBackingStore::Transaction
* transaction
,
242 int64 object_store_id
,
244 const IndexedDBKey
& key
,
245 const RecordIdentifier
& record
) WARN_UNUSED_RESULT
;
246 virtual leveldb::Status
GetPrimaryKeyViaIndex(
247 IndexedDBBackingStore::Transaction
* transaction
,
249 int64 object_store_id
,
251 const IndexedDBKey
& key
,
252 scoped_ptr
<IndexedDBKey
>* primary_key
) WARN_UNUSED_RESULT
;
253 virtual leveldb::Status
KeyExistsInIndex(
254 IndexedDBBackingStore::Transaction
* transaction
,
256 int64 object_store_id
,
258 const IndexedDBKey
& key
,
259 scoped_ptr
<IndexedDBKey
>* found_primary_key
,
260 bool* exists
) WARN_UNUSED_RESULT
;
262 // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
263 virtual void ReportBlobUnused(int64 database_id
, int64 blob_key
);
265 base::FilePath
GetBlobFileName(int64 database_id
, int64 key
);
276 struct CursorOptions
{
280 int64 object_store_id
;
284 std::string high_key
;
290 const IndexedDBKey
& key() const { return *current_key_
; }
291 bool Continue(leveldb::Status
* s
) { return Continue(NULL
, NULL
, SEEK
, s
); }
292 bool Continue(const IndexedDBKey
* key
,
294 leveldb::Status
* s
) {
295 return Continue(key
, NULL
, state
, s
);
297 bool Continue(const IndexedDBKey
* key
,
298 const IndexedDBKey
* primary_key
,
301 bool Advance(uint32 count
, leveldb::Status
*);
302 bool FirstSeek(leveldb::Status
*);
304 virtual Cursor
* Clone() = 0;
305 virtual const IndexedDBKey
& primary_key() const;
306 virtual IndexedDBValue
* value() = 0;
307 virtual const RecordIdentifier
& record_identifier() const;
308 virtual bool LoadCurrentRow() = 0;
311 Cursor(LevelDBTransaction
* transaction
,
312 const CursorOptions
& cursor_options
);
313 explicit Cursor(const IndexedDBBackingStore::Cursor
* other
);
315 virtual std::string
EncodeKey(const IndexedDBKey
& key
) = 0;
316 virtual std::string
EncodeKey(const IndexedDBKey
& key
,
317 const IndexedDBKey
& primary_key
) = 0;
319 bool IsPastBounds() const;
320 bool HaveEnteredRange() const;
322 LevelDBTransaction
* transaction_
;
323 const CursorOptions cursor_options_
;
324 scoped_ptr
<LevelDBIterator
> iterator_
;
325 scoped_ptr
<IndexedDBKey
> current_key_
;
326 IndexedDBBackingStore::RecordIdentifier record_identifier_
;
329 virtual scoped_ptr
<Cursor
> OpenObjectStoreKeyCursor(
330 IndexedDBBackingStore::Transaction
* transaction
,
332 int64 object_store_id
,
333 const IndexedDBKeyRange
& key_range
,
334 indexed_db::CursorDirection
,
336 virtual scoped_ptr
<Cursor
> OpenObjectStoreCursor(
337 IndexedDBBackingStore::Transaction
* transaction
,
339 int64 object_store_id
,
340 const IndexedDBKeyRange
& key_range
,
341 indexed_db::CursorDirection
,
343 virtual scoped_ptr
<Cursor
> OpenIndexKeyCursor(
344 IndexedDBBackingStore::Transaction
* transaction
,
346 int64 object_store_id
,
348 const IndexedDBKeyRange
& key_range
,
349 indexed_db::CursorDirection
,
351 virtual scoped_ptr
<Cursor
> OpenIndexCursor(
352 IndexedDBBackingStore::Transaction
* transaction
,
354 int64 object_store_id
,
356 const IndexedDBKeyRange
& key_range
,
357 indexed_db::CursorDirection
,
362 explicit Transaction(IndexedDBBackingStore
* backing_store
);
363 virtual ~Transaction();
364 virtual void Begin();
365 virtual leveldb::Status
Commit();
366 virtual void Rollback();
368 backing_store_
= NULL
;
371 void PutBlobInfo(int64 database_id
,
372 int64 object_store_id
,
373 const std::string
& object_store_data_key
,
374 std::vector
<IndexedDBBlobInfo
>*,
375 ScopedVector
<webkit_blob::BlobDataHandle
>* handles
);
377 LevelDBTransaction
* transaction() { return transaction_
; }
379 // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
381 typedef std::vector
<std::pair
<BlobEntryKey
, std::string
> >
382 BlobEntryKeyValuePairVec
;
384 class WriteDescriptor
{
386 WriteDescriptor(const GURL
& url
, int64_t key
);
387 WriteDescriptor(const base::FilePath
& path
, int64_t key
);
389 bool is_file() const { return is_file_
; }
390 const GURL
& url() const {
394 const base::FilePath
& file_path() const {
398 int64_t key() const { return key_
; }
403 base::FilePath file_path_
;
407 class ChainedBlobWriter
: public base::RefCounted
<ChainedBlobWriter
> {
409 virtual void set_delegate(
410 scoped_ptr
<fileapi::FileWriterDelegate
> delegate
) = 0;
412 // TODO(ericu): Add a reason in the event of failure.
413 virtual void ReportWriteCompletion(bool succeeded
,
414 int64 bytes_written
) = 0;
416 virtual void Abort() = 0;
419 virtual ~ChainedBlobWriter() {}
420 friend class base::RefCounted
<ChainedBlobWriter
>;
422 class ChainedBlobWriterImpl
;
424 typedef std::vector
<WriteDescriptor
> WriteDescriptorVec
;
427 class BlobChangeRecord
{
429 BlobChangeRecord(const std::string
& key
, int64 object_store_id
);
431 const std::string
& key() const { return key_
; }
432 int64
object_store_id() const { return object_store_id_
; }
433 void SetBlobInfo(std::vector
<IndexedDBBlobInfo
>* blob_info
);
434 std::vector
<IndexedDBBlobInfo
>& mutable_blob_info() { return blob_info_
; }
435 void SetHandles(ScopedVector
<webkit_blob::BlobDataHandle
>* handles
);
439 int64 object_store_id_
;
440 std::vector
<IndexedDBBlobInfo
> blob_info_
;
441 ScopedVector
<webkit_blob::BlobDataHandle
> handles_
;
443 class BlobWriteCallbackWrapper
;
444 typedef std::map
<std::string
, BlobChangeRecord
*> BlobChangeMap
;
446 // The callback will be called eventually on success or failure.
447 void WriteNewBlobs(BlobEntryKeyValuePairVec
& new_blob_entries
,
448 WriteDescriptorVec
& new_files_to_write
,
449 scoped_refptr
<BlobWriteCallback
> callback
);
451 IndexedDBBackingStore
* backing_store_
;
452 scoped_refptr
<LevelDBTransaction
> transaction_
;
453 BlobChangeMap blob_change_map_
;
455 scoped_refptr
<ChainedBlobWriter
> chained_blob_writer_
;
459 IndexedDBBackingStore(IndexedDBFactory
* indexed_db_factory
,
460 const GURL
& origin_url
,
461 const base::FilePath
& blob_path
,
462 net::URLRequestContext
* request_context
,
463 scoped_ptr
<LevelDBDatabase
> db
,
464 scoped_ptr
<LevelDBComparator
> comparator
,
465 base::TaskRunner
* task_runner
);
466 virtual ~IndexedDBBackingStore();
467 friend class base::RefCounted
<IndexedDBBackingStore
>;
469 virtual bool WriteBlobFile(
471 const Transaction::WriteDescriptor
& descriptor
,
472 Transaction::ChainedBlobWriter
* chained_blob_writer
);
473 virtual bool RemoveBlobFile(int64 database_id
, int64 key
);
474 virtual void StartJournalCleaningTimer();
475 void CleanPrimaryJournalIgnoreReturn();
478 static scoped_refptr
<IndexedDBBackingStore
> Create(
479 IndexedDBFactory
* indexed_db_factory
,
480 const GURL
& origin_url
,
481 const base::FilePath
& blob_path
,
482 net::URLRequestContext
* request_context
,
483 scoped_ptr
<LevelDBDatabase
> db
,
484 scoped_ptr
<LevelDBComparator
> comparator
,
485 base::TaskRunner
* task_runner
);
487 static bool ReadCorruptionInfo(const base::FilePath
& path_base
,
488 const GURL
& origin_url
,
489 std::string
& message
);
491 leveldb::Status
FindKeyInIndex(
492 IndexedDBBackingStore::Transaction
* transaction
,
494 int64 object_store_id
,
496 const IndexedDBKey
& key
,
497 std::string
* found_encoded_primary_key
,
499 leveldb::Status
GetIndexes(int64 database_id
,
500 int64 object_store_id
,
501 IndexedDBObjectStoreMetadata::IndexMap
* map
)
503 bool RemoveBlobDirectory(int64 database_id
);
504 leveldb::Status
CleanUpBlobJournal(const std::string
& level_db_key
);
506 IndexedDBFactory
* indexed_db_factory_
;
507 const GURL origin_url_
;
508 base::FilePath blob_path_
;
510 // The origin identifier is a key prefix unique to the origin used in the
511 // leveldb backing store to partition data by origin. It is a normalized
512 // version of the origin URL with a versioning suffix appended, e.g.
513 // "http_localhost_81@1" Since only one origin is stored per backing store
514 // this is redundant but necessary for backwards compatibility; the suffix
515 // provides for future flexibility.
516 const std::string origin_identifier_
;
518 net::URLRequestContext
* request_context_
;
519 base::TaskRunner
* task_runner_
;
520 std::set
<int> child_process_ids_granted_
;
521 base::OneShotTimer
<IndexedDBBackingStore
> journal_cleaning_timer_
;
523 scoped_ptr
<LevelDBDatabase
> db_
;
524 scoped_ptr
<LevelDBComparator
> comparator_
;
525 // Whenever blobs are registered in active_blob_registry_, indexed_db_factory_
526 // will hold a reference to this backing store.
527 IndexedDBActiveBlobRegistry active_blob_registry_
;
528 base::OneShotTimer
<IndexedDBBackingStore
> close_timer_
;
531 } // namespace content
533 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_