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

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

Issue 22297005: Move webkit/{browser,common}/dom_storage into content/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "webkit/browser/dom_storage/dom_storage_area.h" 5 #include "content/browser/dom_storage/dom_storage_area.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "content/browser/dom_storage/dom_storage_namespace.h"
14 #include "content/browser/dom_storage/dom_storage_task_runner.h"
15 #include "content/browser/dom_storage/local_storage_database_adapter.h"
16 #include "content/browser/dom_storage/session_storage_database.h"
17 #include "content/browser/dom_storage/session_storage_database_adapter.h"
18 #include "content/common/dom_storage/dom_storage_map.h"
19 #include "content/common/dom_storage/dom_storage_types.h"
13 #include "webkit/browser/database/database_util.h" 20 #include "webkit/browser/database/database_util.h"
14 #include "webkit/browser/dom_storage/dom_storage_namespace.h"
15 #include "webkit/browser/dom_storage/dom_storage_task_runner.h"
16 #include "webkit/browser/dom_storage/local_storage_database_adapter.h"
17 #include "webkit/browser/dom_storage/session_storage_database.h"
18 #include "webkit/browser/dom_storage/session_storage_database_adapter.h"
19 #include "webkit/common/database/database_identifier.h" 21 #include "webkit/common/database/database_identifier.h"
20 #include "webkit/common/dom_storage/dom_storage_map.h"
21 #include "webkit/common/dom_storage/dom_storage_types.h"
22 #include "webkit/common/fileapi/file_system_util.h" 22 #include "webkit/common/fileapi/file_system_util.h"
23 23
24 using webkit_database::DatabaseUtil; 24 using webkit_database::DatabaseUtil;
25 25
26 namespace dom_storage { 26 namespace content {
27 27
28 static const int kCommitTimerSeconds = 1; 28 static const int kCommitTimerSeconds = 1;
29 29
30 DomStorageArea::CommitBatch::CommitBatch() 30 DOMStorageArea::CommitBatch::CommitBatch()
31 : clear_all_first(false) { 31 : clear_all_first(false) {
32 } 32 }
33 DomStorageArea::CommitBatch::~CommitBatch() {} 33 DOMStorageArea::CommitBatch::~CommitBatch() {}
34 34
35 35
36 // static 36 // static
37 const base::FilePath::CharType DomStorageArea::kDatabaseFileExtension[] = 37 const base::FilePath::CharType DOMStorageArea::kDatabaseFileExtension[] =
38 FILE_PATH_LITERAL(".localstorage"); 38 FILE_PATH_LITERAL(".localstorage");
39 39
40 // static 40 // static
41 base::FilePath DomStorageArea::DatabaseFileNameFromOrigin(const GURL& origin) { 41 base::FilePath DOMStorageArea::DatabaseFileNameFromOrigin(const GURL& origin) {
42 std::string filename = webkit_database::GetIdentifierFromOrigin(origin); 42 std::string filename = webkit_database::GetIdentifierFromOrigin(origin);
43 // There is no base::FilePath.AppendExtension() method, so start with just the 43 // There is no base::FilePath.AppendExtension() method, so start with just the
44 // extension as the filename, and then InsertBeforeExtension the desired 44 // extension as the filename, and then InsertBeforeExtension the desired
45 // name. 45 // name.
46 return base::FilePath().Append(kDatabaseFileExtension). 46 return base::FilePath().Append(kDatabaseFileExtension).
47 InsertBeforeExtensionASCII(filename); 47 InsertBeforeExtensionASCII(filename);
48 } 48 }
49 49
50 // static 50 // static
51 GURL DomStorageArea::OriginFromDatabaseFileName(const base::FilePath& name) { 51 GURL DOMStorageArea::OriginFromDatabaseFileName(const base::FilePath& name) {
52 DCHECK(name.MatchesExtension(kDatabaseFileExtension)); 52 DCHECK(name.MatchesExtension(kDatabaseFileExtension));
53 std::string origin_id = 53 std::string origin_id =
54 name.BaseName().RemoveExtension().MaybeAsASCII(); 54 name.BaseName().RemoveExtension().MaybeAsASCII();
55 return webkit_database::GetOriginFromIdentifier(origin_id); 55 return webkit_database::GetOriginFromIdentifier(origin_id);
56 } 56 }
57 57
58 DomStorageArea::DomStorageArea(const GURL& origin, const base::FilePath& directo ry, 58 DOMStorageArea::DOMStorageArea(
59 DomStorageTaskRunner* task_runner) 59 const GURL& origin, const base::FilePath& directory,
60 DOMStorageTaskRunner* task_runner)
60 : namespace_id_(kLocalStorageNamespaceId), origin_(origin), 61 : namespace_id_(kLocalStorageNamespaceId), origin_(origin),
61 directory_(directory), 62 directory_(directory),
62 task_runner_(task_runner), 63 task_runner_(task_runner),
63 map_(new DomStorageMap(kPerAreaQuota + kPerAreaOverQuotaAllowance)), 64 map_(new DOMStorageMap(kPerStorageAreaQuota +
65 kPerStorageAreaOverQuotaAllowance)),
64 is_initial_import_done_(true), 66 is_initial_import_done_(true),
65 is_shutdown_(false), 67 is_shutdown_(false),
66 commit_batches_in_flight_(0) { 68 commit_batches_in_flight_(0) {
67 if (!directory.empty()) { 69 if (!directory.empty()) {
68 base::FilePath path = directory.Append(DatabaseFileNameFromOrigin(origin_)); 70 base::FilePath path = directory.Append(DatabaseFileNameFromOrigin(origin_));
69 backing_.reset(new LocalStorageDatabaseAdapter(path)); 71 backing_.reset(new LocalStorageDatabaseAdapter(path));
70 is_initial_import_done_ = false; 72 is_initial_import_done_ = false;
71 } 73 }
72 } 74 }
73 75
74 DomStorageArea::DomStorageArea( 76 DOMStorageArea::DOMStorageArea(
75 int64 namespace_id, 77 int64 namespace_id,
76 const std::string& persistent_namespace_id, 78 const std::string& persistent_namespace_id,
77 const GURL& origin, 79 const GURL& origin,
78 SessionStorageDatabase* session_storage_backing, 80 SessionStorageDatabase* session_storage_backing,
79 DomStorageTaskRunner* task_runner) 81 DOMStorageTaskRunner* task_runner)
80 : namespace_id_(namespace_id), 82 : namespace_id_(namespace_id),
81 persistent_namespace_id_(persistent_namespace_id), 83 persistent_namespace_id_(persistent_namespace_id),
82 origin_(origin), 84 origin_(origin),
83 task_runner_(task_runner), 85 task_runner_(task_runner),
84 map_(new DomStorageMap(kPerAreaQuota + kPerAreaOverQuotaAllowance)), 86 map_(new DOMStorageMap(kPerStorageAreaQuota +
87 kPerStorageAreaOverQuotaAllowance)),
85 session_storage_backing_(session_storage_backing), 88 session_storage_backing_(session_storage_backing),
86 is_initial_import_done_(true), 89 is_initial_import_done_(true),
87 is_shutdown_(false), 90 is_shutdown_(false),
88 commit_batches_in_flight_(0) { 91 commit_batches_in_flight_(0) {
89 DCHECK(namespace_id != kLocalStorageNamespaceId); 92 DCHECK(namespace_id != kLocalStorageNamespaceId);
90 if (session_storage_backing) { 93 if (session_storage_backing) {
91 backing_.reset(new SessionStorageDatabaseAdapter( 94 backing_.reset(new SessionStorageDatabaseAdapter(
92 session_storage_backing, persistent_namespace_id, origin)); 95 session_storage_backing, persistent_namespace_id, origin));
93 is_initial_import_done_ = false; 96 is_initial_import_done_ = false;
94 } 97 }
95 } 98 }
96 99
97 DomStorageArea::~DomStorageArea() { 100 DOMStorageArea::~DOMStorageArea() {
98 } 101 }
99 102
100 void DomStorageArea::ExtractValues(ValuesMap* map) { 103 void DOMStorageArea::ExtractValues(DOMStorageValuesMap* map) {
101 if (is_shutdown_) 104 if (is_shutdown_)
102 return; 105 return;
103 InitialImportIfNeeded(); 106 InitialImportIfNeeded();
104 map_->ExtractValues(map); 107 map_->ExtractValues(map);
105 } 108 }
106 109
107 unsigned DomStorageArea::Length() { 110 unsigned DOMStorageArea::Length() {
108 if (is_shutdown_) 111 if (is_shutdown_)
109 return 0; 112 return 0;
110 InitialImportIfNeeded(); 113 InitialImportIfNeeded();
111 return map_->Length(); 114 return map_->Length();
112 } 115 }
113 116
114 base::NullableString16 DomStorageArea::Key(unsigned index) { 117 base::NullableString16 DOMStorageArea::Key(unsigned index) {
115 if (is_shutdown_) 118 if (is_shutdown_)
116 return base::NullableString16(); 119 return base::NullableString16();
117 InitialImportIfNeeded(); 120 InitialImportIfNeeded();
118 return map_->Key(index); 121 return map_->Key(index);
119 } 122 }
120 123
121 base::NullableString16 DomStorageArea::GetItem(const base::string16& key) { 124 base::NullableString16 DOMStorageArea::GetItem(const base::string16& key) {
122 if (is_shutdown_) 125 if (is_shutdown_)
123 return base::NullableString16(); 126 return base::NullableString16();
124 InitialImportIfNeeded(); 127 InitialImportIfNeeded();
125 return map_->GetItem(key); 128 return map_->GetItem(key);
126 } 129 }
127 130
128 bool DomStorageArea::SetItem(const base::string16& key, 131 bool DOMStorageArea::SetItem(const base::string16& key,
129 const base::string16& value, 132 const base::string16& value,
130 base::NullableString16* old_value) { 133 base::NullableString16* old_value) {
131 if (is_shutdown_) 134 if (is_shutdown_)
132 return false; 135 return false;
133 InitialImportIfNeeded(); 136 InitialImportIfNeeded();
134 if (!map_->HasOneRef()) 137 if (!map_->HasOneRef())
135 map_ = map_->DeepCopy(); 138 map_ = map_->DeepCopy();
136 bool success = map_->SetItem(key, value, old_value); 139 bool success = map_->SetItem(key, value, old_value);
137 if (success && backing_) { 140 if (success && backing_) {
138 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); 141 CommitBatch* commit_batch = CreateCommitBatchIfNeeded();
139 commit_batch->changed_values[key] = base::NullableString16(value, false); 142 commit_batch->changed_values[key] = base::NullableString16(value, false);
140 } 143 }
141 return success; 144 return success;
142 } 145 }
143 146
144 bool DomStorageArea::RemoveItem(const base::string16& key, 147 bool DOMStorageArea::RemoveItem(const base::string16& key,
145 base::string16* old_value) { 148 base::string16* old_value) {
146 if (is_shutdown_) 149 if (is_shutdown_)
147 return false; 150 return false;
148 InitialImportIfNeeded(); 151 InitialImportIfNeeded();
149 if (!map_->HasOneRef()) 152 if (!map_->HasOneRef())
150 map_ = map_->DeepCopy(); 153 map_ = map_->DeepCopy();
151 bool success = map_->RemoveItem(key, old_value); 154 bool success = map_->RemoveItem(key, old_value);
152 if (success && backing_) { 155 if (success && backing_) {
153 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); 156 CommitBatch* commit_batch = CreateCommitBatchIfNeeded();
154 commit_batch->changed_values[key] = base::NullableString16(); 157 commit_batch->changed_values[key] = base::NullableString16();
155 } 158 }
156 return success; 159 return success;
157 } 160 }
158 161
159 bool DomStorageArea::Clear() { 162 bool DOMStorageArea::Clear() {
160 if (is_shutdown_) 163 if (is_shutdown_)
161 return false; 164 return false;
162 InitialImportIfNeeded(); 165 InitialImportIfNeeded();
163 if (map_->Length() == 0) 166 if (map_->Length() == 0)
164 return false; 167 return false;
165 168
166 map_ = new DomStorageMap(kPerAreaQuota + kPerAreaOverQuotaAllowance); 169 map_ = new DOMStorageMap(kPerStorageAreaQuota +
170 kPerStorageAreaOverQuotaAllowance);
167 171
168 if (backing_) { 172 if (backing_) {
169 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); 173 CommitBatch* commit_batch = CreateCommitBatchIfNeeded();
170 commit_batch->clear_all_first = true; 174 commit_batch->clear_all_first = true;
171 commit_batch->changed_values.clear(); 175 commit_batch->changed_values.clear();
172 } 176 }
173 177
174 return true; 178 return true;
175 } 179 }
176 180
177 void DomStorageArea::FastClear() { 181 void DOMStorageArea::FastClear() {
178 // TODO(marja): Unify clearing localStorage and sessionStorage. The problem is 182 // TODO(marja): Unify clearing localStorage and sessionStorage. The problem is
179 // to make the following 3 to work together: 1) FastClear, 2) PurgeMemory and 183 // to make the following 3 to work together: 1) FastClear, 2) PurgeMemory and
180 // 3) not creating events when clearing an empty area. 184 // 3) not creating events when clearing an empty area.
181 if (is_shutdown_) 185 if (is_shutdown_)
182 return; 186 return;
183 187
184 map_ = new DomStorageMap(kPerAreaQuota + kPerAreaOverQuotaAllowance); 188 map_ = new DOMStorageMap(kPerStorageAreaQuota +
189 kPerStorageAreaOverQuotaAllowance);
185 // This ensures no import will happen while we're waiting to clear the data 190 // This ensures no import will happen while we're waiting to clear the data
186 // from the database. This mechanism fails if PurgeMemory is called. 191 // from the database. This mechanism fails if PurgeMemory is called.
187 is_initial_import_done_ = true; 192 is_initial_import_done_ = true;
188 193
189 if (backing_) { 194 if (backing_) {
190 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); 195 CommitBatch* commit_batch = CreateCommitBatchIfNeeded();
191 commit_batch->clear_all_first = true; 196 commit_batch->clear_all_first = true;
192 commit_batch->changed_values.clear(); 197 commit_batch->changed_values.clear();
193 } 198 }
194 } 199 }
195 200
196 DomStorageArea* DomStorageArea::ShallowCopy( 201 DOMStorageArea* DOMStorageArea::ShallowCopy(
197 int64 destination_namespace_id, 202 int64 destination_namespace_id,
198 const std::string& destination_persistent_namespace_id) { 203 const std::string& destination_persistent_namespace_id) {
199 DCHECK_NE(kLocalStorageNamespaceId, namespace_id_); 204 DCHECK_NE(kLocalStorageNamespaceId, namespace_id_);
200 DCHECK_NE(kLocalStorageNamespaceId, destination_namespace_id); 205 DCHECK_NE(kLocalStorageNamespaceId, destination_namespace_id);
201 206
202 DomStorageArea* copy = new DomStorageArea( 207 DOMStorageArea* copy = new DOMStorageArea(
203 destination_namespace_id, destination_persistent_namespace_id, origin_, 208 destination_namespace_id, destination_persistent_namespace_id, origin_,
204 session_storage_backing_.get(), task_runner_.get()); 209 session_storage_backing_.get(), task_runner_.get());
205 copy->map_ = map_; 210 copy->map_ = map_;
206 copy->is_shutdown_ = is_shutdown_; 211 copy->is_shutdown_ = is_shutdown_;
207 copy->is_initial_import_done_ = true; 212 copy->is_initial_import_done_ = true;
208 213
209 // All the uncommitted changes to this area need to happen before the actual 214 // All the uncommitted changes to this area need to happen before the actual
210 // shallow copy is made (scheduled by the upper layer). Another OnCommitTimer 215 // shallow copy is made (scheduled by the upper layer). Another OnCommitTimer
211 // call might be in the event queue at this point, but it's handled gracefully 216 // call might be in the event queue at this point, but it's handled gracefully
212 // when it fires. 217 // when it fires.
213 if (commit_batch_) 218 if (commit_batch_)
214 OnCommitTimer(); 219 OnCommitTimer();
215 return copy; 220 return copy;
216 } 221 }
217 222
218 bool DomStorageArea::HasUncommittedChanges() const { 223 bool DOMStorageArea::HasUncommittedChanges() const {
219 DCHECK(!is_shutdown_); 224 DCHECK(!is_shutdown_);
220 return commit_batch_.get() || commit_batches_in_flight_; 225 return commit_batch_.get() || commit_batches_in_flight_;
221 } 226 }
222 227
223 void DomStorageArea::DeleteOrigin() { 228 void DOMStorageArea::DeleteOrigin() {
224 DCHECK(!is_shutdown_); 229 DCHECK(!is_shutdown_);
225 // This function shouldn't be called for sessionStorage. 230 // This function shouldn't be called for sessionStorage.
226 DCHECK(!session_storage_backing_.get()); 231 DCHECK(!session_storage_backing_.get());
227 if (HasUncommittedChanges()) { 232 if (HasUncommittedChanges()) {
228 // TODO(michaeln): This logically deletes the data immediately, 233 // TODO(michaeln): This logically deletes the data immediately,
229 // and in a matter of a second, deletes the rows from the backing 234 // and in a matter of a second, deletes the rows from the backing
230 // database file, but the file itself will linger until shutdown 235 // database file, but the file itself will linger until shutdown
231 // or purge time. Ideally, this should delete the file more 236 // or purge time. Ideally, this should delete the file more
232 // quickly. 237 // quickly.
233 Clear(); 238 Clear();
234 return; 239 return;
235 } 240 }
236 map_ = new DomStorageMap(kPerAreaQuota + kPerAreaOverQuotaAllowance); 241 map_ = new DOMStorageMap(kPerStorageAreaQuota +
242 kPerStorageAreaOverQuotaAllowance);
237 if (backing_) { 243 if (backing_) {
238 is_initial_import_done_ = false; 244 is_initial_import_done_ = false;
239 backing_->Reset(); 245 backing_->Reset();
240 backing_->DeleteFiles(); 246 backing_->DeleteFiles();
241 } 247 }
242 } 248 }
243 249
244 void DomStorageArea::PurgeMemory() { 250 void DOMStorageArea::PurgeMemory() {
245 DCHECK(!is_shutdown_); 251 DCHECK(!is_shutdown_);
246 // Purging sessionStorage is not supported; it won't work with FastClear. 252 // Purging sessionStorage is not supported; it won't work with FastClear.
247 DCHECK(!session_storage_backing_.get()); 253 DCHECK(!session_storage_backing_.get());
248 if (!is_initial_import_done_ || // We're not using any memory. 254 if (!is_initial_import_done_ || // We're not using any memory.
249 !backing_.get() || // We can't purge anything. 255 !backing_.get() || // We can't purge anything.
250 HasUncommittedChanges()) // We leave things alone with changes pending. 256 HasUncommittedChanges()) // We leave things alone with changes pending.
251 return; 257 return;
252 258
253 // Drop the in memory cache, we'll reload when needed. 259 // Drop the in memory cache, we'll reload when needed.
254 is_initial_import_done_ = false; 260 is_initial_import_done_ = false;
255 map_ = new DomStorageMap(kPerAreaQuota + kPerAreaOverQuotaAllowance); 261 map_ = new DOMStorageMap(kPerStorageAreaQuota +
262 kPerStorageAreaOverQuotaAllowance);
256 263
257 // Recreate the database object, this frees up the open sqlite connection 264 // Recreate the database object, this frees up the open sqlite connection
258 // and its page cache. 265 // and its page cache.
259 backing_->Reset(); 266 backing_->Reset();
260 } 267 }
261 268
262 void DomStorageArea::Shutdown() { 269 void DOMStorageArea::Shutdown() {
263 DCHECK(!is_shutdown_); 270 DCHECK(!is_shutdown_);
264 is_shutdown_ = true; 271 is_shutdown_ = true;
265 map_ = NULL; 272 map_ = NULL;
266 if (!backing_) 273 if (!backing_)
267 return; 274 return;
268 275
269 bool success = task_runner_->PostShutdownBlockingTask( 276 bool success = task_runner_->PostShutdownBlockingTask(
270 FROM_HERE, 277 FROM_HERE,
271 DomStorageTaskRunner::COMMIT_SEQUENCE, 278 DOMStorageTaskRunner::COMMIT_SEQUENCE,
272 base::Bind(&DomStorageArea::ShutdownInCommitSequence, this)); 279 base::Bind(&DOMStorageArea::ShutdownInCommitSequence, this));
273 DCHECK(success); 280 DCHECK(success);
274 } 281 }
275 282
276 void DomStorageArea::InitialImportIfNeeded() { 283 void DOMStorageArea::InitialImportIfNeeded() {
277 if (is_initial_import_done_) 284 if (is_initial_import_done_)
278 return; 285 return;
279 286
280 DCHECK(backing_.get()); 287 DCHECK(backing_.get());
281 288
282 base::TimeTicks before = base::TimeTicks::Now(); 289 base::TimeTicks before = base::TimeTicks::Now();
283 ValuesMap initial_values; 290 DOMStorageValuesMap initial_values;
284 backing_->ReadAllValues(&initial_values); 291 backing_->ReadAllValues(&initial_values);
285 map_->SwapValues(&initial_values); 292 map_->SwapValues(&initial_values);
286 is_initial_import_done_ = true; 293 is_initial_import_done_ = true;
287 base::TimeDelta time_to_import = base::TimeTicks::Now() - before; 294 base::TimeDelta time_to_import = base::TimeTicks::Now() - before;
288 UMA_HISTOGRAM_TIMES("LocalStorage.BrowserTimeToPrimeLocalStorage", 295 UMA_HISTOGRAM_TIMES("LocalStorage.BrowserTimeToPrimeLocalStorage",
289 time_to_import); 296 time_to_import);
290 297
291 size_t local_storage_size_kb = map_->bytes_used() / 1024; 298 size_t local_storage_size_kb = map_->bytes_used() / 1024;
292 // Track localStorage size, from 0-6MB. Note that the maximum size should be 299 // Track localStorage size, from 0-6MB. Note that the maximum size should be
293 // 5MB, but we add some slop since we want to make sure the max size is always 300 // 5MB, but we add some slop since we want to make sure the max size is always
294 // above what we see in practice, since histograms can't change. 301 // above what we see in practice, since histograms can't change.
295 UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageSizeInKB", 302 UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageSizeInKB",
296 local_storage_size_kb, 303 local_storage_size_kb,
297 0, 6 * 1024, 50); 304 0, 6 * 1024, 50);
298 if (local_storage_size_kb < 100) { 305 if (local_storage_size_kb < 100) {
299 UMA_HISTOGRAM_TIMES( 306 UMA_HISTOGRAM_TIMES(
300 "LocalStorage.BrowserTimeToPrimeLocalStorageUnder100KB", 307 "LocalStorage.BrowserTimeToPrimeLocalStorageUnder100KB",
301 time_to_import); 308 time_to_import);
302 } else if (local_storage_size_kb < 1000) { 309 } else if (local_storage_size_kb < 1000) {
303 UMA_HISTOGRAM_TIMES( 310 UMA_HISTOGRAM_TIMES(
304 "LocalStorage.BrowserTimeToPrimeLocalStorage100KBTo1MB", 311 "LocalStorage.BrowserTimeToPrimeLocalStorage100KBTo1MB",
305 time_to_import); 312 time_to_import);
306 } else { 313 } else {
307 UMA_HISTOGRAM_TIMES( 314 UMA_HISTOGRAM_TIMES(
308 "LocalStorage.BrowserTimeToPrimeLocalStorage1MBTo5MB", 315 "LocalStorage.BrowserTimeToPrimeLocalStorage1MBTo5MB",
309 time_to_import); 316 time_to_import);
310 } 317 }
311 } 318 }
312 319
313 DomStorageArea::CommitBatch* DomStorageArea::CreateCommitBatchIfNeeded() { 320 DOMStorageArea::CommitBatch* DOMStorageArea::CreateCommitBatchIfNeeded() {
314 DCHECK(!is_shutdown_); 321 DCHECK(!is_shutdown_);
315 if (!commit_batch_) { 322 if (!commit_batch_) {
316 commit_batch_.reset(new CommitBatch()); 323 commit_batch_.reset(new CommitBatch());
317 324
318 // Start a timer to commit any changes that accrue in the batch, but only if 325 // Start a timer to commit any changes that accrue in the batch, but only if
319 // no commits are currently in flight. In that case the timer will be 326 // no commits are currently in flight. In that case the timer will be
320 // started after the commits have happened. 327 // started after the commits have happened.
321 if (!commit_batches_in_flight_) { 328 if (!commit_batches_in_flight_) {
322 task_runner_->PostDelayedTask( 329 task_runner_->PostDelayedTask(
323 FROM_HERE, 330 FROM_HERE,
324 base::Bind(&DomStorageArea::OnCommitTimer, this), 331 base::Bind(&DOMStorageArea::OnCommitTimer, this),
325 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); 332 base::TimeDelta::FromSeconds(kCommitTimerSeconds));
326 } 333 }
327 } 334 }
328 return commit_batch_.get(); 335 return commit_batch_.get();
329 } 336 }
330 337
331 void DomStorageArea::OnCommitTimer() { 338 void DOMStorageArea::OnCommitTimer() {
332 if (is_shutdown_) 339 if (is_shutdown_)
333 return; 340 return;
334 341
335 DCHECK(backing_.get()); 342 DCHECK(backing_.get());
336 343
337 // It's possible that there is nothing to commit, since a shallow copy occured 344 // It's possible that there is nothing to commit, since a shallow copy occured
338 // before the timer fired. 345 // before the timer fired.
339 if (!commit_batch_) 346 if (!commit_batch_)
340 return; 347 return;
341 348
342 // This method executes on the primary sequence, we schedule 349 // This method executes on the primary sequence, we schedule
343 // a task for immediate execution on the commit sequence. 350 // a task for immediate execution on the commit sequence.
344 DCHECK(task_runner_->IsRunningOnPrimarySequence()); 351 DCHECK(task_runner_->IsRunningOnPrimarySequence());
345 bool success = task_runner_->PostShutdownBlockingTask( 352 bool success = task_runner_->PostShutdownBlockingTask(
346 FROM_HERE, 353 FROM_HERE,
347 DomStorageTaskRunner::COMMIT_SEQUENCE, 354 DOMStorageTaskRunner::COMMIT_SEQUENCE,
348 base::Bind(&DomStorageArea::CommitChanges, this, 355 base::Bind(&DOMStorageArea::CommitChanges, this,
349 base::Owned(commit_batch_.release()))); 356 base::Owned(commit_batch_.release())));
350 ++commit_batches_in_flight_; 357 ++commit_batches_in_flight_;
351 DCHECK(success); 358 DCHECK(success);
352 } 359 }
353 360
354 void DomStorageArea::CommitChanges(const CommitBatch* commit_batch) { 361 void DOMStorageArea::CommitChanges(const CommitBatch* commit_batch) {
355 // This method executes on the commit sequence. 362 // This method executes on the commit sequence.
356 DCHECK(task_runner_->IsRunningOnCommitSequence()); 363 DCHECK(task_runner_->IsRunningOnCommitSequence());
357 bool success = backing_->CommitChanges(commit_batch->clear_all_first, 364 bool success = backing_->CommitChanges(commit_batch->clear_all_first,
358 commit_batch->changed_values); 365 commit_batch->changed_values);
359 DCHECK(success); // TODO(michaeln): what if it fails? 366 DCHECK(success); // TODO(michaeln): what if it fails?
360 task_runner_->PostTask( 367 task_runner_->PostTask(
361 FROM_HERE, 368 FROM_HERE,
362 base::Bind(&DomStorageArea::OnCommitComplete, this)); 369 base::Bind(&DOMStorageArea::OnCommitComplete, this));
363 } 370 }
364 371
365 void DomStorageArea::OnCommitComplete() { 372 void DOMStorageArea::OnCommitComplete() {
366 // We're back on the primary sequence in this method. 373 // We're back on the primary sequence in this method.
367 DCHECK(task_runner_->IsRunningOnPrimarySequence()); 374 DCHECK(task_runner_->IsRunningOnPrimarySequence());
368 --commit_batches_in_flight_; 375 --commit_batches_in_flight_;
369 if (is_shutdown_) 376 if (is_shutdown_)
370 return; 377 return;
371 if (commit_batch_.get() && !commit_batches_in_flight_) { 378 if (commit_batch_.get() && !commit_batches_in_flight_) {
372 // More changes have accrued, restart the timer. 379 // More changes have accrued, restart the timer.
373 task_runner_->PostDelayedTask( 380 task_runner_->PostDelayedTask(
374 FROM_HERE, 381 FROM_HERE,
375 base::Bind(&DomStorageArea::OnCommitTimer, this), 382 base::Bind(&DOMStorageArea::OnCommitTimer, this),
376 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); 383 base::TimeDelta::FromSeconds(kCommitTimerSeconds));
377 } 384 }
378 } 385 }
379 386
380 void DomStorageArea::ShutdownInCommitSequence() { 387 void DOMStorageArea::ShutdownInCommitSequence() {
381 // This method executes on the commit sequence. 388 // This method executes on the commit sequence.
382 DCHECK(task_runner_->IsRunningOnCommitSequence()); 389 DCHECK(task_runner_->IsRunningOnCommitSequence());
383 DCHECK(backing_.get()); 390 DCHECK(backing_.get());
384 if (commit_batch_) { 391 if (commit_batch_) {
385 // Commit any changes that accrued prior to the timer firing. 392 // Commit any changes that accrued prior to the timer firing.
386 bool success = backing_->CommitChanges( 393 bool success = backing_->CommitChanges(
387 commit_batch_->clear_all_first, 394 commit_batch_->clear_all_first,
388 commit_batch_->changed_values); 395 commit_batch_->changed_values);
389 DCHECK(success); 396 DCHECK(success);
390 } 397 }
391 commit_batch_.reset(); 398 commit_batch_.reset();
392 backing_.reset(); 399 backing_.reset();
393 session_storage_backing_ = NULL; 400 session_storage_backing_ = NULL;
394 } 401 }
395 402
396 } // namespace dom_storage 403 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/dom_storage/dom_storage_area.h ('k') | content/browser/dom_storage/dom_storage_area_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698