OLD | NEW |
---|---|
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/dom_storage/dom_storage_area.h" | 5 #include "webkit/dom_storage/dom_storage_area.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | |
9 #include "base/location.h" | 8 #include "base/location.h" |
10 #include "base/logging.h" | 9 #include "base/logging.h" |
11 #include "base/time.h" | 10 #include "base/time.h" |
12 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 11 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
13 #include "webkit/database/database_util.h" | 12 #include "webkit/database/database_util.h" |
13 #include "webkit/dom_storage/dom_storage_database.h" | |
14 #include "webkit/dom_storage/dom_storage_map.h" | 14 #include "webkit/dom_storage/dom_storage_map.h" |
15 #include "webkit/dom_storage/dom_storage_namespace.h" | 15 #include "webkit/dom_storage/dom_storage_namespace.h" |
16 #include "webkit/dom_storage/dom_storage_task_runner.h" | 16 #include "webkit/dom_storage/dom_storage_task_runner.h" |
17 #include "webkit/dom_storage/dom_storage_types.h" | 17 #include "webkit/dom_storage/dom_storage_types.h" |
18 #include "webkit/dom_storage/local_storage_database_adapter.h" | |
19 #include "webkit/dom_storage/session_storage_database.h" | |
20 #include "webkit/dom_storage/session_storage_database_adapter.h" | |
18 #include "webkit/fileapi/file_system_util.h" | 21 #include "webkit/fileapi/file_system_util.h" |
19 #include "webkit/glue/webkit_glue.h" | 22 #include "webkit/glue/webkit_glue.h" |
20 | 23 |
21 using webkit_database::DatabaseUtil; | 24 using webkit_database::DatabaseUtil; |
22 | 25 |
23 namespace dom_storage { | 26 namespace dom_storage { |
24 | 27 |
25 static const int kCommitTimerSeconds = 1; | 28 static const int kCommitTimerSeconds = 1; |
26 | 29 |
27 DomStorageArea::CommitBatch::CommitBatch() | 30 DomStorageArea::CommitBatch::CommitBatch() |
28 : clear_all_first(false) { | 31 : clear_all_first(false), |
32 clear_all_after_deep_copy(false) { | |
29 } | 33 } |
30 DomStorageArea::CommitBatch::~CommitBatch() {} | 34 DomStorageArea::CommitBatch::~CommitBatch() {} |
31 | 35 |
32 | 36 |
33 // static | 37 // static |
34 const FilePath::CharType DomStorageArea::kDatabaseFileExtension[] = | 38 const FilePath::CharType DomStorageArea::kDatabaseFileExtension[] = |
35 FILE_PATH_LITERAL(".localstorage"); | 39 FILE_PATH_LITERAL(".localstorage"); |
36 | 40 |
37 // static | 41 // static |
38 FilePath DomStorageArea::DatabaseFileNameFromOrigin(const GURL& origin) { | 42 FilePath DomStorageArea::DatabaseFileNameFromOrigin(const GURL& origin) { |
(...skipping 13 matching lines...) Expand all Loading... | |
52 return DatabaseUtil::GetOriginFromIdentifier(origin_id); | 56 return DatabaseUtil::GetOriginFromIdentifier(origin_id); |
53 } | 57 } |
54 | 58 |
55 DomStorageArea::DomStorageArea( | 59 DomStorageArea::DomStorageArea( |
56 int64 namespace_id, const GURL& origin, | 60 int64 namespace_id, const GURL& origin, |
57 const FilePath& directory, DomStorageTaskRunner* task_runner) | 61 const FilePath& directory, DomStorageTaskRunner* task_runner) |
58 : namespace_id_(namespace_id), origin_(origin), | 62 : namespace_id_(namespace_id), origin_(origin), |
59 directory_(directory), | 63 directory_(directory), |
60 task_runner_(task_runner), | 64 task_runner_(task_runner), |
61 map_(new DomStorageMap(kPerAreaQuota)), | 65 map_(new DomStorageMap(kPerAreaQuota)), |
66 is_initial_import_done_(false), | |
67 is_shutdown_(false), | |
68 is_shallow_copy_(false) { | |
69 DCHECK(!directory.empty()); | |
70 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id); | |
71 FilePath path = directory.Append(DatabaseFileNameFromOrigin(origin_)); | |
72 backing_.reset(new LocalStorageDatabaseAdapter(new DomStorageDatabase(path))); | |
73 } | |
74 | |
75 DomStorageArea::DomStorageArea( | |
76 int64 namespace_id, const GURL& origin, | |
77 SessionStorageDatabase* session_storage_backing, | |
78 DomStorageTaskRunner* task_runner) | |
79 : namespace_id_(namespace_id), origin_(origin), | |
80 task_runner_(task_runner), | |
81 map_(new DomStorageMap(kPerAreaQuota)), | |
82 session_storage_backing_(session_storage_backing), | |
83 is_initial_import_done_(false), | |
84 is_shutdown_(false), | |
85 is_shallow_copy_(false) { | |
86 DCHECK(namespace_id != kLocalStorageNamespaceId); | |
87 backing_.reset(new SessionStorageDatabaseAdapter( | |
88 session_storage_backing, namespace_id, origin)); | |
89 } | |
90 | |
91 DomStorageArea::DomStorageArea(int64 namespace_id, | |
92 const GURL& origin, | |
93 DomStorageTaskRunner* task_runner) | |
94 : namespace_id_(namespace_id), origin_(origin), | |
95 task_runner_(task_runner), | |
96 map_(new DomStorageMap(kPerAreaQuota)), | |
62 is_initial_import_done_(true), | 97 is_initial_import_done_(true), |
63 is_shutdown_(false) { | 98 is_shutdown_(false), |
64 if (namespace_id == kLocalStorageNamespaceId && !directory.empty()) { | 99 is_shallow_copy_(false) { |
65 FilePath path = directory.Append(DatabaseFileNameFromOrigin(origin_)); | |
66 backing_.reset(new DomStorageDatabase(path)); | |
67 is_initial_import_done_ = false; | |
68 } | |
69 } | 100 } |
70 | 101 |
71 DomStorageArea::~DomStorageArea() { | 102 DomStorageArea::~DomStorageArea() { |
72 } | 103 } |
73 | 104 |
74 unsigned DomStorageArea::Length() { | 105 unsigned DomStorageArea::Length() { |
75 if (is_shutdown_) | 106 if (is_shutdown_) |
76 return 0; | 107 return 0; |
77 InitialImportIfNeeded(); | 108 InitialImportIfNeeded(); |
78 return map_->Length(); | 109 return map_->Length(); |
(...skipping 12 matching lines...) Expand all Loading... | |
91 InitialImportIfNeeded(); | 122 InitialImportIfNeeded(); |
92 return map_->GetItem(key); | 123 return map_->GetItem(key); |
93 } | 124 } |
94 | 125 |
95 bool DomStorageArea::SetItem(const string16& key, | 126 bool DomStorageArea::SetItem(const string16& key, |
96 const string16& value, | 127 const string16& value, |
97 NullableString16* old_value) { | 128 NullableString16* old_value) { |
98 if (is_shutdown_) | 129 if (is_shutdown_) |
99 return false; | 130 return false; |
100 InitialImportIfNeeded(); | 131 InitialImportIfNeeded(); |
101 if (!map_->HasOneRef()) | 132 bool was_shallow_copy = is_shallow_copy_; |
102 map_ = map_->DeepCopy(); | 133 if (is_shallow_copy_) { |
134 // It's possible that the other DomStorageAreas referring to the same map | |
135 // already made a deep copy. If that's the case, we don't need to do | |
136 // anything. | |
michaeln
2012/04/22 21:43:35
i'd rather depend on HasOneRef() for this and nix
marja
2012/05/11 12:18:32
Done.
| |
137 if (!map_->HasOneRef()) | |
138 map_ = map_->DeepCopy(); | |
139 is_shallow_copy_ = false; | |
140 } | |
103 bool success = map_->SetItem(key, value, old_value); | 141 bool success = map_->SetItem(key, value, old_value); |
104 if (success && backing_.get()) { | 142 if (success && backing_.get()) { |
105 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 143 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
106 commit_batch->changed_values[key] = NullableString16(value, false); | 144 // If this area was a shallow copy, the existing changes in the commit batch |
145 // should be committed before doing a deep copy. This change, and all the | |
146 // changes after this, should be committed after the deep copy. The database | |
147 // takes care of not doing a deep copy of a map which is only referred to | |
148 // once. | |
michaeln
2012/04/22 21:43:35
It might be a simplification to flush pending chan
michaeln
2012/04/22 23:48:02
or maybe a pattern like this that factors out more
marja
2012/05/11 12:18:32
- The deep copy problem was solved by http://coder
michaeln
2012/05/16 08:10:55
sgtm!
| |
149 if (was_shallow_copy || | |
150 !commit_batch->changed_values_after_deep_copy.empty() || | |
151 commit_batch->clear_all_after_deep_copy) { | |
152 commit_batch->changed_values_after_deep_copy[key] = | |
153 NullableString16(value, false); | |
154 } | |
155 else { | |
156 commit_batch->changed_values[key] = NullableString16(value, false); | |
157 } | |
107 } | 158 } |
108 return success; | 159 return success; |
109 } | 160 } |
110 | 161 |
111 bool DomStorageArea::RemoveItem(const string16& key, string16* old_value) { | 162 bool DomStorageArea::RemoveItem(const string16& key, string16* old_value) { |
112 if (is_shutdown_) | 163 if (is_shutdown_) |
113 return false; | 164 return false; |
114 InitialImportIfNeeded(); | 165 InitialImportIfNeeded(); |
115 if (!map_->HasOneRef()) | 166 // See comments in SetItem. |
116 map_ = map_->DeepCopy(); | 167 bool was_shallow_copy = is_shallow_copy_; |
168 if (is_shallow_copy_) { | |
169 if (!map_->HasOneRef()) | |
170 map_ = map_->DeepCopy(); | |
171 is_shallow_copy_ = false; | |
172 } | |
117 bool success = map_->RemoveItem(key, old_value); | 173 bool success = map_->RemoveItem(key, old_value); |
118 if (success && backing_.get()) { | 174 if (success && backing_.get()) { |
119 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 175 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
120 commit_batch->changed_values[key] = NullableString16(true); | 176 if (was_shallow_copy || |
177 !commit_batch->changed_values_after_deep_copy.empty() || | |
178 commit_batch->clear_all_after_deep_copy) { | |
179 commit_batch->changed_values_after_deep_copy[key] = | |
180 NullableString16(true); | |
181 } else { | |
182 commit_batch->changed_values[key] = NullableString16(true); | |
183 } | |
121 } | 184 } |
122 return success; | 185 return success; |
123 } | 186 } |
124 | 187 |
125 bool DomStorageArea::Clear() { | 188 bool DomStorageArea::Clear() { |
126 if (is_shutdown_) | 189 if (is_shutdown_) |
127 return false; | 190 return false; |
128 InitialImportIfNeeded(); | 191 InitialImportIfNeeded(); |
129 if (map_->Length() == 0) | 192 if (map_->Length() == 0) |
130 return false; | 193 return false; |
131 | 194 |
195 // See comments in SetItem. | |
196 bool was_shallow_copy = is_shallow_copy_; | |
197 is_shallow_copy_ = false; | |
132 map_ = new DomStorageMap(kPerAreaQuota); | 198 map_ = new DomStorageMap(kPerAreaQuota); |
133 | 199 |
134 if (backing_.get()) { | 200 if (backing_.get()) { |
135 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 201 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
136 commit_batch->clear_all_first = true; | 202 if (was_shallow_copy || |
137 commit_batch->changed_values.clear(); | 203 !commit_batch->changed_values_after_deep_copy.empty() || |
204 commit_batch->clear_all_after_deep_copy) { | |
205 commit_batch->clear_all_after_deep_copy = true; | |
206 commit_batch->changed_values_after_deep_copy.clear(); | |
207 } else { | |
208 commit_batch->clear_all_first = true; | |
209 commit_batch->changed_values.clear(); | |
210 } | |
138 } | 211 } |
139 | 212 |
140 return true; | 213 return true; |
141 } | 214 } |
142 | 215 |
143 DomStorageArea* DomStorageArea::ShallowCopy(int64 destination_namespace_id) { | 216 DomStorageArea* DomStorageArea::ShallowCopy(int64 destination_namespace_id) { |
144 DCHECK_NE(kLocalStorageNamespaceId, namespace_id_); | 217 DCHECK_NE(kLocalStorageNamespaceId, namespace_id_); |
145 DCHECK_NE(kLocalStorageNamespaceId, destination_namespace_id); | 218 DCHECK_NE(kLocalStorageNamespaceId, destination_namespace_id); |
146 DCHECK(!backing_.get()); // SessionNamespaces aren't stored on disk. | 219 DCHECK(session_storage_backing_.get()); |
147 | 220 |
148 DomStorageArea* copy = new DomStorageArea(destination_namespace_id, origin_, | 221 DomStorageArea* copy = new DomStorageArea( |
149 FilePath(), task_runner_); | 222 destination_namespace_id, origin_, session_storage_backing_, |
223 task_runner_); | |
224 copy->is_shallow_copy_ = true; | |
150 copy->map_ = map_; | 225 copy->map_ = map_; |
151 copy->is_shutdown_ = is_shutdown_; | 226 copy->is_shutdown_ = is_shutdown_; |
227 | |
228 // Also this area is now a shallow copy; changes to either of these 2 areas | |
229 // will initiate deep copying. | |
230 is_shallow_copy_ = true; | |
231 | |
232 if (session_storage_backing_.get()) { | |
233 // If this area has uncommitted changes, they need to happen before | |
234 // DomStorageNamespace does the shallow-copying of the database. Also, if | |
235 // the area is empty, we need to ensure that a placeholder for it exists in | |
236 // the database. An empty commit batch achieves this. | |
michaeln
2012/04/22 21:43:35
Does the empty placeholder really need to be there
marja
2012/05/11 12:18:32
Done. Empty placeholder is not needed any more.
| |
237 CreateCommitBatchIfNeeded(); | |
238 OnCommitTimer(); | |
239 } | |
152 return copy; | 240 return copy; |
153 } | 241 } |
154 | 242 |
155 bool DomStorageArea::HasUncommittedChanges() const { | 243 bool DomStorageArea::HasUncommittedChanges() const { |
156 DCHECK(!is_shutdown_); | 244 DCHECK(!is_shutdown_); |
157 return commit_batch_.get() || in_flight_commit_batch_.get(); | 245 return commit_batch_.get() || in_flight_commit_batch_.get(); |
158 } | 246 } |
159 | 247 |
160 void DomStorageArea::DeleteOrigin() { | 248 void DomStorageArea::DeleteOrigin() { |
161 DCHECK(!is_shutdown_); | 249 DCHECK(!is_shutdown_); |
162 if (HasUncommittedChanges()) { | 250 if (HasUncommittedChanges()) { |
163 // TODO(michaeln): This logically deletes the data immediately, | 251 // TODO(michaeln): This logically deletes the data immediately, |
164 // and in a matter of a second, deletes the rows from the backing | 252 // and in a matter of a second, deletes the rows from the backing |
165 // database file, but the file itself will linger until shutdown | 253 // database file, but the file itself will linger until shutdown |
166 // or purge time. Ideally, this should delete the file more | 254 // or purge time. Ideally, this should delete the file more |
167 // quickly. | 255 // quickly. |
168 Clear(); | 256 Clear(); |
169 return; | 257 return; |
170 } | 258 } |
171 map_ = new DomStorageMap(kPerAreaQuota); | 259 map_ = new DomStorageMap(kPerAreaQuota); |
172 if (backing_.get()) { | 260 if (backing_.get() && !session_storage_backing_.get()) { |
261 // This is localStorage. | |
173 is_initial_import_done_ = false; | 262 is_initial_import_done_ = false; |
174 backing_.reset(new DomStorageDatabase(backing_->file_path())); | 263 backing_->Reset(); |
175 file_util::Delete(backing_->file_path(), false); | 264 backing_->DeleteFiles(); |
176 file_util::Delete( | 265 } else if (session_storage_backing_.get()) { |
177 DomStorageDatabase::GetJournalFilePath(backing_->file_path()), false); | 266 // Delete the origin from the session storage by creating an empty commit |
267 // batch. | |
268 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | |
269 if (is_shallow_copy_) | |
270 commit_batch->clear_all_after_deep_copy = true; | |
271 else | |
272 commit_batch->clear_all_first = true; | |
178 } | 273 } |
179 } | 274 } |
180 | 275 |
181 void DomStorageArea::PurgeMemory() { | 276 void DomStorageArea::PurgeMemory() { |
182 DCHECK(!is_shutdown_); | 277 DCHECK(!is_shutdown_); |
183 if (!is_initial_import_done_ || // We're not using any memory. | 278 if (!is_initial_import_done_ || // We're not using any memory. |
184 !backing_.get() || // We can't purge anything. | 279 !backing_.get() || // We can't purge anything. |
185 HasUncommittedChanges()) // We leave things alone with changes pending. | 280 HasUncommittedChanges()) // We leave things alone with changes pending. |
186 return; | 281 return; |
187 | 282 |
188 // Drop the in memory cache, we'll reload when needed. | 283 // Drop the in memory cache, we'll reload when needed. |
189 is_initial_import_done_ = false; | 284 is_initial_import_done_ = false; |
190 map_ = new DomStorageMap(kPerAreaQuota); | 285 map_ = new DomStorageMap(kPerAreaQuota); |
191 | 286 |
192 // Recreate the database object, this frees up the open sqlite connection | 287 // Recreate the database object, this frees up the open sqlite connection |
193 // and its page cache. | 288 // and its page cache. |
194 backing_.reset(new DomStorageDatabase(backing_->file_path())); | 289 backing_->Reset(); |
195 } | 290 } |
196 | 291 |
197 void DomStorageArea::Shutdown() { | 292 void DomStorageArea::Shutdown() { |
198 DCHECK(!is_shutdown_); | 293 DCHECK(!is_shutdown_); |
199 is_shutdown_ = true; | 294 is_shutdown_ = true; |
200 map_ = NULL; | 295 map_ = NULL; |
201 if (!backing_.get()) | 296 if (!backing_.get()) |
202 return; | 297 return; |
203 | 298 |
204 bool success = task_runner_->PostShutdownBlockingTask( | 299 bool success = task_runner_->PostShutdownBlockingTask( |
205 FROM_HERE, | 300 FROM_HERE, |
206 DomStorageTaskRunner::COMMIT_SEQUENCE, | 301 DomStorageTaskRunner::COMMIT_SEQUENCE, |
207 base::Bind(&DomStorageArea::ShutdownInCommitSequence, this)); | 302 base::Bind(&DomStorageArea::ShutdownInCommitSequence, this)); |
208 DCHECK(success); | 303 DCHECK(success); |
209 } | 304 } |
210 | 305 |
211 void DomStorageArea::InitialImportIfNeeded() { | 306 void DomStorageArea::InitialImportIfNeeded() { |
212 if (is_initial_import_done_) | 307 if (is_initial_import_done_) |
213 return; | 308 return; |
214 | 309 |
215 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id_); | |
216 DCHECK(backing_.get()); | 310 DCHECK(backing_.get()); |
217 | 311 |
218 ValuesMap initial_values; | 312 ValuesMap initial_values; |
219 backing_->ReadAllValues(&initial_values); | 313 backing_->ReadAllValues(&initial_values); |
220 map_->SwapValues(&initial_values); | 314 map_->SwapValues(&initial_values); |
221 is_initial_import_done_ = true; | 315 is_initial_import_done_ = true; |
222 } | 316 } |
223 | 317 |
224 DomStorageArea::CommitBatch* DomStorageArea::CreateCommitBatchIfNeeded() { | 318 DomStorageArea::CommitBatch* DomStorageArea::CreateCommitBatchIfNeeded() { |
225 DCHECK(!is_shutdown_); | 319 DCHECK(!is_shutdown_); |
226 if (!commit_batch_.get()) { | 320 if (!commit_batch_.get()) { |
227 commit_batch_.reset(new CommitBatch()); | 321 commit_batch_.reset(new CommitBatch()); |
228 | 322 |
229 // Start a timer to commit any changes that accrue in the batch, | 323 // Start a timer to commit any changes that accrue in the batch, |
230 // but only if a commit is not currently in flight. In that case | 324 // but only if a commit is not currently in flight. In that case |
231 // the timer will be started after the current commit has happened. | 325 // the timer will be started after the current commit has happened. |
232 if (!in_flight_commit_batch_.get()) { | 326 if (!in_flight_commit_batch_.get()) { |
233 task_runner_->PostDelayedTask( | 327 task_runner_->PostDelayedTask( |
234 FROM_HERE, | 328 FROM_HERE, |
235 base::Bind(&DomStorageArea::OnCommitTimer, this), | 329 base::Bind(&DomStorageArea::OnCommitTimer, this), |
236 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); | 330 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); |
237 } | 331 } |
238 } | 332 } |
239 return commit_batch_.get(); | 333 return commit_batch_.get(); |
240 } | 334 } |
241 | 335 |
242 void DomStorageArea::OnCommitTimer() { | 336 void DomStorageArea::OnCommitTimer() { |
243 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id_); | |
244 if (is_shutdown_) | 337 if (is_shutdown_) |
245 return; | 338 return; |
246 | 339 |
247 DCHECK(backing_.get()); | 340 DCHECK(backing_.get()); |
248 DCHECK(commit_batch_.get()); | 341 // It's possible that there is nothing to commit, since a shallow copy occured |
342 // before the timer fired. | |
343 if (!commit_batch_.get()) | |
344 return; | |
345 | |
249 DCHECK(!in_flight_commit_batch_.get()); | 346 DCHECK(!in_flight_commit_batch_.get()); |
250 | 347 |
251 // This method executes on the primary sequence, we schedule | 348 // This method executes on the primary sequence, we schedule |
252 // a task for immediate execution on the commit sequence. | 349 // a task for immediate execution on the commit sequence. |
253 DCHECK(task_runner_->IsRunningOnPrimarySequence()); | 350 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
254 in_flight_commit_batch_ = commit_batch_.Pass(); | 351 in_flight_commit_batch_ = commit_batch_.Pass(); |
255 bool success = task_runner_->PostShutdownBlockingTask( | 352 bool success = task_runner_->PostShutdownBlockingTask( |
256 FROM_HERE, | 353 FROM_HERE, |
257 DomStorageTaskRunner::COMMIT_SEQUENCE, | 354 DomStorageTaskRunner::COMMIT_SEQUENCE, |
258 base::Bind(&DomStorageArea::CommitChanges, this)); | 355 base::Bind(&DomStorageArea::CommitChanges, this)); |
259 DCHECK(success); | 356 DCHECK(success); |
260 } | 357 } |
261 | 358 |
262 void DomStorageArea::CommitChanges() { | 359 void DomStorageArea::CommitChanges() { |
263 // This method executes on the commit sequence. | 360 // This method executes on the commit sequence. |
264 DCHECK(task_runner_->IsRunningOnCommitSequence()); | 361 DCHECK(task_runner_->IsRunningOnCommitSequence()); |
265 DCHECK(in_flight_commit_batch_.get()); | 362 DCHECK(in_flight_commit_batch_.get()); |
266 bool success = backing_->CommitChanges( | 363 bool success = backing_->CommitChanges( |
267 in_flight_commit_batch_->clear_all_first, | 364 in_flight_commit_batch_->clear_all_first, |
268 in_flight_commit_batch_->changed_values); | 365 in_flight_commit_batch_->changed_values); |
269 DCHECK(success); // TODO(michaeln): what if it fails? | 366 DCHECK(success); // TODO(michaeln): what if it fails? |
367 if (session_storage_backing_.get() && | |
368 (in_flight_commit_batch_->clear_all_after_deep_copy || | |
369 !in_flight_commit_batch_->changed_values_after_deep_copy.empty())) { | |
370 if (in_flight_commit_batch_->clear_all_after_deep_copy) { | |
371 // Shortcut: If we're going to make a deep copy and clear the area, no | |
372 // need to create the deep copy first. We will just break the association | |
373 // to the existing map. A new map will be created when data is inserted | |
374 // into it. | |
375 session_storage_backing_->DisassociateMap(namespace_id_, origin_); | |
376 } else { | |
377 session_storage_backing_->DeepCopy(namespace_id_, origin_); | |
378 } | |
379 bool success = backing_->CommitChanges( | |
380 false, in_flight_commit_batch_->changed_values_after_deep_copy); | |
381 DCHECK(success); // TODO(michaeln): what if it fails? | |
382 } | |
383 | |
270 task_runner_->PostTask( | 384 task_runner_->PostTask( |
271 FROM_HERE, | 385 FROM_HERE, |
272 base::Bind(&DomStorageArea::OnCommitComplete, this)); | 386 base::Bind(&DomStorageArea::OnCommitComplete, this)); |
273 } | 387 } |
274 | 388 |
275 void DomStorageArea::OnCommitComplete() { | 389 void DomStorageArea::OnCommitComplete() { |
276 // We're back on the primary sequence in this method. | 390 // We're back on the primary sequence in this method. |
277 DCHECK(task_runner_->IsRunningOnPrimarySequence()); | 391 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
278 if (is_shutdown_) | 392 if (is_shutdown_) |
279 return; | 393 return; |
(...skipping 14 matching lines...) Expand all Loading... | |
294 if (commit_batch_.get()) { | 408 if (commit_batch_.get()) { |
295 // Commit any changes that accrued prior to the timer firing. | 409 // Commit any changes that accrued prior to the timer firing. |
296 bool success = backing_->CommitChanges( | 410 bool success = backing_->CommitChanges( |
297 commit_batch_->clear_all_first, | 411 commit_batch_->clear_all_first, |
298 commit_batch_->changed_values); | 412 commit_batch_->changed_values); |
299 DCHECK(success); | 413 DCHECK(success); |
300 } | 414 } |
301 commit_batch_.reset(); | 415 commit_batch_.reset(); |
302 in_flight_commit_batch_.reset(); | 416 in_flight_commit_batch_.reset(); |
303 backing_.reset(); | 417 backing_.reset(); |
418 session_storage_backing_ = NULL; | |
304 } | 419 } |
305 | 420 |
306 } // namespace dom_storage | 421 } // namespace dom_storage |
OLD | NEW |