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 |