Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / indexed_db / indexed_db_backing_store.h
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.
4
5 #ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
6 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
7
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
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"
35
36 namespace base {
37 class SequencedTaskRunner;
38 }
39
40 namespace storage {
41 class FileWriterDelegate;
42 }
43
44 namespace net {
45 class URLRequestContext;
46 }
47
48 namespace content {
49
50 class IndexedDBFactory;
51 class LevelDBComparator;
52 class LevelDBDatabase;
53 class LevelDBFactory;
54 struct IndexedDBValue;
55
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;
64   };
65
66   class CONTENT_EXPORT RecordIdentifier {
67    public:
68     RecordIdentifier(const std::string& primary_key, int64 version);
69     RecordIdentifier();
70     ~RecordIdentifier();
71
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;
77     }
78
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);
85   };
86
87   class BlobWriteCallback : public base::RefCounted<BlobWriteCallback> {
88    public:
89     virtual void Run(bool succeeded) = 0;
90
91    protected:
92     friend class base::RefCounted<BlobWriteCallback>;
93     virtual ~BlobWriteCallback() {}
94   };
95
96   class BlobChangeRecord {
97    public:
98     BlobChangeRecord(const std::string& key, int64 object_store_id);
99     ~BlobChangeRecord();
100
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_;
107     }
108     void SetHandles(ScopedVector<storage::BlobDataHandle>* handles);
109     scoped_ptr<BlobChangeRecord> Clone() const;
110
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);
117   };
118   typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap;
119
120   class CONTENT_EXPORT Transaction {
121    public:
122     explicit Transaction(IndexedDBBackingStore* backing_store);
123     virtual ~Transaction();
124
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;
134     }
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);
146
147     LevelDBTransaction* transaction() { return transaction_.get(); }
148
149     leveldb::Status GetBlobInfoForRecord(
150         int64 database_id,
151         const std::string& object_store_data_key,
152         IndexedDBValue* value);
153
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;
158
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);
166
167       bool is_file() const { return is_file_; }
168       const GURL& url() const {
169         DCHECK(!is_file_);
170         return url_;
171       }
172       const base::FilePath& file_path() const {
173         DCHECK(is_file_);
174         return file_path_;
175       }
176       int64_t key() const { return key_; }
177       int64_t size() const { return size_; }
178       base::Time last_modified() const { return last_modified_; }
179
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_;
187     };
188
189     class ChainedBlobWriter
190         : public base::RefCountedThreadSafe<ChainedBlobWriter> {
191      public:
192       virtual void set_delegate(
193           scoped_ptr<storage::FileWriterDelegate> delegate) = 0;
194
195       // TODO(ericu): Add a reason in the event of failure.
196       virtual void ReportWriteCompletion(bool succeeded,
197                                          int64 bytes_written) = 0;
198
199       virtual void Abort() = 0;
200
201      protected:
202       friend class base::RefCountedThreadSafe<ChainedBlobWriter>;
203       virtual ~ChainedBlobWriter() {}
204     };
205
206     class ChainedBlobWriterImpl;
207
208     typedef std::vector<WriteDescriptor> WriteDescriptorVec;
209
210    private:
211     class BlobWriteCallbackWrapper;
212
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();
223
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_;
231   };
232
233   class Cursor {
234    public:
235     enum IteratorState { READY = 0, SEEK };
236
237     virtual ~Cursor();
238
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;
251     };
252
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);
259     }
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*);
266
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;
272
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);
279
280     virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
281     virtual std::string EncodeKey(const IndexedDBKey& key,
282                                   const IndexedDBKey& primary_key) = 0;
283
284     bool IsPastBounds() const;
285     bool HaveEnteredRange() const;
286
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_;
294
295    private:
296     DISALLOW_COPY_AND_ASSIGN(Cursor);
297   };
298
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_;
304   }
305   IndexedDBActiveBlobRegistry* active_blob_registry() {
306     return &active_blob_registry_;
307   }
308
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);
341
342   void GrantChildProcessPermissions(int child_process_id);
343
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);
361
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;
382
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;
429
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;
466
467   // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
468   virtual void ReportBlobUnused(int64 database_id, int64 blob_key);
469
470   base::FilePath GetBlobFileName(int64 database_id, int64 key);
471
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*);
502
503  protected:
504   friend class base::RefCounted<IndexedDBBackingStore>;
505
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();
514
515   bool is_incognito() const { return !indexed_db_factory_; }
516
517   leveldb::Status SetUpMetadata();
518
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();
526
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);
537
538   static bool ReadCorruptionInfo(const base::FilePath& path_base,
539                                  const GURL& origin_url,
540                                  std::string* message);
541
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);
556
557   IndexedDBFactory* indexed_db_factory_;
558   const GURL origin_url_;
559   base::FilePath blob_path_;
560
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_;
568
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_;
574
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_;
581
582   DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStore);
583 };
584
585 }  // namespace content
586
587 #endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_