Index: content/browser/indexed_db/indexed_db_backing_store.cc |
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc |
index 32c53bc92fe810d1cbddf112a9f75fda9eb268ce..106a367d9e5f7ba26c7604c0683f0c06251d864f 100644 |
--- a/content/browser/indexed_db/indexed_db_backing_store.cc |
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc |
@@ -12,6 +12,8 @@ |
#include "base/metrics/histogram.h" |
#include "base/strings/string_util.h" |
#include "base/strings/utf_string_conversions.h" |
+#include "content/browser/child_process_security_policy_impl.h" |
+#include "content/browser/indexed_db/indexed_db_blob_info.h" |
#include "content/browser/indexed_db/indexed_db_database_error.h" |
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h" |
#include "content/browser/indexed_db/indexed_db_metadata.h" |
@@ -27,6 +29,7 @@ |
#include "third_party/WebKit/public/platform/WebIDBTypes.h" |
#include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h" |
#include "third_party/leveldatabase/env_chromium.h" |
+#include "webkit/browser/blob/blob_data_handle.h" |
#include "webkit/common/database/database_identifier.h" |
using base::StringPiece; |
@@ -45,6 +48,12 @@ static base::FilePath ComputeFileName(const GURL& origin_url) { |
.AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); |
} |
+static base::FilePath ComputeBlobPath(const GURL& origin_url) { |
+ return base::FilePath() |
+ .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) |
+ .AddExtension(FILE_PATH_LITERAL(".indexeddb.blob")); |
cmumford
2014/04/10 16:59:43
Nit: Consider removing leading '.' as FilePath::kE
jsbell
2014/04/11 16:19:57
Can you give an example of where this would be pro
ericu
2014/04/14 23:23:38
It need not be an extension separator as long as i
|
+} |
+ |
static base::FilePath ComputeCorruptionFileName(const GURL& origin_url) { |
return ComputeFileName(origin_url) |
.Append(FILE_PATH_LITERAL("corruption_info.json")); |
@@ -424,11 +433,13 @@ class DefaultLevelDBFactory : public LevelDBFactory { |
IndexedDBBackingStore::IndexedDBBackingStore( |
IndexedDBFactory* indexed_db_factory, |
const GURL& origin_url, |
+ const base::FilePath& blob_path, |
scoped_ptr<LevelDBDatabase> db, |
scoped_ptr<LevelDBComparator> comparator, |
base::TaskRunner* task_runner) |
: indexed_db_factory_(indexed_db_factory), |
origin_url_(origin_url), |
+ blob_path_(blob_path), |
origin_identifier_(ComputeOriginIdentifier(origin_url)), |
task_runner_(task_runner), |
db_(db.Pass()), |
@@ -436,6 +447,15 @@ IndexedDBBackingStore::IndexedDBBackingStore( |
active_blob_registry_(this) {} |
IndexedDBBackingStore::~IndexedDBBackingStore() { |
+ if (!blob_path_.empty() && !child_process_ids_granted_.empty()) { |
+ ChildProcessSecurityPolicyImpl* policy = |
+ ChildProcessSecurityPolicyImpl::GetInstance(); |
+ for (std::set<int>::iterator iter = child_process_ids_granted_.begin(); |
cmumford
2014/04/10 16:59:43
Nit: const_iterator?
ericu
2014/04/14 23:23:38
Done.
|
+ iter != child_process_ids_granted_.end(); |
+ ++iter) { |
+ policy->RevokeAllPermissionsForFile(*iter, blob_path_); |
+ } |
+ } |
// db_'s destructor uses comparator_. The order of destruction is important. |
db_.reset(); |
comparator_.reset(); |
@@ -654,6 +674,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( |
const base::FilePath file_path = |
path_base.Append(ComputeFileName(origin_url)); |
+ const base::FilePath blob_path = |
+ path_base.Append(ComputeBlobPath(origin_url)); |
if (IsPathTooLong(file_path)) { |
HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, |
@@ -749,6 +771,7 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( |
return Create(indexed_db_factory, |
origin_url, |
+ blob_path, |
db.Pass(), |
comparator.Pass(), |
task_runner); |
@@ -783,6 +806,7 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( |
return Create(NULL /* indexed_db_factory */, |
origin_url, |
+ base::FilePath(), |
db.Pass(), |
comparator.Pass(), |
task_runner); |
@@ -792,6 +816,7 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( |
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( |
IndexedDBFactory* indexed_db_factory, |
const GURL& origin_url, |
+ const base::FilePath& blob_path, |
scoped_ptr<LevelDBDatabase> db, |
scoped_ptr<LevelDBComparator> comparator, |
base::TaskRunner* task_runner) { |
@@ -800,6 +825,7 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( |
scoped_refptr<IndexedDBBackingStore> backing_store( |
new IndexedDBBackingStore(indexed_db_factory, |
origin_url, |
+ blob_path, |
db.Pass(), |
comparator.Pass(), |
task_runner)); |
@@ -810,6 +836,14 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( |
return backing_store; |
} |
+void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) { |
+ if (!child_process_ids_granted_.count(child_process_id)) { |
+ child_process_ids_granted_.insert(child_process_id); |
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( |
+ child_process_id, blob_path_); |
+ } |
+} |
+ |
std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames() { |
std::vector<base::string16> found_names; |
const std::string start_key = |
@@ -1093,7 +1127,7 @@ leveldb::Status IndexedDBBackingStore::GetObjectStores( |
INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
} |
- it->Next(); // Is evicatble. |
+ it->Next(); // Is evictable. |
if (!CheckObjectStoreAndMetaDataType(it.get(), |
stop_key, |
object_store_id, |
@@ -1382,7 +1416,8 @@ leveldb::Status IndexedDBBackingStore::PutRecord( |
int64 database_id, |
int64 object_store_id, |
const IndexedDBKey& key, |
- const IndexedDBValue& value, |
+ IndexedDBValue& value, |
+ ScopedVector<webkit_blob::BlobDataHandle>* handles, |
RecordIdentifier* record_identifier) { |
IDB_TRACE("IndexedDBBackingStore::PutRecord"); |
if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
@@ -1404,6 +1439,12 @@ leveldb::Status IndexedDBBackingStore::PutRecord( |
v.append(value.bits); |
leveldb_transaction->Put(object_store_data_key, &v); |
+ transaction->PutBlobInfo(database_id, |
+ object_store_id, |
+ object_store_data_key, |
+ &value.blob_info, |
+ handles); |
+ DCHECK(!handles->size()); |
const std::string exists_entry_key = |
ExistsEntryKey::Encode(database_id, object_store_id, key); |
@@ -1446,6 +1487,8 @@ leveldb::Status IndexedDBBackingStore::DeleteRecord( |
const std::string object_store_data_key = ObjectStoreDataKey::Encode( |
database_id, object_store_id, record_identifier.primary_key()); |
leveldb_transaction->Remove(object_store_data_key); |
+ transaction->PutBlobInfo( |
+ database_id, object_store_id, object_store_data_key, NULL, NULL); |
const std::string exists_entry_key = ExistsEntryKey::Encode( |
database_id, object_store_id, record_identifier.primary_key()); |
@@ -2767,9 +2810,14 @@ IndexedDBBackingStore::OpenIndexCursor( |
IndexedDBBackingStore::Transaction::Transaction( |
IndexedDBBackingStore* backing_store) |
- : backing_store_(backing_store) {} |
+ : backing_store_(backing_store), database_id_(-1) {} |
-IndexedDBBackingStore::Transaction::~Transaction() {} |
+IndexedDBBackingStore::Transaction::~Transaction() { |
+ BlobChangeMap::iterator iter = blob_change_map_.begin(); |
cmumford
2014/04/10 16:59:43
Can you use STLDeleteContainerPairSecondPointers()
ericu
2014/04/14 23:23:38
Done. Just barely makes it shorter, what with tha
|
+ for (; iter != blob_change_map_.end(); ++iter) { |
+ delete iter->second; |
+ } |
+} |
void IndexedDBBackingStore::Transaction::Begin() { |
IDB_TRACE("IndexedDBBackingStore::Transaction::Begin"); |
@@ -2794,4 +2842,50 @@ void IndexedDBBackingStore::Transaction::Rollback() { |
transaction_ = NULL; |
} |
+ |
+void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetBlobInfo( |
+ std::vector<IndexedDBBlobInfo>* blob_info) { |
+ blob_info_.clear(); |
+ if (blob_info) |
+ blob_info_.swap(*blob_info); |
cmumford
2014/04/10 16:59:43
Why swap the blob info vs. operator=()
ericu
2014/04/14 23:23:38
I believe that swapping the innards of a std::vect
|
+} |
+ |
+void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetHandles( |
+ ScopedVector<webkit_blob::BlobDataHandle>* handles) { |
+ handles_.clear(); |
+ if (handles) |
+ handles_.swap(*handles); |
+} |
+ |
+// 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 |
+// changes to exists or index keys here. |
+void IndexedDBBackingStore::Transaction::PutBlobInfo( |
+ int64 database_id, |
+ int64 object_store_id, |
+ const std::string& key, |
+ std::vector<IndexedDBBlobInfo>* blob_info, |
+ ScopedVector<webkit_blob::BlobDataHandle>* handles) { |
+ DCHECK_GT(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); |
+ BlobChangeRecord* record = NULL; |
+ if (it == blob_change_map_.end()) { |
+ record = new BlobChangeRecord(); |
+ blob_change_map_[key] = record; |
+ record->set_key(key); |
+ record->set_object_store_id(object_store_id); |
+ } else { |
+ record = it->second; |
+ } |
+ DCHECK_EQ(record->object_store_id(), object_store_id); |
+ record->SetBlobInfo(blob_info); |
+ record->SetHandles(handles); |
+ DCHECK(!handles || !handles->size()); |
+} |
+ |
} // namespace content |