| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/dom_storage/local_storage_context_mojo.h" | 5 #include "content/browser/dom_storage/local_storage_context_mojo.h" |
| 6 | 6 |
| 7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "components/leveldb/public/cpp/util.h" | 9 #include "components/leveldb/public/cpp/util.h" |
| 10 #include "components/leveldb/public/interfaces/leveldb.mojom.h" | 10 #include "components/leveldb/public/interfaces/leveldb.mojom.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 const int64_t kCurrentSchemaVersion = 1; | 41 const int64_t kCurrentSchemaVersion = 1; |
| 42 | 42 |
| 43 std::vector<uint8_t> CreateMetaDataKey(const url::Origin& origin) { | 43 std::vector<uint8_t> CreateMetaDataKey(const url::Origin& origin) { |
| 44 auto serialized_origin = leveldb::StdStringToUint8Vector(origin.Serialize()); | 44 auto serialized_origin = leveldb::StdStringToUint8Vector(origin.Serialize()); |
| 45 std::vector<uint8_t> key; | 45 std::vector<uint8_t> key; |
| 46 key.reserve(arraysize(kMetaPrefix) + serialized_origin.size()); | 46 key.reserve(arraysize(kMetaPrefix) + serialized_origin.size()); |
| 47 key.insert(key.end(), kMetaPrefix, kMetaPrefix + arraysize(kMetaPrefix)); | 47 key.insert(key.end(), kMetaPrefix, kMetaPrefix + arraysize(kMetaPrefix)); |
| 48 key.insert(key.end(), serialized_origin.begin(), serialized_origin.end()); | 48 key.insert(key.end(), serialized_origin.begin(), serialized_origin.end()); |
| 49 return key; | 49 return key; |
| 50 } | 50 } |
| 51 |
| 52 void NoOpSuccess(bool success) {} |
| 51 } | 53 } |
| 52 | 54 |
| 53 LocalStorageContextMojo::LocalStorageContextMojo( | 55 LocalStorageContextMojo::LocalStorageContextMojo( |
| 54 service_manager::Connector* connector, | 56 service_manager::Connector* connector, |
| 55 const base::FilePath& subdirectory) | 57 const base::FilePath& subdirectory) |
| 56 : connector_(connector), | 58 : connector_(connector), |
| 57 subdirectory_(subdirectory), | 59 subdirectory_(subdirectory), |
| 58 weak_ptr_factory_(this) {} | 60 weak_ptr_factory_(this) {} |
| 59 | 61 |
| 60 LocalStorageContextMojo::~LocalStorageContextMojo() {} | 62 LocalStorageContextMojo::~LocalStorageContextMojo() {} |
| 61 | 63 |
| 62 void LocalStorageContextMojo::OpenLocalStorage( | 64 void LocalStorageContextMojo::OpenLocalStorage( |
| 63 const url::Origin& origin, | 65 const url::Origin& origin, |
| 64 mojom::LevelDBWrapperRequest request) { | 66 mojom::LevelDBWrapperRequest request) { |
| 65 RunWhenConnected(base::BindOnce(&LocalStorageContextMojo::BindLocalStorage, | 67 RunWhenConnected(base::BindOnce(&LocalStorageContextMojo::BindLocalStorage, |
| 66 weak_ptr_factory_.GetWeakPtr(), origin, | 68 weak_ptr_factory_.GetWeakPtr(), origin, |
| 67 std::move(request))); | 69 std::move(request))); |
| 68 } | 70 } |
| 69 | 71 |
| 70 void LocalStorageContextMojo::GetStorageUsage( | 72 void LocalStorageContextMojo::GetStorageUsage( |
| 71 GetStorageUsageCallback callback) { | 73 GetStorageUsageCallback callback) { |
| 72 RunWhenConnected( | 74 RunWhenConnected( |
| 73 base::BindOnce(&LocalStorageContextMojo::RetrieveStorageUsage, | 75 base::BindOnce(&LocalStorageContextMojo::RetrieveStorageUsage, |
| 74 weak_ptr_factory_.GetWeakPtr(), std::move(callback))); | 76 weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| 75 } | 77 } |
| 76 | 78 |
| 79 void LocalStorageContextMojo::DeleteStorage(const url::Origin& origin) { |
| 80 if (connection_state_ != CONNECTION_FINISHED) { |
| 81 RunWhenConnected(base::BindOnce(&LocalStorageContextMojo::DeleteStorage, |
| 82 weak_ptr_factory_.GetWeakPtr(), origin)); |
| 83 return; |
| 84 } |
| 85 |
| 86 LevelDBWrapperImpl* wrapper = GetOrCreateDBWrapper(origin); |
| 87 // Renderer process expects |source| to always be two newline separated |
| 88 // strings. |
| 89 wrapper->DeleteAll("\n", base::Bind(&NoOpSuccess)); |
| 90 wrapper->ScheduleImmediateCommit(); |
| 91 } |
| 92 |
| 93 void LocalStorageContextMojo::DeleteStorageForPhysicalOrigin( |
| 94 const url::Origin& origin) { |
| 95 GetStorageUsage(base::BindOnce( |
| 96 &LocalStorageContextMojo::OnGotStorageUsageForDeletePhysicalOrigin, |
| 97 weak_ptr_factory_.GetWeakPtr(), origin)); |
| 98 } |
| 99 |
| 77 void LocalStorageContextMojo::SetDatabaseForTesting( | 100 void LocalStorageContextMojo::SetDatabaseForTesting( |
| 78 leveldb::mojom::LevelDBDatabasePtr database) { | 101 leveldb::mojom::LevelDBDatabasePtr database) { |
| 79 DCHECK_EQ(connection_state_, NO_CONNECTION); | 102 DCHECK_EQ(connection_state_, NO_CONNECTION); |
| 80 connection_state_ = CONNECTION_IN_PROGRESS; | 103 connection_state_ = CONNECTION_IN_PROGRESS; |
| 81 database_ = std::move(database); | 104 database_ = std::move(database); |
| 82 OnDatabaseOpened(leveldb::mojom::DatabaseError::OK); | 105 OnDatabaseOpened(leveldb::mojom::DatabaseError::OK); |
| 83 } | 106 } |
| 84 | 107 |
| 85 void LocalStorageContextMojo::RunWhenConnected(base::OnceClosure callback) { | 108 void LocalStorageContextMojo::RunWhenConnected(base::OnceClosure callback) { |
| 86 // If we don't have a filesystem_connection_, we'll need to establish one. | 109 // If we don't have a filesystem_connection_, we'll need to establish one. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 item->type = leveldb::mojom::BatchOperationType::PUT_KEY; | 167 item->type = leveldb::mojom::BatchOperationType::PUT_KEY; |
| 145 item->key = leveldb::StdStringToUint8Vector(kVersionKey); | 168 item->key = leveldb::StdStringToUint8Vector(kVersionKey); |
| 146 item->value = leveldb::StdStringToUint8Vector( | 169 item->value = leveldb::StdStringToUint8Vector( |
| 147 base::Int64ToString(kCurrentSchemaVersion)); | 170 base::Int64ToString(kCurrentSchemaVersion)); |
| 148 operations.push_back(std::move(item)); | 171 operations.push_back(std::move(item)); |
| 149 database_initialized_ = true; | 172 database_initialized_ = true; |
| 150 } | 173 } |
| 151 | 174 |
| 152 leveldb::mojom::BatchedOperationPtr item = | 175 leveldb::mojom::BatchedOperationPtr item = |
| 153 leveldb::mojom::BatchedOperation::New(); | 176 leveldb::mojom::BatchedOperation::New(); |
| 177 item->type = leveldb::mojom::BatchOperationType::PUT_KEY; |
| 154 item->key = CreateMetaDataKey(origin); | 178 item->key = CreateMetaDataKey(origin); |
| 155 if (wrapper.bytes_used() == 0) { | 179 if (wrapper.bytes_used() == 0) { |
| 156 item->type = leveldb::mojom::BatchOperationType::DELETE_KEY; | 180 item->type = leveldb::mojom::BatchOperationType::DELETE_KEY; |
| 157 } else { | 181 } else { |
| 158 item->type = leveldb::mojom::BatchOperationType::PUT_KEY; | 182 item->type = leveldb::mojom::BatchOperationType::PUT_KEY; |
| 159 LocalStorageOriginMetaData data; | 183 LocalStorageOriginMetaData data; |
| 160 data.set_last_modified(base::Time::Now().ToInternalValue()); | 184 data.set_last_modified(base::Time::Now().ToInternalValue()); |
| 161 data.set_size_bytes(wrapper.bytes_used()); | 185 data.set_size_bytes(wrapper.bytes_used()); |
| 162 item->value = leveldb::StdStringToUint8Vector(data.SerializeAsString()); | 186 item->value = leveldb::StdStringToUint8Vector(data.SerializeAsString()); |
| 163 } | 187 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 for (size_t i = 0; i < on_database_opened_callbacks_.size(); ++i) | 278 for (size_t i = 0; i < on_database_opened_callbacks_.size(); ++i) |
| 255 std::move(on_database_opened_callbacks_[i]).Run(); | 279 std::move(on_database_opened_callbacks_[i]).Run(); |
| 256 on_database_opened_callbacks_.clear(); | 280 on_database_opened_callbacks_.clear(); |
| 257 } | 281 } |
| 258 | 282 |
| 259 // The (possibly delayed) implementation of OpenLocalStorage(). Can be called | 283 // The (possibly delayed) implementation of OpenLocalStorage(). Can be called |
| 260 // directly from that function, or through |on_database_open_callbacks_|. | 284 // directly from that function, or through |on_database_open_callbacks_|. |
| 261 void LocalStorageContextMojo::BindLocalStorage( | 285 void LocalStorageContextMojo::BindLocalStorage( |
| 262 const url::Origin& origin, | 286 const url::Origin& origin, |
| 263 mojom::LevelDBWrapperRequest request) { | 287 mojom::LevelDBWrapperRequest request) { |
| 288 GetOrCreateDBWrapper(origin)->Bind(std::move(request)); |
| 289 } |
| 290 |
| 291 LevelDBWrapperImpl* LocalStorageContextMojo::GetOrCreateDBWrapper( |
| 292 const url::Origin& origin) { |
| 293 DCHECK_EQ(connection_state_, CONNECTION_FINISHED); |
| 294 auto found = level_db_wrappers_.find(origin); |
| 295 if (found != level_db_wrappers_.end()) |
| 296 return found->second.get(); |
| 297 |
| 264 // Delay for a moment after a value is set in anticipation | 298 // Delay for a moment after a value is set in anticipation |
| 265 // of other values being set, so changes are batched. | 299 // of other values being set, so changes are batched. |
| 266 const int kCommitDefaultDelaySecs = 5; | 300 const int kCommitDefaultDelaySecs = 5; |
| 267 | 301 |
| 268 // To avoid excessive IO we apply limits to the amount of data being written | 302 // To avoid excessive IO we apply limits to the amount of data being written |
| 269 // and the frequency of writes. | 303 // and the frequency of writes. |
| 270 const int kMaxBytesPerHour = kPerStorageAreaQuota; | 304 const int kMaxBytesPerHour = kPerStorageAreaQuota; |
| 271 const int kMaxCommitsPerHour = 60; | 305 const int kMaxCommitsPerHour = 60; |
| 272 | 306 |
| 273 auto found = level_db_wrappers_.find(origin); | 307 auto wrapper = base::MakeUnique<LevelDBWrapperImpl>( |
| 274 if (found == level_db_wrappers_.end()) { | 308 database_.get(), kDataPrefix + origin.Serialize() + kOriginSeparator, |
| 275 level_db_wrappers_[origin] = base::MakeUnique<LevelDBWrapperImpl>( | 309 kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance, |
| 276 database_.get(), kDataPrefix + origin.Serialize() + kOriginSeparator, | 310 base::TimeDelta::FromSeconds(kCommitDefaultDelaySecs), kMaxBytesPerHour, |
| 277 kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance, | 311 kMaxCommitsPerHour, |
| 278 base::TimeDelta::FromSeconds(kCommitDefaultDelaySecs), kMaxBytesPerHour, | 312 base::Bind(&LocalStorageContextMojo::OnLevelDBWrapperHasNoBindings, |
| 279 kMaxCommitsPerHour, | 313 base::Unretained(this), origin), |
| 280 base::Bind(&LocalStorageContextMojo::OnLevelDBWrapperHasNoBindings, | 314 base::Bind(&LocalStorageContextMojo::OnLevelDBWrapperPrepareToCommit, |
| 281 base::Unretained(this), origin), | 315 base::Unretained(this), origin)); |
| 282 base::Bind(&LocalStorageContextMojo::OnLevelDBWrapperPrepareToCommit, | 316 LevelDBWrapperImpl* wrapper_ptr = wrapper.get(); |
| 283 base::Unretained(this), origin)); | 317 level_db_wrappers_[origin] = std::move(wrapper); |
| 284 found = level_db_wrappers_.find(origin); | 318 return wrapper_ptr; |
| 285 } | |
| 286 | |
| 287 found->second->Bind(std::move(request)); | |
| 288 } | 319 } |
| 289 | 320 |
| 290 void LocalStorageContextMojo::RetrieveStorageUsage( | 321 void LocalStorageContextMojo::RetrieveStorageUsage( |
| 291 GetStorageUsageCallback callback) { | 322 GetStorageUsageCallback callback) { |
| 292 database_->GetPrefixed( | 323 database_->GetPrefixed( |
| 293 std::vector<uint8_t>(kMetaPrefix, kMetaPrefix + arraysize(kMetaPrefix)), | 324 std::vector<uint8_t>(kMetaPrefix, kMetaPrefix + arraysize(kMetaPrefix)), |
| 294 base::Bind(&LocalStorageContextMojo::OnGotMetaData, | 325 base::Bind(&LocalStorageContextMojo::OnGotMetaData, |
| 295 weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback))); | 326 weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback))); |
| 296 } | 327 } |
| 297 | 328 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 315 // TODO(mek): Deal with database corruption. | 346 // TODO(mek): Deal with database corruption. |
| 316 continue; | 347 continue; |
| 317 } | 348 } |
| 318 info.data_size = data.size_bytes(); | 349 info.data_size = data.size_bytes(); |
| 319 info.last_modified = base::Time::FromInternalValue(data.last_modified()); | 350 info.last_modified = base::Time::FromInternalValue(data.last_modified()); |
| 320 result.push_back(std::move(info)); | 351 result.push_back(std::move(info)); |
| 321 } | 352 } |
| 322 std::move(callback).Run(std::move(result)); | 353 std::move(callback).Run(std::move(result)); |
| 323 } | 354 } |
| 324 | 355 |
| 356 void LocalStorageContextMojo::OnGotStorageUsageForDeletePhysicalOrigin( |
| 357 const url::Origin& origin, |
| 358 std::vector<LocalStorageUsageInfo> usage) { |
| 359 for (const auto& info : usage) { |
| 360 url::Origin origin_candidate(info.origin); |
| 361 if (!origin_candidate.IsSameOriginWith(origin) && |
| 362 origin_candidate.IsSamePhysicalOriginWith(origin)) |
| 363 DeleteStorage(origin_candidate); |
| 364 } |
| 365 DeleteStorage(origin); |
| 366 } |
| 367 |
| 325 } // namespace content | 368 } // namespace content |
| OLD | NEW |