aw: Rendering test harness and end-to-end smoke test
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_backing_store.h
blob80be291b7fb1f3baf0915989ac5ebd3e702f4ab2
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,
162 int64_t key,
163 int64_t size,
164 base::Time last_modified);
165 WriteDescriptor(const base::FilePath& path,
166 int64_t key,
167 int64_t size,
168 base::Time last_modified);
170 bool is_file() const { return is_file_; }
171 const GURL& url() const {
172 DCHECK(!is_file_);
173 return url_;
175 const base::FilePath& file_path() const {
176 DCHECK(is_file_);
177 return file_path_;
179 int64_t key() const { return key_; }
180 int64_t size() const { return size_; }
181 base::Time last_modified() const { return last_modified_; }
183 private:
184 bool is_file_;
185 GURL url_;
186 base::FilePath file_path_;
187 int64_t key_;
188 int64_t size_;
189 base::Time last_modified_;
192 class ChainedBlobWriter
193 : public base::RefCountedThreadSafe<ChainedBlobWriter> {
194 public:
195 virtual void set_delegate(
196 scoped_ptr<storage::FileWriterDelegate> delegate) = 0;
198 // TODO(ericu): Add a reason in the event of failure.
199 virtual void ReportWriteCompletion(bool succeeded,
200 int64 bytes_written) = 0;
202 virtual void Abort() = 0;
204 protected:
205 friend class base::RefCountedThreadSafe<ChainedBlobWriter>;
206 virtual ~ChainedBlobWriter() {}
209 class ChainedBlobWriterImpl;
211 typedef std::vector<WriteDescriptor> WriteDescriptorVec;
213 private:
214 class BlobWriteCallbackWrapper;
216 leveldb::Status HandleBlobPreTransaction(
217 BlobEntryKeyValuePairVec* new_blob_entries,
218 WriteDescriptorVec* new_files_to_write);
219 // Returns true on success, false on failure.
220 bool CollectBlobFilesToRemove();
221 // The callback will be called eventually on success or failure.
222 void WriteNewBlobs(BlobEntryKeyValuePairVec* new_blob_entries,
223 WriteDescriptorVec* new_files_to_write,
224 scoped_refptr<BlobWriteCallback> callback);
225 leveldb::Status SortBlobsToRemove();
227 IndexedDBBackingStore* backing_store_;
228 scoped_refptr<LevelDBTransaction> transaction_;
229 BlobChangeMap blob_change_map_;
230 BlobChangeMap incognito_blob_map_;
231 int64 database_id_;
232 BlobJournalType blobs_to_remove_;
233 scoped_refptr<ChainedBlobWriter> chained_blob_writer_;
236 class Cursor {
237 public:
238 enum IteratorState { READY = 0, SEEK };
240 virtual ~Cursor();
242 struct CursorOptions {
243 CursorOptions();
244 ~CursorOptions();
245 int64 database_id;
246 int64 object_store_id;
247 int64 index_id;
248 std::string low_key;
249 bool low_open;
250 std::string high_key;
251 bool high_open;
252 bool forward;
253 bool unique;
256 const IndexedDBKey& key() const { return *current_key_; }
257 bool Continue(leveldb::Status* s) { return Continue(NULL, NULL, SEEK, s); }
258 bool Continue(const IndexedDBKey* key,
259 IteratorState state,
260 leveldb::Status* s) {
261 return Continue(key, NULL, state, s);
263 bool Continue(const IndexedDBKey* key,
264 const IndexedDBKey* primary_key,
265 IteratorState state,
266 leveldb::Status*);
267 bool Advance(uint32 count, leveldb::Status*);
268 bool FirstSeek(leveldb::Status*);
270 virtual Cursor* Clone() = 0;
271 virtual const IndexedDBKey& primary_key() const;
272 virtual IndexedDBValue* value() = 0;
273 virtual const RecordIdentifier& record_identifier() const;
274 virtual bool LoadCurrentRow() = 0;
276 protected:
277 Cursor(scoped_refptr<IndexedDBBackingStore> backing_store,
278 Transaction* transaction,
279 int64 database_id,
280 const CursorOptions& cursor_options);
281 explicit Cursor(const IndexedDBBackingStore::Cursor* other);
283 virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
284 virtual std::string EncodeKey(const IndexedDBKey& key,
285 const IndexedDBKey& primary_key) = 0;
287 bool IsPastBounds() const;
288 bool HaveEnteredRange() const;
290 IndexedDBBackingStore* backing_store_;
291 Transaction* transaction_;
292 int64 database_id_;
293 const CursorOptions cursor_options_;
294 scoped_ptr<LevelDBIterator> iterator_;
295 scoped_ptr<IndexedDBKey> current_key_;
296 IndexedDBBackingStore::RecordIdentifier record_identifier_;
298 private:
299 DISALLOW_COPY_AND_ASSIGN(Cursor);
302 const GURL& origin_url() const { return origin_url_; }
303 IndexedDBFactory* factory() const { return indexed_db_factory_; }
304 base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
305 base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
306 return &close_timer_;
308 IndexedDBActiveBlobRegistry* active_blob_registry() {
309 return &active_blob_registry_;
312 static scoped_refptr<IndexedDBBackingStore> Open(
313 IndexedDBFactory* indexed_db_factory,
314 const GURL& origin_url,
315 const base::FilePath& path_base,
316 net::URLRequestContext* request_context,
317 blink::WebIDBDataLoss* data_loss,
318 std::string* data_loss_message,
319 bool* disk_full,
320 base::SequencedTaskRunner* task_runner,
321 bool clean_journal,
322 leveldb::Status* status);
323 static scoped_refptr<IndexedDBBackingStore> Open(
324 IndexedDBFactory* indexed_db_factory,
325 const GURL& origin_url,
326 const base::FilePath& path_base,
327 net::URLRequestContext* request_context,
328 blink::WebIDBDataLoss* data_loss,
329 std::string* data_loss_message,
330 bool* disk_full,
331 LevelDBFactory* leveldb_factory,
332 base::SequencedTaskRunner* task_runner,
333 bool clean_journal,
334 leveldb::Status* status);
335 static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
336 const GURL& origin_url,
337 base::SequencedTaskRunner* task_runner,
338 leveldb::Status* status);
339 static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
340 const GURL& origin_url,
341 LevelDBFactory* leveldb_factory,
342 base::SequencedTaskRunner* task_runner,
343 leveldb::Status* status);
345 void GrantChildProcessPermissions(int child_process_id);
347 // Compact is public for testing.
348 virtual void Compact();
349 virtual std::vector<base::string16> GetDatabaseNames(leveldb::Status*);
350 virtual leveldb::Status GetIDBDatabaseMetaData(
351 const base::string16& name,
352 IndexedDBDatabaseMetadata* metadata,
353 bool* success) WARN_UNUSED_RESULT;
354 virtual leveldb::Status CreateIDBDatabaseMetaData(
355 const base::string16& name,
356 const base::string16& version,
357 int64 int_version,
358 int64* row_id);
359 virtual bool UpdateIDBDatabaseIntVersion(
360 IndexedDBBackingStore::Transaction* transaction,
361 int64 row_id,
362 int64 int_version);
363 virtual leveldb::Status DeleteDatabase(const base::string16& name);
365 // Assumes caller has already closed the backing store.
366 static leveldb::Status DestroyBackingStore(const base::FilePath& path_base,
367 const GURL& origin_url);
368 static bool RecordCorruptionInfo(const base::FilePath& path_base,
369 const GURL& origin_url,
370 const std::string& message);
371 leveldb::Status GetObjectStores(
372 int64 database_id,
373 IndexedDBDatabaseMetadata::ObjectStoreMap* map) WARN_UNUSED_RESULT;
374 virtual leveldb::Status CreateObjectStore(
375 IndexedDBBackingStore::Transaction* transaction,
376 int64 database_id,
377 int64 object_store_id,
378 const base::string16& name,
379 const IndexedDBKeyPath& key_path,
380 bool auto_increment);
381 virtual leveldb::Status DeleteObjectStore(
382 IndexedDBBackingStore::Transaction* transaction,
383 int64 database_id,
384 int64 object_store_id) WARN_UNUSED_RESULT;
386 virtual leveldb::Status GetRecord(
387 IndexedDBBackingStore::Transaction* transaction,
388 int64 database_id,
389 int64 object_store_id,
390 const IndexedDBKey& key,
391 IndexedDBValue* record) WARN_UNUSED_RESULT;
392 virtual leveldb::Status PutRecord(
393 IndexedDBBackingStore::Transaction* transaction,
394 int64 database_id,
395 int64 object_store_id,
396 const IndexedDBKey& key,
397 IndexedDBValue* value,
398 ScopedVector<storage::BlobDataHandle>* handles,
399 RecordIdentifier* record) WARN_UNUSED_RESULT;
400 virtual leveldb::Status ClearObjectStore(
401 IndexedDBBackingStore::Transaction* transaction,
402 int64 database_id,
403 int64 object_store_id) WARN_UNUSED_RESULT;
404 virtual leveldb::Status DeleteRecord(
405 IndexedDBBackingStore::Transaction* transaction,
406 int64 database_id,
407 int64 object_store_id,
408 const RecordIdentifier& record) WARN_UNUSED_RESULT;
409 virtual leveldb::Status DeleteRange(
410 IndexedDBBackingStore::Transaction* transaction,
411 int64 database_id,
412 int64 object_store_id,
413 const IndexedDBKeyRange&) WARN_UNUSED_RESULT;
414 virtual leveldb::Status GetKeyGeneratorCurrentNumber(
415 IndexedDBBackingStore::Transaction* transaction,
416 int64 database_id,
417 int64 object_store_id,
418 int64* current_number) WARN_UNUSED_RESULT;
419 virtual leveldb::Status MaybeUpdateKeyGeneratorCurrentNumber(
420 IndexedDBBackingStore::Transaction* transaction,
421 int64 database_id,
422 int64 object_store_id,
423 int64 new_state,
424 bool check_current) WARN_UNUSED_RESULT;
425 virtual leveldb::Status KeyExistsInObjectStore(
426 IndexedDBBackingStore::Transaction* transaction,
427 int64 database_id,
428 int64 object_store_id,
429 const IndexedDBKey& key,
430 RecordIdentifier* found_record_identifier,
431 bool* found) WARN_UNUSED_RESULT;
433 virtual leveldb::Status CreateIndex(
434 IndexedDBBackingStore::Transaction* transaction,
435 int64 database_id,
436 int64 object_store_id,
437 int64 index_id,
438 const base::string16& name,
439 const IndexedDBKeyPath& key_path,
440 bool is_unique,
441 bool is_multi_entry) WARN_UNUSED_RESULT;
442 virtual leveldb::Status DeleteIndex(
443 IndexedDBBackingStore::Transaction* transaction,
444 int64 database_id,
445 int64 object_store_id,
446 int64 index_id) WARN_UNUSED_RESULT;
447 virtual leveldb::Status PutIndexDataForRecord(
448 IndexedDBBackingStore::Transaction* transaction,
449 int64 database_id,
450 int64 object_store_id,
451 int64 index_id,
452 const IndexedDBKey& key,
453 const RecordIdentifier& record) WARN_UNUSED_RESULT;
454 virtual leveldb::Status GetPrimaryKeyViaIndex(
455 IndexedDBBackingStore::Transaction* transaction,
456 int64 database_id,
457 int64 object_store_id,
458 int64 index_id,
459 const IndexedDBKey& key,
460 scoped_ptr<IndexedDBKey>* primary_key) WARN_UNUSED_RESULT;
461 virtual leveldb::Status KeyExistsInIndex(
462 IndexedDBBackingStore::Transaction* transaction,
463 int64 database_id,
464 int64 object_store_id,
465 int64 index_id,
466 const IndexedDBKey& key,
467 scoped_ptr<IndexedDBKey>* found_primary_key,
468 bool* exists) WARN_UNUSED_RESULT;
470 // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
471 virtual void ReportBlobUnused(int64 database_id, int64 blob_key);
473 base::FilePath GetBlobFileName(int64 database_id, int64 key);
475 virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
476 IndexedDBBackingStore::Transaction* transaction,
477 int64 database_id,
478 int64 object_store_id,
479 const IndexedDBKeyRange& key_range,
480 blink::WebIDBCursorDirection,
481 leveldb::Status*);
482 virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
483 IndexedDBBackingStore::Transaction* transaction,
484 int64 database_id,
485 int64 object_store_id,
486 const IndexedDBKeyRange& key_range,
487 blink::WebIDBCursorDirection,
488 leveldb::Status*);
489 virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
490 IndexedDBBackingStore::Transaction* transaction,
491 int64 database_id,
492 int64 object_store_id,
493 int64 index_id,
494 const IndexedDBKeyRange& key_range,
495 blink::WebIDBCursorDirection,
496 leveldb::Status*);
497 virtual scoped_ptr<Cursor> OpenIndexCursor(
498 IndexedDBBackingStore::Transaction* transaction,
499 int64 database_id,
500 int64 object_store_id,
501 int64 index_id,
502 const IndexedDBKeyRange& key_range,
503 blink::WebIDBCursorDirection,
504 leveldb::Status*);
506 protected:
507 friend class base::RefCounted<IndexedDBBackingStore>;
509 IndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
510 const GURL& origin_url,
511 const base::FilePath& blob_path,
512 net::URLRequestContext* request_context,
513 scoped_ptr<LevelDBDatabase> db,
514 scoped_ptr<LevelDBComparator> comparator,
515 base::SequencedTaskRunner* task_runner);
516 virtual ~IndexedDBBackingStore();
518 bool is_incognito() const { return !indexed_db_factory_; }
520 leveldb::Status SetUpMetadata();
522 virtual bool WriteBlobFile(
523 int64 database_id,
524 const Transaction::WriteDescriptor& descriptor,
525 Transaction::ChainedBlobWriter* chained_blob_writer);
526 virtual bool RemoveBlobFile(int64 database_id, int64 key);
527 virtual void StartJournalCleaningTimer();
528 void CleanPrimaryJournalIgnoreReturn();
530 private:
531 static scoped_refptr<IndexedDBBackingStore> Create(
532 IndexedDBFactory* indexed_db_factory,
533 const GURL& origin_url,
534 const base::FilePath& blob_path,
535 net::URLRequestContext* request_context,
536 scoped_ptr<LevelDBDatabase> db,
537 scoped_ptr<LevelDBComparator> comparator,
538 base::SequencedTaskRunner* task_runner,
539 leveldb::Status* status);
541 static bool ReadCorruptionInfo(const base::FilePath& path_base,
542 const GURL& origin_url,
543 std::string* message);
545 leveldb::Status FindKeyInIndex(
546 IndexedDBBackingStore::Transaction* transaction,
547 int64 database_id,
548 int64 object_store_id,
549 int64 index_id,
550 const IndexedDBKey& key,
551 std::string* found_encoded_primary_key,
552 bool* found);
553 leveldb::Status GetIndexes(int64 database_id,
554 int64 object_store_id,
555 IndexedDBObjectStoreMetadata::IndexMap* map)
556 WARN_UNUSED_RESULT;
557 bool RemoveBlobDirectory(int64 database_id);
558 leveldb::Status CleanUpBlobJournal(const std::string& level_db_key);
560 IndexedDBFactory* indexed_db_factory_;
561 const GURL origin_url_;
562 base::FilePath blob_path_;
564 // The origin identifier is a key prefix unique to the origin used in the
565 // leveldb backing store to partition data by origin. It is a normalized
566 // version of the origin URL with a versioning suffix appended, e.g.
567 // "http_localhost_81@1" Since only one origin is stored per backing store
568 // this is redundant but necessary for backwards compatibility; the suffix
569 // provides for future flexibility.
570 const std::string origin_identifier_;
572 net::URLRequestContext* request_context_;
573 scoped_refptr<base::SequencedTaskRunner> task_runner_;
574 std::set<int> child_process_ids_granted_;
575 BlobChangeMap incognito_blob_map_;
576 base::OneShotTimer<IndexedDBBackingStore> journal_cleaning_timer_;
578 scoped_ptr<LevelDBDatabase> db_;
579 scoped_ptr<LevelDBComparator> comparator_;
580 // Whenever blobs are registered in active_blob_registry_, indexed_db_factory_
581 // will hold a reference to this backing store.
582 IndexedDBActiveBlobRegistry active_blob_registry_;
583 base::OneShotTimer<IndexedDBBackingStore> close_timer_;
585 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStore);
588 } // namespace content
590 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_