| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/dom_storage_context_wrapper.h" | 5 #include "content/browser/dom_storage/dom_storage_context_wrapper.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 MojoState(service_manager::Connector* connector, | 89 MojoState(service_manager::Connector* connector, |
| 90 const base::FilePath& subdirectory) | 90 const base::FilePath& subdirectory) |
| 91 : connector_(connector), | 91 : connector_(connector), |
| 92 // TODO(michaeln): Enable writing to disk when db is versioned, | 92 // TODO(michaeln): Enable writing to disk when db is versioned, |
| 93 // for now using an empty subdirectory to use an in-memory db. | 93 // for now using an empty subdirectory to use an in-memory db. |
| 94 // subdirectory_(subdirectory), | 94 // subdirectory_(subdirectory), |
| 95 connection_state_(NO_CONNECTION), | 95 connection_state_(NO_CONNECTION), |
| 96 weak_ptr_factory_(this) {} | 96 weak_ptr_factory_(this) {} |
| 97 | 97 |
| 98 void OpenLocalStorage(const url::Origin& origin, | 98 void OpenLocalStorage(const url::Origin& origin, |
| 99 mojom::LevelDBObserverPtr observer, | |
| 100 mojom::LevelDBWrapperRequest request); | 99 mojom::LevelDBWrapperRequest request); |
| 101 | 100 |
| 102 private: | 101 private: |
| 103 void OnLevelDDWrapperHasNoBindings(const url::Origin& origin) { | 102 void OnLevelDDWrapperHasNoBindings(const url::Origin& origin) { |
| 104 DCHECK(level_db_wrappers_.find(origin) != level_db_wrappers_.end()); | 103 DCHECK(level_db_wrappers_.find(origin) != level_db_wrappers_.end()); |
| 105 level_db_wrappers_.erase(origin); | 104 level_db_wrappers_.erase(origin); |
| 106 } | 105 } |
| 107 | 106 |
| 108 void OnUserServiceConnectionComplete() { | 107 void OnUserServiceConnectionComplete() { |
| 109 CHECK_EQ(service_manager::mojom::ConnectResult::SUCCEEDED, | 108 CHECK_EQ(service_manager::mojom::ConnectResult::SUCCEEDED, |
| 110 file_service_connection_->GetResult()); | 109 file_service_connection_->GetResult()); |
| 111 } | 110 } |
| 112 | 111 |
| 113 void OnUserServiceConnectionError() { | 112 void OnUserServiceConnectionError() { |
| 114 CHECK(false); | 113 CHECK(false); |
| 115 } | 114 } |
| 116 | 115 |
| 117 // Part of our asynchronous directory opening called from OpenLocalStorage(). | 116 // Part of our asynchronous directory opening called from OpenLocalStorage(). |
| 118 void OnDirectoryOpened(filesystem::mojom::FileError err); | 117 void OnDirectoryOpened(filesystem::mojom::FileError err); |
| 119 void OnDatabaseOpened(leveldb::mojom::DatabaseError status); | 118 void OnDatabaseOpened(leveldb::mojom::DatabaseError status); |
| 120 | 119 |
| 121 // The (possibly delayed) implementation of OpenLocalStorage(). Can be called | 120 // The (possibly delayed) implementation of OpenLocalStorage(). Can be called |
| 122 // directly from that function, or through |on_database_open_callbacks_|. | 121 // directly from that function, or through |on_database_open_callbacks_|. |
| 123 void BindLocalStorage(const url::Origin& origin, | 122 void BindLocalStorage(const url::Origin& origin, |
| 124 mojom::LevelDBObserverPtr observer, | |
| 125 mojom::LevelDBWrapperRequest request); | 123 mojom::LevelDBWrapperRequest request); |
| 126 | 124 |
| 127 service_manager::Connector* const connector_; | 125 service_manager::Connector* const connector_; |
| 128 const base::FilePath subdirectory_; | 126 const base::FilePath subdirectory_; |
| 129 | 127 |
| 130 enum ConnectionState { | 128 enum ConnectionState { |
| 131 NO_CONNECTION, | 129 NO_CONNECTION, |
| 132 CONNECTION_IN_PROGRESS, | 130 CONNECTION_IN_PROGRESS, |
| 133 CONNECTION_FINISHED | 131 CONNECTION_FINISHED |
| 134 } connection_state_; | 132 } connection_state_; |
| 135 | 133 |
| 136 std::unique_ptr<service_manager::Connection> file_service_connection_; | 134 std::unique_ptr<service_manager::Connection> file_service_connection_; |
| 137 | 135 |
| 138 file::mojom::FileSystemPtr file_system_; | 136 file::mojom::FileSystemPtr file_system_; |
| 139 filesystem::mojom::DirectoryPtr directory_; | 137 filesystem::mojom::DirectoryPtr directory_; |
| 140 | 138 |
| 141 leveldb::mojom::LevelDBServicePtr leveldb_service_; | 139 leveldb::mojom::LevelDBServicePtr leveldb_service_; |
| 142 leveldb::mojom::LevelDBDatabasePtr database_; | 140 leveldb::mojom::LevelDBDatabasePtr database_; |
| 143 | 141 |
| 144 std::vector<base::Closure> on_database_opened_callbacks_; | 142 std::vector<base::Closure> on_database_opened_callbacks_; |
| 145 | 143 |
| 146 // Maps between an origin and its prefixed LevelDB view. | 144 // Maps between an origin and its prefixed LevelDB view. |
| 147 std::map<url::Origin, std::unique_ptr<LevelDBWrapperImpl>> level_db_wrappers_; | 145 std::map<url::Origin, std::unique_ptr<LevelDBWrapperImpl>> level_db_wrappers_; |
| 148 | 146 |
| 149 base::WeakPtrFactory<MojoState> weak_ptr_factory_; | 147 base::WeakPtrFactory<MojoState> weak_ptr_factory_; |
| 150 }; | 148 }; |
| 151 | 149 |
| 152 void DOMStorageContextWrapper::MojoState::OpenLocalStorage( | 150 void DOMStorageContextWrapper::MojoState::OpenLocalStorage( |
| 153 const url::Origin& origin, | 151 const url::Origin& origin, |
| 154 mojom::LevelDBObserverPtr observer, | |
| 155 mojom::LevelDBWrapperRequest request) { | 152 mojom::LevelDBWrapperRequest request) { |
| 156 // If we don't have a filesystem_connection_, we'll need to establish one. | 153 // If we don't have a filesystem_connection_, we'll need to establish one. |
| 157 if (connection_state_ == NO_CONNECTION) { | 154 if (connection_state_ == NO_CONNECTION) { |
| 158 CHECK(connector_); | 155 CHECK(connector_); |
| 159 file_service_connection_ = | 156 file_service_connection_ = |
| 160 connector_->Connect(file::mojom::kServiceName); | 157 connector_->Connect(file::mojom::kServiceName); |
| 161 connection_state_ = CONNECTION_IN_PROGRESS; | 158 connection_state_ = CONNECTION_IN_PROGRESS; |
| 162 file_service_connection_->AddConnectionCompletedClosure( | 159 file_service_connection_->AddConnectionCompletedClosure( |
| 163 base::Bind(&MojoState::OnUserServiceConnectionComplete, | 160 base::Bind(&MojoState::OnUserServiceConnectionComplete, |
| 164 weak_ptr_factory_.GetWeakPtr())); | 161 weak_ptr_factory_.GetWeakPtr())); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 180 leveldb_service_->OpenInMemory( | 177 leveldb_service_->OpenInMemory( |
| 181 MakeRequest(&database_), base::Bind(&MojoState::OnDatabaseOpened, | 178 MakeRequest(&database_), base::Bind(&MojoState::OnDatabaseOpened, |
| 182 weak_ptr_factory_.GetWeakPtr())); | 179 weak_ptr_factory_.GetWeakPtr())); |
| 183 } | 180 } |
| 184 } | 181 } |
| 185 | 182 |
| 186 if (connection_state_ == CONNECTION_IN_PROGRESS) { | 183 if (connection_state_ == CONNECTION_IN_PROGRESS) { |
| 187 // Queue this OpenLocalStorage call for when we have a level db pointer. | 184 // Queue this OpenLocalStorage call for when we have a level db pointer. |
| 188 on_database_opened_callbacks_.push_back( | 185 on_database_opened_callbacks_.push_back( |
| 189 base::Bind(&MojoState::BindLocalStorage, weak_ptr_factory_.GetWeakPtr(), | 186 base::Bind(&MojoState::BindLocalStorage, weak_ptr_factory_.GetWeakPtr(), |
| 190 origin, base::Passed(&observer), base::Passed(&request))); | 187 origin, base::Passed(&request))); |
| 191 return; | 188 return; |
| 192 } | 189 } |
| 193 | 190 |
| 194 BindLocalStorage(origin, std::move(observer), std::move(request)); | 191 BindLocalStorage(origin, std::move(request)); |
| 195 } | 192 } |
| 196 | 193 |
| 197 void DOMStorageContextWrapper::MojoState::OnDirectoryOpened( | 194 void DOMStorageContextWrapper::MojoState::OnDirectoryOpened( |
| 198 filesystem::mojom::FileError err) { | 195 filesystem::mojom::FileError err) { |
| 199 if (err != filesystem::mojom::FileError::OK) { | 196 if (err != filesystem::mojom::FileError::OK) { |
| 200 // We failed to open the directory; continue with startup so that we create | 197 // We failed to open the directory; continue with startup so that we create |
| 201 // the |level_db_wrappers_|. | 198 // the |level_db_wrappers_|. |
| 202 OnDatabaseOpened(leveldb::mojom::DatabaseError::IO_ERROR); | 199 OnDatabaseOpened(leveldb::mojom::DatabaseError::IO_ERROR); |
| 203 return; | 200 return; |
| 204 } | 201 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 229 // |leveldb_| should be known to either be valid or invalid by now. Run our | 226 // |leveldb_| should be known to either be valid or invalid by now. Run our |
| 230 // delayed bindings. | 227 // delayed bindings. |
| 231 connection_state_ = CONNECTION_FINISHED; | 228 connection_state_ = CONNECTION_FINISHED; |
| 232 for (size_t i = 0; i < on_database_opened_callbacks_.size(); ++i) | 229 for (size_t i = 0; i < on_database_opened_callbacks_.size(); ++i) |
| 233 on_database_opened_callbacks_[i].Run(); | 230 on_database_opened_callbacks_[i].Run(); |
| 234 on_database_opened_callbacks_.clear(); | 231 on_database_opened_callbacks_.clear(); |
| 235 } | 232 } |
| 236 | 233 |
| 237 void DOMStorageContextWrapper::MojoState::BindLocalStorage( | 234 void DOMStorageContextWrapper::MojoState::BindLocalStorage( |
| 238 const url::Origin& origin, | 235 const url::Origin& origin, |
| 239 mojom::LevelDBObserverPtr observer, | |
| 240 mojom::LevelDBWrapperRequest request) { | 236 mojom::LevelDBWrapperRequest request) { |
| 241 // Delay for a moment after a value is set in anticipation | 237 // Delay for a moment after a value is set in anticipation |
| 242 // of other values being set, so changes are batched. | 238 // of other values being set, so changes are batched. |
| 243 const int kCommitDefaultDelaySecs = 5; | 239 const int kCommitDefaultDelaySecs = 5; |
| 244 | 240 |
| 245 // To avoid excessive IO we apply limits to the amount of data being written | 241 // To avoid excessive IO we apply limits to the amount of data being written |
| 246 // and the frequency of writes. | 242 // and the frequency of writes. |
| 247 const int kMaxBytesPerHour = kPerStorageAreaQuota; | 243 const int kMaxBytesPerHour = kPerStorageAreaQuota; |
| 248 const int kMaxCommitsPerHour = 60; | 244 const int kMaxCommitsPerHour = 60; |
| 249 | 245 |
| 250 auto found = level_db_wrappers_.find(origin); | 246 auto found = level_db_wrappers_.find(origin); |
| 251 if (found == level_db_wrappers_.end()) { | 247 if (found == level_db_wrappers_.end()) { |
| 252 level_db_wrappers_[origin] = base::MakeUnique<LevelDBWrapperImpl>( | 248 level_db_wrappers_[origin] = base::MakeUnique<LevelDBWrapperImpl>( |
| 253 database_.get(), origin.Serialize(), | 249 database_.get(), origin.Serialize(), |
| 254 kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance, | 250 kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance, |
| 255 base::TimeDelta::FromSeconds(kCommitDefaultDelaySecs), kMaxBytesPerHour, | 251 base::TimeDelta::FromSeconds(kCommitDefaultDelaySecs), kMaxBytesPerHour, |
| 256 kMaxCommitsPerHour, | 252 kMaxCommitsPerHour, |
| 257 base::Bind(&MojoState::OnLevelDDWrapperHasNoBindings, | 253 base::Bind(&MojoState::OnLevelDDWrapperHasNoBindings, |
| 258 base::Unretained(this), origin)); | 254 base::Unretained(this), origin)); |
| 259 found = level_db_wrappers_.find(origin); | 255 found = level_db_wrappers_.find(origin); |
| 260 } | 256 } |
| 261 | 257 |
| 262 found->second->Bind(std::move(request)); | 258 found->second->Bind(std::move(request)); |
| 263 found->second->AddObserver(std::move(observer)); | |
| 264 } | 259 } |
| 265 | 260 |
| 266 DOMStorageContextWrapper::DOMStorageContextWrapper( | 261 DOMStorageContextWrapper::DOMStorageContextWrapper( |
| 267 service_manager::Connector* connector, | 262 service_manager::Connector* connector, |
| 268 const base::FilePath& profile_path, | 263 const base::FilePath& profile_path, |
| 269 const base::FilePath& local_partition_path, | 264 const base::FilePath& local_partition_path, |
| 270 storage::SpecialStoragePolicy* special_storage_policy) { | 265 storage::SpecialStoragePolicy* special_storage_policy) { |
| 271 base::FilePath storage_dir; | 266 base::FilePath storage_dir; |
| 272 if (!profile_path.empty()) | 267 if (!profile_path.empty()) |
| 273 storage_dir = local_partition_path.AppendASCII(kLocalStorageDirectory); | 268 storage_dir = local_partition_path.AppendASCII(kLocalStorageDirectory); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 | 409 |
| 415 void DOMStorageContextWrapper::Flush() { | 410 void DOMStorageContextWrapper::Flush() { |
| 416 DCHECK(context_.get()); | 411 DCHECK(context_.get()); |
| 417 context_->task_runner()->PostShutdownBlockingTask( | 412 context_->task_runner()->PostShutdownBlockingTask( |
| 418 FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE, | 413 FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE, |
| 419 base::Bind(&DOMStorageContextImpl::Flush, context_)); | 414 base::Bind(&DOMStorageContextImpl::Flush, context_)); |
| 420 } | 415 } |
| 421 | 416 |
| 422 void DOMStorageContextWrapper::OpenLocalStorage( | 417 void DOMStorageContextWrapper::OpenLocalStorage( |
| 423 const url::Origin& origin, | 418 const url::Origin& origin, |
| 424 mojom::LevelDBObserverPtr observer, | |
| 425 mojom::LevelDBWrapperRequest request) { | 419 mojom::LevelDBWrapperRequest request) { |
| 426 mojo_state_->OpenLocalStorage( | 420 mojo_state_->OpenLocalStorage(origin, std::move(request)); |
| 427 origin, std::move(observer), std::move(request)); | |
| 428 } | 421 } |
| 429 | 422 |
| 430 void DOMStorageContextWrapper::OnMemoryPressure( | 423 void DOMStorageContextWrapper::OnMemoryPressure( |
| 431 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { | 424 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { |
| 432 DOMStorageContextImpl::PurgeOption purge_option = | 425 DOMStorageContextImpl::PurgeOption purge_option = |
| 433 DOMStorageContextImpl::PURGE_UNOPENED; | 426 DOMStorageContextImpl::PURGE_UNOPENED; |
| 434 if (memory_pressure_level == | 427 if (memory_pressure_level == |
| 435 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { | 428 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { |
| 436 purge_option = DOMStorageContextImpl::PURGE_AGGRESSIVE; | 429 purge_option = DOMStorageContextImpl::PURGE_AGGRESSIVE; |
| 437 } | 430 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 461 } | 454 } |
| 462 | 455 |
| 463 void DOMStorageContextWrapper::PurgeMemory(DOMStorageContextImpl::PurgeOption | 456 void DOMStorageContextWrapper::PurgeMemory(DOMStorageContextImpl::PurgeOption |
| 464 purge_option) { | 457 purge_option) { |
| 465 context_->task_runner()->PostTask( | 458 context_->task_runner()->PostTask( |
| 466 FROM_HERE, | 459 FROM_HERE, |
| 467 base::Bind(&DOMStorageContextImpl::PurgeMemory, context_, purge_option)); | 460 base::Bind(&DOMStorageContextImpl::PurgeMemory, context_, purge_option)); |
| 468 } | 461 } |
| 469 | 462 |
| 470 } // namespace content | 463 } // namespace content |
| OLD | NEW |