Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_backing_store.h
bloba15b2372a6b1761f25df1e9de1bdf3e173900b2f
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_
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <utility>
12 #include <vector>
14 #include "base/basictypes.h"
15 #include "base/files/file_path.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/strings/string_piece.h"
19 #include "base/time/time.h"
20 #include "base/timer/timer.h"
21 #include "content/browser/indexed_db/indexed_db.h"
22 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
23 #include "content/browser/indexed_db/indexed_db_blob_info.h"
24 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
25 #include "content/browser/indexed_db/indexed_db_metadata.h"
26 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
27 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
28 #include "content/common/content_export.h"
29 #include "content/common/indexed_db/indexed_db_key.h"
30 #include "content/common/indexed_db/indexed_db_key_path.h"
31 #include "content/common/indexed_db/indexed_db_key_range.h"
32 #include "storage/browser/blob/blob_data_handle.h"
33 #include "third_party/leveldatabase/src/include/leveldb/status.h"
34 #include "url/gurl.h"
36 namespace base {
37 class SequencedTaskRunner;
40 namespace storage {
41 class FileWriterDelegate;
44 namespace net {
45 class URLRequestContext;
48 namespace content {
50 class IndexedDBFactory;
51 class LevelDBComparator;
52 class LevelDBDatabase;
53 class LevelDBFactory;
54 struct IndexedDBValue;
56 class CONTENT_EXPORT IndexedDBBackingStore
57 : public base::RefCounted<IndexedDBBackingStore> {
58 public:
59 class CONTENT_EXPORT Comparator : public LevelDBComparator {
60 public:
61 int Compare(const base::StringPiece& a,
62 const base::StringPiece& b) const override;
63 const char* Name() const override;
66 class CONTENT_EXPORT RecordIdentifier {
67 public:
68 RecordIdentifier(const std::string& primary_key, int64 version);
69 RecordIdentifier();
70 ~RecordIdentifier();
72 const std::string& primary_key() const { return primary_key_; }
73 int64 version() const { return version_; }
74 void Reset(const std::string& primary_key, int64 version) {
75 primary_key_ = primary_key;
76 version_ = version;
79 private:
80 // TODO(jsbell): Make it more clear that this is the *encoded* version of
81 // the key.
82 std::string primary_key_;
83 int64 version_;
84 DISALLOW_COPY_AND_ASSIGN(RecordIdentifier);
87 class BlobWriteCallback : public base::RefCounted<BlobWriteCallback> {
88 public:
89 virtual void Run(bool succeeded) = 0;
91 protected:
92 friend class base::RefCounted<BlobWriteCallback>;
93 virtual ~BlobWriteCallback() {}
96 class BlobChangeRecord {
97 public:
98 BlobChangeRecord(const std::string& key, int64 object_store_id);
99 ~BlobChangeRecord();
101 const std::string& key() const { return key_; }
102 int64 object_store_id() const { return object_store_id_; }
103 void SetBlobInfo(std::vector<IndexedDBBlobInfo>* blob_info);
104 std::vector<IndexedDBBlobInfo>& mutable_blob_info() { return blob_info_; }
105 const std::vector<IndexedDBBlobInfo>& blob_info() const {
106 return blob_info_;
108 void SetHandles(ScopedVector<storage::BlobDataHandle>* handles);
109 scoped_ptr<BlobChangeRecord> Clone() const;
111 private:
112 std::string key_;
113 int64 object_store_id_;
114 std::vector<IndexedDBBlobInfo> blob_info_;
115 ScopedVector<storage::BlobDataHandle> handles_;
116 DISALLOW_COPY_AND_ASSIGN(BlobChangeRecord);
118 typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap;
120 class CONTENT_EXPORT Transaction {
121 public:
122 explicit Transaction(IndexedDBBackingStore* backing_store);
123 virtual ~Transaction();
125 virtual void Begin();
126 // The callback will be called eventually on success or failure, or
127 // immediately if phase one is complete due to lack of any blobs to write.
128 virtual leveldb::Status CommitPhaseOne(scoped_refptr<BlobWriteCallback>);
129 virtual leveldb::Status CommitPhaseTwo();
130 virtual void Rollback();
131 void Reset() {
132 backing_store_ = NULL;
133 transaction_ = NULL;
135 leveldb::Status PutBlobInfoIfNeeded(
136 int64 database_id,
137 int64 object_store_id,
138 const std::string& object_store_data_key,
139 std::vector<IndexedDBBlobInfo>*,
140 ScopedVector<storage::BlobDataHandle>* handles);
141 void PutBlobInfo(int64 database_id,
142 int64 object_store_id,
143 const std::string& object_store_data_key,
144 std::vector<IndexedDBBlobInfo>*,
145 ScopedVector<storage::BlobDataHandle>* handles);
147 LevelDBTransaction* transaction() { return transaction_.get(); }
149 leveldb::Status GetBlobInfoForRecord(
150 int64 database_id,
151 const std::string& object_store_data_key,
152 IndexedDBValue* value);
154 // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
155 // under that key.
156 typedef std::vector<std::pair<BlobEntryKey, std::string> >
157 BlobEntryKeyValuePairVec;
159 class WriteDescriptor {
160 public:
161 WriteDescriptor(const GURL& url, int64_t key, int64_t size);
162 WriteDescriptor(const base::FilePath& path,
163 int64_t key,
164 int64_t size,
165 base::Time last_modified);
167 bool is_file() const { return is_file_; }
168 const GURL& url() const {
169 DCHECK(!is_file_);
170 return url_;
172 const base::FilePath& file_path() const {
173 DCHECK(is_file_);
174 return file_path_;
176 int64_t key() const { return key_; }
177 int64_t size() const { return size_; }
178 base::Time last_modified() const { return last_modified_; }
180 private:
181 bool is_file_;
182 GURL url_;
183 base::FilePath file_path_;
184 int64_t key_;
185 int64_t size_;
186 base::Time last_modified_;
189 class ChainedBlobWriter
190 : public base::RefCountedThreadSafe<ChainedBlobWriter> {
191 public:
192 virtual void set_delegate(
193 scoped_ptr<storage::FileWriterDelegate> delegate) = 0;
195 // TODO(ericu): Add a reason in the event of failure.
196 virtual void ReportWriteCompletion(bool succeeded,
197 int64 bytes_written) = 0;
199 virtual void Abort() = 0;
201 protected:
202 friend class base::RefCountedThreadSafe<ChainedBlobWriter>;
203 virtual ~ChainedBlobWriter() {}
206 class ChainedBlobWriterImpl;
208 typedef std::vector<WriteDescriptor> WriteDescriptorVec;
210 private:
211 class BlobWriteCallbackWrapper;
213 leveldb::Status HandleBlobPreTransaction(
214 BlobEntryKeyValuePairVec* new_blob_entries,
215 WriteDescriptorVec* new_files_to_write);
216 // Returns true on success, false on failure.
217 bool CollectBlobFilesToRemove();
218 // The callback will be called eventually on success or failure.
219 void WriteNewBlobs(BlobEntryKeyValuePairVec* new_blob_entries,
220 WriteDescriptorVec* new_files_to_write,
221 scoped_refptr<BlobWriteCallback> callback);
222 leveldb::Status SortBlobsToRemove();
224 IndexedDBBackingStore* backing_store_;
225 scoped_refptr<LevelDBTransaction> transaction_;
226 BlobChangeMap blob_change_map_;
227 BlobChangeMap incognito_blob_map_;
228 int64 database_id_;
229 BlobJournalType blobs_to_remove_;
230 scoped_refptr<ChainedBlobWriter> chained_blob_writer_;
233 class Cursor {
234 public:
235 enum IteratorState { READY = 0, SEEK };
237 virtual ~Cursor();
239 struct CursorOptions {
240 CursorOptions();
241 ~CursorOptions();
242 int64 database_id;
243 int64 object_store_id;
244 int64 index_id;
245 std::string low_key;
246 bool low_open;
247 std::string high_key;
248 bool high_open;
249 bool forward;
250 bool unique;
253 const IndexedDBKey& key() const { return *current_key_; }
254 bool Continue(leveldb::Status* s) { return Continue(NULL, NULL, SEEK, s); }
255 bool Continue(const IndexedDBKey* key,
256 IteratorState state,
257 leveldb::Status* s) {
258 return Continue(key, NULL, state, s);
260 bool Continue(const IndexedDBKey* key,
261 const IndexedDBKey* primary_key,
262 IteratorState state,
263 leveldb::Status*);
264 bool Advance(uint32 count, leveldb::Status*);
265 bool FirstSeek(leveldb::Status*);
267 virtual Cursor* Clone() = 0;
268 virtual const IndexedDBKey& primary_key() const;
269 virtual IndexedDBValue* value() = 0;
270 virtual const RecordIdentifier& record_identifier() const;
271 virtual bool LoadCurrentRow() = 0;
273 protected:
274 Cursor(scoped_refptr<IndexedDBBackingStore> backing_store,
275 Transaction* transaction,
276 int64 database_id,
277 const CursorOptions& cursor_options);
278 explicit Cursor(const IndexedDBBackingStore::Cursor* other);
280 virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
281 virtual std::string EncodeKey(const IndexedDBKey& key,
282 const IndexedDBKey& primary_key) = 0;
284 bool IsPastBounds() const;
285 bool HaveEnteredRange() const;
287 IndexedDBBackingStore* backing_store_;
288 Transaction* transaction_;
289 int64 database_id_;
290 const CursorOptions cursor_options_;
291 scoped_ptr<LevelDBIterator> iterator_;
292 scoped_ptr<IndexedDBKey> current_key_;
293 IndexedDBBackingStore::RecordIdentifier record_identifier_;
295 private:
296 DISALLOW_COPY_AND_ASSIGN(Cursor);
299 const GURL& origin_url() const { return origin_url_; }
300 IndexedDBFactory* factory() const { return indexed_db_factory_; }
301 base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
302 base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
303 return &close_timer_;
305 IndexedDBActiveBlobRegistry* active_blob_registry() {
306 return &active_blob_registry_;
309 static scoped_refptr<IndexedDBBackingStore> Open(
310 IndexedDBFactory* indexed_db_factory,
311 const GURL& origin_url,
312 const base::FilePath& path_base,
313 net::URLRequestContext* request_context,
314 blink::WebIDBDataLoss* data_loss,
315 std::string* data_loss_message,
316 bool* disk_full,
317 base::SequencedTaskRunner* task_runner,
318 bool clean_journal,
319 leveldb::Status* status);
320 static scoped_refptr<IndexedDBBackingStore> Open(
321 IndexedDBFactory* indexed_db_factory,
322 const GURL& origin_url,
323 const base::FilePath& path_base,
324 net::URLRequestContext* request_context,
325 blink::WebIDBDataLoss* data_loss,
326 std::string* data_loss_message,
327 bool* disk_full,
328 LevelDBFactory* leveldb_factory,
329 base::SequencedTaskRunner* task_runner,
330 bool clean_journal,
331 leveldb::Status* status);
332 static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
333 const GURL& origin_url,
334 base::SequencedTaskRunner* task_runner,
335 leveldb::Status* status);
336 static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
337 const GURL& origin_url,
338 LevelDBFactory* leveldb_factory,
339 base::SequencedTaskRunner* task_runner,
340 leveldb::Status* status);
342 void GrantChildProcessPermissions(int child_process_id);
344 // Compact is public for testing.
345 virtual void Compact();
346 virtual std::vector<base::string16> GetDatabaseNames(leveldb::Status*);
347 virtual leveldb::Status GetIDBDatabaseMetaData(
348 const base::string16& name,
349 IndexedDBDatabaseMetadata* metadata,
350 bool* success) WARN_UNUSED_RESULT;
351 virtual leveldb::Status CreateIDBDatabaseMetaData(
352 const base::string16& name,
353 const base::string16& version,
354 int64 int_version,
355 int64* row_id);
356 virtual bool UpdateIDBDatabaseIntVersion(
357 IndexedDBBackingStore::Transaction* transaction,
358 int64 row_id,
359 int64 int_version);
360 virtual leveldb::Status DeleteDatabase(const base::string16& name);
362 // Assumes caller has already closed the backing store.
363 static leveldb::Status DestroyBackingStore(const base::FilePath& path_base,
364 const GURL& origin_url);
365 static bool RecordCorruptionInfo(const base::FilePath& path_base,
366 const GURL& origin_url,
367 const std::string& message);
368 leveldb::Status GetObjectStores(
369 int64 database_id,
370 IndexedDBDatabaseMetadata::ObjectStoreMap* map) WARN_UNUSED_RESULT;
371 virtual leveldb::Status CreateObjectStore(
372 IndexedDBBackingStore::Transaction* transaction,
373 int64 database_id,
374 int64 object_store_id,
375 const base::string16& name,
376 const IndexedDBKeyPath& key_path,
377 bool auto_increment);
378 virtual leveldb::Status DeleteObjectStore(
379 IndexedDBBackingStore::Transaction* transaction,
380 int64 database_id,
381 int64 object_store_id) WARN_UNUSED_RESULT;
383 virtual leveldb::Status GetRecord(
384 IndexedDBBackingStore::Transaction* transaction,
385 int64 database_id,
386 int64 object_store_id,
387 const IndexedDBKey& key,
388 IndexedDBValue* record) WARN_UNUSED_RESULT;
389 virtual leveldb::Status PutRecord(
390 IndexedDBBackingStore::Transaction* transaction,
391 int64 database_id,
392 int64 object_store_id,
393 const IndexedDBKey& key,
394 IndexedDBValue* value,
395 ScopedVector<storage::BlobDataHandle>* handles,
396 RecordIdentifier* record) WARN_UNUSED_RESULT;
397 virtual leveldb::Status ClearObjectStore(
398 IndexedDBBackingStore::Transaction* transaction,
399 int64 database_id,
400 int64 object_store_id) WARN_UNUSED_RESULT;
401 virtual leveldb::Status DeleteRecord(
402 IndexedDBBackingStore::Transaction* transaction,
403 int64 database_id,
404 int64 object_store_id,
405 const RecordIdentifier& record) WARN_UNUSED_RESULT;
406 virtual leveldb::Status DeleteRange(
407 IndexedDBBackingStore::Transaction* transaction,
408 int64 database_id,
409 int64 object_store_id,
410 const IndexedDBKeyRange&) WARN_UNUSED_RESULT;
411 virtual leveldb::Status GetKeyGeneratorCurrentNumber(
412 IndexedDBBackingStore::Transaction* transaction,
413 int64 database_id,
414 int64 object_store_id,
415 int64* current_number) WARN_UNUSED_RESULT;
416 virtual leveldb::Status MaybeUpdateKeyGeneratorCurrentNumber(
417 IndexedDBBackingStore::Transaction* transaction,
418 int64 database_id,
419 int64 object_store_id,
420 int64 new_state,
421 bool check_current) WARN_UNUSED_RESULT;
422 virtual leveldb::Status KeyExistsInObjectStore(
423 IndexedDBBackingStore::Transaction* transaction,
424 int64 database_id,
425 int64 object_store_id,
426 const IndexedDBKey& key,
427 RecordIdentifier* found_record_identifier,
428 bool* found) WARN_UNUSED_RESULT;
430 virtual leveldb::Status CreateIndex(
431 IndexedDBBackingStore::Transaction* transaction,
432 int64 database_id,
433 int64 object_store_id,
434 int64 index_id,
435 const base::string16& name,
436 const IndexedDBKeyPath& key_path,
437 bool is_unique,
438 bool is_multi_entry) WARN_UNUSED_RESULT;
439 virtual leveldb::Status DeleteIndex(
440 IndexedDBBackingStore::Transaction* transaction,
441 int64 database_id,
442 int64 object_store_id,
443 int64 index_id) WARN_UNUSED_RESULT;
444 virtual leveldb::Status PutIndexDataForRecord(
445 IndexedDBBackingStore::Transaction* transaction,
446 int64 database_id,
447 int64 object_store_id,
448 int64 index_id,
449 const IndexedDBKey& key,
450 const RecordIdentifier& record) WARN_UNUSED_RESULT;
451 virtual leveldb::Status GetPrimaryKeyViaIndex(
452 IndexedDBBackingStore::Transaction* transaction,
453 int64 database_id,
454 int64 object_store_id,
455 int64 index_id,
456 const IndexedDBKey& key,
457 scoped_ptr<IndexedDBKey>* primary_key) WARN_UNUSED_RESULT;
458 virtual leveldb::Status KeyExistsInIndex(
459 IndexedDBBackingStore::Transaction* transaction,
460 int64 database_id,
461 int64 object_store_id,
462 int64 index_id,
463 const IndexedDBKey& key,
464 scoped_ptr<IndexedDBKey>* found_primary_key,
465 bool* exists) WARN_UNUSED_RESULT;
467 // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
468 virtual void ReportBlobUnused(int64 database_id, int64 blob_key);
470 base::FilePath GetBlobFileName(int64 database_id, int64 key);
472 virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
473 IndexedDBBackingStore::Transaction* transaction,
474 int64 database_id,
475 int64 object_store_id,
476 const IndexedDBKeyRange& key_range,
477 blink::WebIDBCursorDirection,
478 leveldb::Status*);
479 virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
480 IndexedDBBackingStore::Transaction* transaction,
481 int64 database_id,
482 int64 object_store_id,
483 const IndexedDBKeyRange& key_range,
484 blink::WebIDBCursorDirection,
485 leveldb::Status*);
486 virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
487 IndexedDBBackingStore::Transaction* transaction,
488 int64 database_id,
489 int64 object_store_id,
490 int64 index_id,
491 const IndexedDBKeyRange& key_range,
492 blink::WebIDBCursorDirection,
493 leveldb::Status*);
494 virtual scoped_ptr<Cursor> OpenIndexCursor(
495 IndexedDBBackingStore::Transaction* transaction,
496 int64 database_id,
497 int64 object_store_id,
498 int64 index_id,
499 const IndexedDBKeyRange& key_range,
500 blink::WebIDBCursorDirection,
501 leveldb::Status*);
503 protected:
504 friend class base::RefCounted<IndexedDBBackingStore>;
506 IndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
507 const GURL& origin_url,
508 const base::FilePath& blob_path,
509 net::URLRequestContext* request_context,
510 scoped_ptr<LevelDBDatabase> db,
511 scoped_ptr<LevelDBComparator> comparator,
512 base::SequencedTaskRunner* task_runner);
513 virtual ~IndexedDBBackingStore();
515 bool is_incognito() const { return !indexed_db_factory_; }
517 leveldb::Status SetUpMetadata();
519 virtual bool WriteBlobFile(
520 int64 database_id,
521 const Transaction::WriteDescriptor& descriptor,
522 Transaction::ChainedBlobWriter* chained_blob_writer);
523 virtual bool RemoveBlobFile(int64 database_id, int64 key);
524 virtual void StartJournalCleaningTimer();
525 void CleanPrimaryJournalIgnoreReturn();
527 private:
528 static scoped_refptr<IndexedDBBackingStore> Create(
529 IndexedDBFactory* indexed_db_factory,
530 const GURL& origin_url,
531 const base::FilePath& blob_path,
532 net::URLRequestContext* request_context,
533 scoped_ptr<LevelDBDatabase> db,
534 scoped_ptr<LevelDBComparator> comparator,
535 base::SequencedTaskRunner* task_runner,
536 leveldb::Status* status);
538 static bool ReadCorruptionInfo(const base::FilePath& path_base,
539 const GURL& origin_url,
540 std::string* message);
542 leveldb::Status FindKeyInIndex(
543 IndexedDBBackingStore::Transaction* transaction,
544 int64 database_id,
545 int64 object_store_id,
546 int64 index_id,
547 const IndexedDBKey& key,
548 std::string* found_encoded_primary_key,
549 bool* found);
550 leveldb::Status GetIndexes(int64 database_id,
551 int64 object_store_id,
552 IndexedDBObjectStoreMetadata::IndexMap* map)
553 WARN_UNUSED_RESULT;
554 bool RemoveBlobDirectory(int64 database_id);
555 leveldb::Status CleanUpBlobJournal(const std::string& level_db_key);
557 IndexedDBFactory* indexed_db_factory_;
558 const GURL origin_url_;
559 base::FilePath blob_path_;
561 // The origin identifier is a key prefix unique to the origin used in the
562 // leveldb backing store to partition data by origin. It is a normalized
563 // version of the origin URL with a versioning suffix appended, e.g.
564 // "http_localhost_81@1" Since only one origin is stored per backing store
565 // this is redundant but necessary for backwards compatibility; the suffix
566 // provides for future flexibility.
567 const std::string origin_identifier_;
569 net::URLRequestContext* request_context_;
570 scoped_refptr<base::SequencedTaskRunner> task_runner_;
571 std::set<int> child_process_ids_granted_;
572 BlobChangeMap incognito_blob_map_;
573 base::OneShotTimer<IndexedDBBackingStore> journal_cleaning_timer_;
575 scoped_ptr<LevelDBDatabase> db_;
576 scoped_ptr<LevelDBComparator> comparator_;
577 // Whenever blobs are registered in active_blob_registry_, indexed_db_factory_
578 // will hold a reference to this backing store.
579 IndexedDBActiveBlobRegistry active_blob_registry_;
580 base::OneShotTimer<IndexedDBBackingStore> close_timer_;
582 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStore);
585 } // namespace content
587 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_