#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
+#include <set>
#include <string>
#include <vector>
#include "base/strings/string_piece.h"
#include "base/timer/timer.h"
#include "content/browser/indexed_db/indexed_db.h"
+#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
+#include "content/browser/indexed_db/indexed_db_blob_info.h"
+#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
#include "url/gurl.h"
+#include "webkit/browser/blob/blob_data_handle.h"
+
+namespace base {
+class TaskRunner;
+}
+
+namespace fileapi {
+class FileWriterDelegate;
+}
+
+namespace net {
+class URLRequestContext;
+}
namespace content {
+class IndexedDBFactory;
class LevelDBComparator;
class LevelDBDatabase;
struct IndexedDBValue;
};
const GURL& origin_url() const { return origin_url_; }
+ IndexedDBFactory* factory() const { return indexed_db_factory_; }
+ base::TaskRunner* task_runner() const { return task_runner_; }
base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
return &close_timer_;
}
+ IndexedDBActiveBlobRegistry* active_blob_registry() {
+ return &active_blob_registry_;
+ }
static scoped_refptr<IndexedDBBackingStore> Open(
+ IndexedDBFactory* indexed_db_factory,
const GURL& origin_url,
const base::FilePath& path_base,
+ net::URLRequestContext* request_context,
blink::WebIDBDataLoss* data_loss,
std::string* data_loss_message,
- bool* disk_full);
-
+ bool* disk_full,
+ base::TaskRunner* task_runner,
+ bool clean_journal);
static scoped_refptr<IndexedDBBackingStore> Open(
+ IndexedDBFactory* indexed_db_factory,
const GURL& origin_url,
const base::FilePath& path_base,
+ net::URLRequestContext* request_context,
blink::WebIDBDataLoss* data_loss,
std::string* data_loss_message,
bool* disk_full,
- LevelDBFactory* factory);
+ LevelDBFactory* leveldb_factory,
+ base::TaskRunner* task_runner,
+ bool clean_journal);
static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
- const GURL& origin_url);
+ const GURL& origin_url,
+ base::TaskRunner* task_runner);
static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
const GURL& origin_url,
- LevelDBFactory* factory);
+ LevelDBFactory* level_db_factory,
+ base::TaskRunner* task_runner);
+
+ void GrantChildProcessPermissions(int child_process_id);
- virtual std::vector<base::string16> GetDatabaseNames();
+ // Compact is public for testing.
+ virtual void Compact();
+ virtual std::vector<base::string16> GetDatabaseNames(leveldb::Status*);
virtual leveldb::Status GetIDBDatabaseMetaData(
const base::string16& name,
IndexedDBDatabaseMetadata* metadata,
int64 int_version);
virtual leveldb::Status DeleteDatabase(const base::string16& name);
+ // Assumes caller has already closed the backing store.
+ static leveldb::Status DestroyBackingStore(const base::FilePath& path_base,
+ const GURL& origin_url);
+ static bool RecordCorruptionInfo(const base::FilePath& path_base,
+ const GURL& origin_url,
+ const std::string& message);
leveldb::Status GetObjectStores(
int64 database_id,
IndexedDBDatabaseMetadata::ObjectStoreMap* map) WARN_UNUSED_RESULT;
DISALLOW_COPY_AND_ASSIGN(RecordIdentifier);
};
+ class BlobWriteCallback : public base::RefCounted<BlobWriteCallback> {
+ public:
+ virtual void Run(bool succeeded) = 0;
+ protected:
+ virtual ~BlobWriteCallback() {}
+ friend class base::RefCounted<BlobWriteCallback>;
+ };
+
virtual leveldb::Status GetRecord(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
int64 database_id,
int64 object_store_id,
const IndexedDBKey& key,
- const IndexedDBValue& value,
+ IndexedDBValue& value,
+ ScopedVector<webkit_blob::BlobDataHandle>* handles,
RecordIdentifier* record) WARN_UNUSED_RESULT;
virtual leveldb::Status ClearObjectStore(
IndexedDBBackingStore::Transaction* transaction,
scoped_ptr<IndexedDBKey>* found_primary_key,
bool* exists) WARN_UNUSED_RESULT;
+ // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
+ virtual void ReportBlobUnused(int64 database_id, int64 blob_key);
+
+ base::FilePath GetBlobFileName(int64 database_id, int64 key);
+
class Cursor {
public:
virtual ~Cursor();
};
const IndexedDBKey& key() const { return *current_key_; }
- bool Continue() { return Continue(NULL, NULL, SEEK); }
- bool Continue(const IndexedDBKey* key, IteratorState state) {
- return Continue(key, NULL, state);
+ bool Continue(leveldb::Status* s) { return Continue(NULL, NULL, SEEK, s); }
+ bool Continue(const IndexedDBKey* key,
+ IteratorState state,
+ leveldb::Status* s) {
+ return Continue(key, NULL, state, s);
}
bool Continue(const IndexedDBKey* key,
const IndexedDBKey* primary_key,
- IteratorState state);
- bool Advance(uint32 count);
- bool FirstSeek();
+ IteratorState state,
+ leveldb::Status*);
+ bool Advance(uint32 count, leveldb::Status*);
+ bool FirstSeek(leveldb::Status*);
virtual Cursor* Clone() = 0;
virtual const IndexedDBKey& primary_key() const;
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection);
+ indexed_db::CursorDirection,
+ leveldb::Status*);
virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection);
+ indexed_db::CursorDirection,
+ leveldb::Status*);
virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection);
+ indexed_db::CursorDirection,
+ leveldb::Status*);
virtual scoped_ptr<Cursor> OpenIndexCursor(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection);
+ indexed_db::CursorDirection,
+ leveldb::Status*);
class Transaction {
public:
backing_store_ = NULL;
transaction_ = NULL;
}
+ void PutBlobInfo(int64 database_id,
+ int64 object_store_id,
+ const std::string& object_store_data_key,
+ std::vector<IndexedDBBlobInfo>*,
+ ScopedVector<webkit_blob::BlobDataHandle>* handles);
LevelDBTransaction* transaction() { return transaction_; }
+ // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
+ // under that key.
+ typedef std::vector<std::pair<BlobEntryKey, std::string> >
+ BlobEntryKeyValuePairVec;
+
+ class WriteDescriptor {
+ public:
+ WriteDescriptor(const GURL& url, int64_t key);
+ WriteDescriptor(const base::FilePath& path, int64_t key);
+
+ bool is_file() const { return is_file_; }
+ const GURL& url() const {
+ DCHECK(!is_file_);
+ return url_;
+ }
+ const base::FilePath& file_path() const {
+ DCHECK(is_file_);
+ return file_path_;
+ }
+ int64_t key() const { return key_; }
+
+ private:
+ bool is_file_;
+ GURL url_;
+ base::FilePath file_path_;
+ int64_t key_;
+ };
+
+ class ChainedBlobWriter : public base::RefCounted<ChainedBlobWriter> {
+ public:
+ virtual void set_delegate(
+ scoped_ptr<fileapi::FileWriterDelegate> delegate) = 0;
+
+ // TODO(ericu): Add a reason in the event of failure.
+ virtual void ReportWriteCompletion(bool succeeded,
+ int64 bytes_written) = 0;
+
+ virtual void Abort() = 0;
+
+ protected:
+ virtual ~ChainedBlobWriter() {}
+ friend class base::RefCounted<ChainedBlobWriter>;
+ };
+ class ChainedBlobWriterImpl;
+
+ typedef std::vector<WriteDescriptor> WriteDescriptorVec;
+
private:
+ class BlobChangeRecord {
+ public:
+ BlobChangeRecord(const std::string& key, int64 object_store_id);
+ ~BlobChangeRecord();
+ const std::string& key() const { return key_; }
+ int64 object_store_id() const { return object_store_id_; }
+ void SetBlobInfo(std::vector<IndexedDBBlobInfo>* blob_info);
+ std::vector<IndexedDBBlobInfo>& mutable_blob_info() { return blob_info_; }
+ void SetHandles(ScopedVector<webkit_blob::BlobDataHandle>* handles);
+
+ private:
+ std::string key_;
+ int64 object_store_id_;
+ std::vector<IndexedDBBlobInfo> blob_info_;
+ ScopedVector<webkit_blob::BlobDataHandle> handles_;
+ };
+ class BlobWriteCallbackWrapper;
+ typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap;
+
+ // The callback will be called eventually on success or failure.
+ void WriteNewBlobs(BlobEntryKeyValuePairVec& new_blob_entries,
+ WriteDescriptorVec& new_files_to_write,
+ scoped_refptr<BlobWriteCallback> callback);
+
IndexedDBBackingStore* backing_store_;
scoped_refptr<LevelDBTransaction> transaction_;
+ BlobChangeMap blob_change_map_;
+ int64 database_id_;
+ scoped_refptr<ChainedBlobWriter> chained_blob_writer_;
};
protected:
- IndexedDBBackingStore(const GURL& origin_url,
+ IndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
+ const GURL& origin_url,
+ const base::FilePath& blob_path,
+ net::URLRequestContext* request_context,
scoped_ptr<LevelDBDatabase> db,
- scoped_ptr<LevelDBComparator> comparator);
+ scoped_ptr<LevelDBComparator> comparator,
+ base::TaskRunner* task_runner);
virtual ~IndexedDBBackingStore();
friend class base::RefCounted<IndexedDBBackingStore>;
+ virtual bool WriteBlobFile(
+ int64 database_id,
+ const Transaction::WriteDescriptor& descriptor,
+ Transaction::ChainedBlobWriter* chained_blob_writer);
+ virtual bool RemoveBlobFile(int64 database_id, int64 key);
+ virtual void StartJournalCleaningTimer();
+ void CleanPrimaryJournalIgnoreReturn();
+
private:
static scoped_refptr<IndexedDBBackingStore> Create(
+ IndexedDBFactory* indexed_db_factory,
const GURL& origin_url,
+ const base::FilePath& blob_path,
+ net::URLRequestContext* request_context,
scoped_ptr<LevelDBDatabase> db,
- scoped_ptr<LevelDBComparator> comparator);
+ scoped_ptr<LevelDBComparator> comparator,
+ base::TaskRunner* task_runner);
+
+ static bool ReadCorruptionInfo(const base::FilePath& path_base,
+ const GURL& origin_url,
+ std::string& message);
leveldb::Status FindKeyInIndex(
IndexedDBBackingStore::Transaction* transaction,
int64 object_store_id,
IndexedDBObjectStoreMetadata::IndexMap* map)
WARN_UNUSED_RESULT;
+ bool RemoveBlobDirectory(int64 database_id);
+ leveldb::Status CleanUpBlobJournal(const std::string& level_db_key);
+ IndexedDBFactory* indexed_db_factory_;
const GURL origin_url_;
+ base::FilePath blob_path_;
// The origin identifier is a key prefix unique to the origin used in the
// leveldb backing store to partition data by origin. It is a normalized
// provides for future flexibility.
const std::string origin_identifier_;
+ net::URLRequestContext* request_context_;
+ base::TaskRunner* task_runner_;
+ std::set<int> child_process_ids_granted_;
+ base::OneShotTimer<IndexedDBBackingStore> journal_cleaning_timer_;
+
scoped_ptr<LevelDBDatabase> db_;
scoped_ptr<LevelDBComparator> comparator_;
+ // Whenever blobs are registered in active_blob_registry_, indexed_db_factory_
+ // will hold a reference to this backing store.
+ IndexedDBActiveBlobRegistry active_blob_registry_;
base::OneShotTimer<IndexedDBBackingStore> close_timer_;
};