Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: content/browser/dom_storage/local_storage_context_mojo.cc

Issue 2597353002: Add callback to LevelDBWrapperImpl to allow extra operations on commit. (Closed)
Patch Set: Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "content/browser/leveldb_wrapper_impl.h" 10 #include "content/browser/leveldb_wrapper_impl.h"
(...skipping 13 matching lines...) Expand all
24 // 24 //
25 // key: "_" + <url::Origin> 'origin'> + '\x00' + <script controlled key> 25 // key: "_" + <url::Origin> 'origin'> + '\x00' + <script controlled key>
26 // value: <script controlled value> 26 // value: <script controlled value>
27 27
28 namespace { 28 namespace {
29 const char kVersionKey[] = "VERSION"; 29 const char kVersionKey[] = "VERSION";
30 const char kOriginSeparator = '\x00'; 30 const char kOriginSeparator = '\x00';
31 const char kDataPrefix[] = "_"; 31 const char kDataPrefix[] = "_";
32 const int64_t kMinSchemaVersion = 1; 32 const int64_t kMinSchemaVersion = 1;
33 const int64_t kCurrentSchemaVersion = 1; 33 const int64_t kCurrentSchemaVersion = 1;
34
35 void NoOpResult(leveldb::mojom::DatabaseError status) {}
36 } 34 }
37 35
38 LocalStorageContextMojo::LocalStorageContextMojo( 36 LocalStorageContextMojo::LocalStorageContextMojo(
39 service_manager::Connector* connector, 37 service_manager::Connector* connector,
40 const base::FilePath& subdirectory) 38 const base::FilePath& subdirectory)
41 : connector_(connector), 39 : connector_(connector),
42 subdirectory_(subdirectory), 40 subdirectory_(subdirectory),
43 weak_ptr_factory_(this) {} 41 weak_ptr_factory_(this) {}
44 42
45 LocalStorageContextMojo::~LocalStorageContextMojo() {} 43 LocalStorageContextMojo::~LocalStorageContextMojo() {}
(...skipping 26 matching lines...) Expand all
72 file_service_connection_->GetInterface(&leveldb_service_); 70 file_service_connection_->GetInterface(&leveldb_service_);
73 leveldb_service_->OpenInMemory( 71 leveldb_service_->OpenInMemory(
74 MakeRequest(&database_), 72 MakeRequest(&database_),
75 base::Bind(&LocalStorageContextMojo::OnDatabaseOpened, 73 base::Bind(&LocalStorageContextMojo::OnDatabaseOpened,
76 weak_ptr_factory_.GetWeakPtr())); 74 weak_ptr_factory_.GetWeakPtr()));
77 } 75 }
78 } 76 }
79 77
80 if (connection_state_ == CONNECTION_IN_PROGRESS) { 78 if (connection_state_ == CONNECTION_IN_PROGRESS) {
81 // Queue this OpenLocalStorage call for when we have a level db pointer. 79 // Queue this OpenLocalStorage call for when we have a level db pointer.
82 on_database_opened_callbacks_.push_back(base::Bind( 80 on_database_opened_callbacks_.push_back(base::BindOnce(
83 &LocalStorageContextMojo::BindLocalStorage, 81 &LocalStorageContextMojo::BindLocalStorage,
84 weak_ptr_factory_.GetWeakPtr(), origin, base::Passed(&request))); 82 weak_ptr_factory_.GetWeakPtr(), origin, std::move(request)));
85 return; 83 return;
86 } 84 }
87 85
88 BindLocalStorage(origin, std::move(request)); 86 BindLocalStorage(origin, std::move(request));
89 } 87 }
90 88
91 void LocalStorageContextMojo::SetDatabaseForTesting( 89 void LocalStorageContextMojo::SetDatabaseForTesting(
92 leveldb::mojom::LevelDBDatabasePtr database) { 90 leveldb::mojom::LevelDBDatabasePtr database) {
93 DCHECK_EQ(connection_state_, NO_CONNECTION); 91 DCHECK_EQ(connection_state_, NO_CONNECTION);
94 connection_state_ = CONNECTION_IN_PROGRESS; 92 connection_state_ = CONNECTION_IN_PROGRESS;
95 database_ = std::move(database); 93 database_ = std::move(database);
96 OnDatabaseOpened(leveldb::mojom::DatabaseError::OK); 94 OnDatabaseOpened(leveldb::mojom::DatabaseError::OK);
97 } 95 }
98 96
99 void LocalStorageContextMojo::OnLevelDBWrapperHasNoBindings( 97 void LocalStorageContextMojo::OnLevelDBWrapperHasNoBindings(
100 const url::Origin& origin) { 98 const url::Origin& origin) {
101 DCHECK(level_db_wrappers_.find(origin) != level_db_wrappers_.end()); 99 DCHECK(level_db_wrappers_.find(origin) != level_db_wrappers_.end());
102 level_db_wrappers_.erase(origin); 100 level_db_wrappers_.erase(origin);
103 } 101 }
104 102
103 std::vector<leveldb::mojom::BatchedOperationPtr>
104 LocalStorageContextMojo::OnLevelDBWrapperPrepareToCommit() {
105 std::vector<leveldb::mojom::BatchedOperationPtr> operations;
106
107 // Write schema version if not already done so before.
108 if (!database_initialized_) {
109 leveldb::mojom::BatchedOperationPtr item =
110 leveldb::mojom::BatchedOperation::New();
111 item->key = leveldb::StdStringToUint8Vector(kVersionKey);
112 item->value = leveldb::StdStringToUint8Vector(
113 base::Int64ToString(kCurrentSchemaVersion));
114 operations.push_back(std::move(item));
115 database_initialized_ = true;
116 }
117
118 return operations;
119 }
120
105 void LocalStorageContextMojo::OnUserServiceConnectionComplete() { 121 void LocalStorageContextMojo::OnUserServiceConnectionComplete() {
106 CHECK_EQ(service_manager::mojom::ConnectResult::SUCCEEDED, 122 CHECK_EQ(service_manager::mojom::ConnectResult::SUCCEEDED,
107 file_service_connection_->GetResult()); 123 file_service_connection_->GetResult());
108 } 124 }
109 125
110 void LocalStorageContextMojo::OnUserServiceConnectionError() { 126 void LocalStorageContextMojo::OnUserServiceConnectionError() {
111 CHECK(false); 127 CHECK(false);
112 } 128 }
113 129
114 // Part of our asynchronous directory opening called from OpenLocalStorage(). 130 // Part of our asynchronous directory opening called from OpenLocalStorage().
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 } 170 }
155 171
156 OnGotDatabaseVersion(leveldb::mojom::DatabaseError::IO_ERROR, 172 OnGotDatabaseVersion(leveldb::mojom::DatabaseError::IO_ERROR,
157 std::vector<uint8_t>()); 173 std::vector<uint8_t>());
158 } 174 }
159 175
160 void LocalStorageContextMojo::OnGotDatabaseVersion( 176 void LocalStorageContextMojo::OnGotDatabaseVersion(
161 leveldb::mojom::DatabaseError status, 177 leveldb::mojom::DatabaseError status,
162 const std::vector<uint8_t>& value) { 178 const std::vector<uint8_t>& value) {
163 if (status == leveldb::mojom::DatabaseError::NOT_FOUND) { 179 if (status == leveldb::mojom::DatabaseError::NOT_FOUND) {
164 // New database, write current version and continue. 180 // New database, nothing more to do. Current version will get written
165 // TODO(mek): Delay writing version until first actual data gets committed. 181 // when first data is committed.
166 database_->Put(leveldb::StdStringToUint8Vector(kVersionKey),
167 leveldb::StdStringToUint8Vector(
168 base::Int64ToString(kCurrentSchemaVersion)),
169 base::Bind(&NoOpResult));
170 // new database
171 } else if (status == leveldb::mojom::DatabaseError::OK) { 182 } else if (status == leveldb::mojom::DatabaseError::OK) {
172 // Existing database, check if version number matches current schema 183 // Existing database, check if version number matches current schema
173 // version. 184 // version.
174 int64_t db_version; 185 int64_t db_version;
175 if (!base::StringToInt64(leveldb::Uint8VectorToStdString(value), 186 if (!base::StringToInt64(leveldb::Uint8VectorToStdString(value),
176 &db_version) || 187 &db_version) ||
177 db_version < kMinSchemaVersion || db_version > kCurrentSchemaVersion) { 188 db_version < kMinSchemaVersion || db_version > kCurrentSchemaVersion) {
178 // TODO(mek): delete and recreate database, rather than failing outright. 189 // TODO(mek): delete and recreate database, rather than failing outright.
179 database_ = nullptr; 190 database_ = nullptr;
180 } 191 }
192
193 database_initialized_ = true;
181 } else { 194 } else {
182 // Other read error. Possibly database corruption. 195 // Other read error. Possibly database corruption.
183 // TODO(mek): delete and recreate database, rather than failing outright. 196 // TODO(mek): delete and recreate database, rather than failing outright.
184 database_ = nullptr; 197 database_ = nullptr;
185 } 198 }
186 199
187 // |database_| should be known to either be valid or invalid by now. Run our 200 // |database_| should be known to either be valid or invalid by now. Run our
188 // delayed bindings. 201 // delayed bindings.
189 connection_state_ = CONNECTION_FINISHED; 202 connection_state_ = CONNECTION_FINISHED;
190 for (size_t i = 0; i < on_database_opened_callbacks_.size(); ++i) 203 for (size_t i = 0; i < on_database_opened_callbacks_.size(); ++i)
191 on_database_opened_callbacks_[i].Run(); 204 std::move(on_database_opened_callbacks_[i]).Run();
192 on_database_opened_callbacks_.clear(); 205 on_database_opened_callbacks_.clear();
193 } 206 }
194 207
195 // The (possibly delayed) implementation of OpenLocalStorage(). Can be called 208 // The (possibly delayed) implementation of OpenLocalStorage(). Can be called
196 // directly from that function, or through |on_database_open_callbacks_|. 209 // directly from that function, or through |on_database_open_callbacks_|.
197 void LocalStorageContextMojo::BindLocalStorage( 210 void LocalStorageContextMojo::BindLocalStorage(
198 const url::Origin& origin, 211 const url::Origin& origin,
199 mojom::LevelDBWrapperRequest request) { 212 mojom::LevelDBWrapperRequest request) {
200 // Delay for a moment after a value is set in anticipation 213 // Delay for a moment after a value is set in anticipation
201 // of other values being set, so changes are batched. 214 // of other values being set, so changes are batched.
202 const int kCommitDefaultDelaySecs = 5; 215 const int kCommitDefaultDelaySecs = 5;
203 216
204 // To avoid excessive IO we apply limits to the amount of data being written 217 // To avoid excessive IO we apply limits to the amount of data being written
205 // and the frequency of writes. 218 // and the frequency of writes.
206 const int kMaxBytesPerHour = kPerStorageAreaQuota; 219 const int kMaxBytesPerHour = kPerStorageAreaQuota;
207 const int kMaxCommitsPerHour = 60; 220 const int kMaxCommitsPerHour = 60;
208 221
209 auto found = level_db_wrappers_.find(origin); 222 auto found = level_db_wrappers_.find(origin);
210 if (found == level_db_wrappers_.end()) { 223 if (found == level_db_wrappers_.end()) {
211 level_db_wrappers_[origin] = base::MakeUnique<LevelDBWrapperImpl>( 224 level_db_wrappers_[origin] = base::MakeUnique<LevelDBWrapperImpl>(
212 database_.get(), kDataPrefix + origin.Serialize() + kOriginSeparator, 225 database_.get(), kDataPrefix + origin.Serialize() + kOriginSeparator,
213 kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance, 226 kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
214 base::TimeDelta::FromSeconds(kCommitDefaultDelaySecs), kMaxBytesPerHour, 227 base::TimeDelta::FromSeconds(kCommitDefaultDelaySecs), kMaxBytesPerHour,
215 kMaxCommitsPerHour, 228 kMaxCommitsPerHour,
216 base::Bind(&LocalStorageContextMojo::OnLevelDBWrapperHasNoBindings, 229 base::Bind(&LocalStorageContextMojo::OnLevelDBWrapperHasNoBindings,
217 base::Unretained(this), origin)); 230 base::Unretained(this), origin),
231 base::Bind(&LocalStorageContextMojo::OnLevelDBWrapperPrepareToCommit,
232 base::Unretained(this)));
218 found = level_db_wrappers_.find(origin); 233 found = level_db_wrappers_.find(origin);
219 } 234 }
220 235
221 found->second->Bind(std::move(request)); 236 found->second->Bind(std::move(request));
222 } 237 }
223 238
224 } // namespace content 239 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698