Commit 496cbfbe authored by ericu@chromium.org's avatar ericu@chromium.org

More changes to support incognito mode in the IDB/Blob code.

Also includes a few small cleanup changes I noticed while I was in there.

BUG=108012

Review URL: https://codereview.chromium.org/261843004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269605 0039d316-1c4b-4281-b951-d872f2087c98
parent 509ac32e
......@@ -602,6 +602,8 @@ IndexedDBBackingStore::~IndexedDBBackingStore() {
policy->RevokeAllPermissionsForFile(*iter, blob_path_);
}
}
STLDeleteContainerPairSecondPointers(incognito_blob_map_.begin(),
incognito_blob_map_.end());
// db_'s destructor uses comparator_. The order of destruction is important.
db_.reset();
comparator_.reset();
......@@ -1016,7 +1018,8 @@ std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames(
*s = it->Next()) {
StringPiece slice(it->Key());
DatabaseNameKey database_name_key;
if (!DatabaseNameKey::Decode(&slice, &database_name_key)) {
if (!DatabaseNameKey::Decode(&slice, &database_name_key) ||
!slice.empty()) {
INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES);
continue;
}
......@@ -1256,9 +1259,10 @@ leveldb::Status IndexedDBBackingStore::GetObjectStores(
while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
StringPiece slice(it->Key());
ObjectStoreMetaDataKey meta_data_key;
bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key);
bool ok =
ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key) && slice.empty();
DCHECK(ok);
if (meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) {
if (!ok || meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) {
INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
// Possible stale metadata, but don't fail the load.
s = it->Next();
......@@ -1764,7 +1768,7 @@ leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
s = it->Next()) {
StringPiece slice(it->Key());
ObjectStoreDataKey data_key;
if (!ObjectStoreDataKey::Decode(&slice, &data_key)) {
if (!ObjectStoreDataKey::Decode(&slice, &data_key) || !slice.empty()) {
INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
return InternalInconsistencyStatus();
}
......@@ -3399,17 +3403,28 @@ IndexedDBBackingStore::OpenIndexCursor(
IndexedDBBackingStore::Transaction::Transaction(
IndexedDBBackingStore* backing_store)
: backing_store_(backing_store), database_id_(-1) {}
: backing_store_(backing_store), database_id_(-1) {
}
IndexedDBBackingStore::Transaction::~Transaction() {
STLDeleteContainerPairSecondPointers(
blob_change_map_.begin(), blob_change_map_.end());
STLDeleteContainerPairSecondPointers(incognito_blob_map_.begin(),
incognito_blob_map_.end());
}
void IndexedDBBackingStore::Transaction::Begin() {
IDB_TRACE("IndexedDBBackingStore::Transaction::Begin");
DCHECK(!transaction_.get());
transaction_ = new LevelDBTransaction(backing_store_->db_.get());
// If incognito, this snapshots blobs just as the above transaction_
// constructor snapshots the leveldb.
BlobChangeMap::const_iterator iter;
for (iter = backing_store_->incognito_blob_map_.begin();
iter != backing_store_->incognito_blob_map_.end();
++iter)
incognito_blob_map_[iter->first] = iter->second->Clone().release();
}
leveldb::Status IndexedDBBackingStore::Transaction::Commit() {
......@@ -3417,6 +3432,23 @@ leveldb::Status IndexedDBBackingStore::Transaction::Commit() {
DCHECK(transaction_.get());
leveldb::Status s = transaction_->Commit();
transaction_ = NULL;
if (s.ok() && backing_store_->is_incognito() && !blob_change_map_.empty()) {
BlobChangeMap& target_map = backing_store_->incognito_blob_map_;
BlobChangeMap::iterator iter;
for (iter = blob_change_map_.begin(); iter != blob_change_map_.end();
++iter) {
BlobChangeMap::iterator target_record = target_map.find(iter->first);
if (target_record != target_map.end()) {
delete target_record->second;
target_map.erase(target_record);
}
if (iter->second) {
target_map[iter->first] = iter->second;
iter->second = NULL;
}
}
}
if (!s.ok())
INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
return s;
......@@ -3479,28 +3511,41 @@ void IndexedDBBackingStore::Transaction::Rollback() {
transaction_ = NULL;
}
IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord(
const std::string& key, int64 object_store_id)
IndexedDBBackingStore::BlobChangeRecord::BlobChangeRecord(
const std::string& key,
int64 object_store_id)
: key_(key), object_store_id_(object_store_id) {
}
IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() {
IndexedDBBackingStore::BlobChangeRecord::~BlobChangeRecord() {
}
void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetBlobInfo(
void IndexedDBBackingStore::BlobChangeRecord::SetBlobInfo(
std::vector<IndexedDBBlobInfo>* blob_info) {
blob_info_.clear();
if (blob_info)
blob_info_.swap(*blob_info);
}
void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetHandles(
void IndexedDBBackingStore::BlobChangeRecord::SetHandles(
ScopedVector<webkit_blob::BlobDataHandle>* handles) {
handles_.clear();
if (handles)
handles_.swap(*handles);
}
scoped_ptr<IndexedDBBackingStore::BlobChangeRecord>
IndexedDBBackingStore::BlobChangeRecord::Clone() const {
scoped_ptr<IndexedDBBackingStore::BlobChangeRecord> record(
new BlobChangeRecord(key_, object_store_id_));
record->blob_info_ = blob_info_;
ScopedVector<webkit_blob::BlobDataHandle>::const_iterator iter;
for (iter = handles_.begin(); iter != handles_.end(); ++iter)
record->handles_.push_back(new webkit_blob::BlobDataHandle(**iter));
return record.Pass();
}
// This is storing an info, even if empty, even if the previous key had no blob
// info that we know of. It duplicates a bunch of information stored in the
// leveldb transaction, but only w.r.t. the user keys altered--we don't keep the
......@@ -3508,19 +3553,19 @@ void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetHandles(
void IndexedDBBackingStore::Transaction::PutBlobInfo(
int64 database_id,
int64 object_store_id,
const std::string& key,
const std::string& object_store_data_key,
std::vector<IndexedDBBlobInfo>* blob_info,
ScopedVector<webkit_blob::BlobDataHandle>* handles) {
DCHECK_GT(key.size(), 0UL);
DCHECK_GT(object_store_data_key.size(), 0UL);
if (database_id_ < 0)
database_id_ = database_id;
DCHECK_EQ(database_id_, database_id);
BlobChangeMap::iterator it = blob_change_map_.find(key);
BlobChangeMap::iterator it = blob_change_map_.find(object_store_data_key);
BlobChangeRecord* record = NULL;
if (it == blob_change_map_.end()) {
record = new BlobChangeRecord(key, object_store_id);
blob_change_map_[key] = record;
record = new BlobChangeRecord(object_store_data_key, object_store_id);
blob_change_map_[object_store_data_key] = record;
} else {
record = it->second;
}
......
......@@ -107,7 +107,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
base::TaskRunner* task_runner);
static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
const GURL& origin_url,
LevelDBFactory* level_db_factory,
LevelDBFactory* leveldb_factory,
base::TaskRunner* task_runner);
void GrantChildProcessPermissions(int child_process_id);
......@@ -357,6 +357,29 @@ class CONTENT_EXPORT IndexedDBBackingStore
indexed_db::CursorDirection,
leveldb::Status*);
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_; }
const std::vector<IndexedDBBlobInfo>& blob_info() const {
return blob_info_;
}
void SetHandles(ScopedVector<webkit_blob::BlobDataHandle>* handles);
scoped_ptr<BlobChangeRecord> Clone() const;
private:
std::string key_;
int64 object_store_id_;
std::vector<IndexedDBBlobInfo> blob_info_;
ScopedVector<webkit_blob::BlobDataHandle> handles_;
DISALLOW_COPY_AND_ASSIGN(BlobChangeRecord);
};
typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap;
class Transaction {
public:
explicit Transaction(IndexedDBBackingStore* backing_store);
......@@ -424,24 +447,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
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,
......@@ -451,6 +457,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBBackingStore* backing_store_;
scoped_refptr<LevelDBTransaction> transaction_;
BlobChangeMap blob_change_map_;
BlobChangeMap incognito_blob_map_;
int64 database_id_;
scoped_refptr<ChainedBlobWriter> chained_blob_writer_;
};
......@@ -466,6 +473,8 @@ class CONTENT_EXPORT IndexedDBBackingStore
virtual ~IndexedDBBackingStore();
friend class base::RefCounted<IndexedDBBackingStore>;
bool is_incognito() const { return !indexed_db_factory_; }
virtual bool WriteBlobFile(
int64 database_id,
const Transaction::WriteDescriptor& descriptor,
......@@ -518,6 +527,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
net::URLRequestContext* request_context_;
base::TaskRunner* task_runner_;
std::set<int> child_process_ids_granted_;
BlobChangeMap incognito_blob_map_;
base::OneShotTimer<IndexedDBBackingStore> journal_cleaning_timer_;
scoped_ptr<LevelDBDatabase> db_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment