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" | 8 #include "base/file_util.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/time.h" | 11 #include "base/time.h" |
12 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 12 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
13 #include "webkit/database/database_util.h" | 13 #include "webkit/database/database_util.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/session_storage_database.h" | |
18 #include "webkit/fileapi/file_system_util.h" | 19 #include "webkit/fileapi/file_system_util.h" |
19 #include "webkit/glue/webkit_glue.h" | 20 #include "webkit/glue/webkit_glue.h" |
20 | 21 |
21 using webkit_database::DatabaseUtil; | 22 using webkit_database::DatabaseUtil; |
22 | 23 |
23 namespace dom_storage { | 24 namespace dom_storage { |
24 | 25 |
25 static const int kCommitTimerSeconds = 1; | 26 static const int kCommitTimerSeconds = 1; |
26 | 27 |
27 DomStorageArea::CommitBatch::CommitBatch() | 28 DomStorageArea::CommitBatch::CommitBatch() |
(...skipping 24 matching lines...) Expand all Loading... | |
52 return DatabaseUtil::GetOriginFromIdentifier(origin_id); | 53 return DatabaseUtil::GetOriginFromIdentifier(origin_id); |
53 } | 54 } |
54 | 55 |
55 DomStorageArea::DomStorageArea( | 56 DomStorageArea::DomStorageArea( |
56 int64 namespace_id, const GURL& origin, | 57 int64 namespace_id, const GURL& origin, |
57 const FilePath& directory, DomStorageTaskRunner* task_runner) | 58 const FilePath& directory, DomStorageTaskRunner* task_runner) |
58 : namespace_id_(namespace_id), origin_(origin), | 59 : namespace_id_(namespace_id), origin_(origin), |
59 directory_(directory), | 60 directory_(directory), |
60 task_runner_(task_runner), | 61 task_runner_(task_runner), |
61 map_(new DomStorageMap(kPerAreaQuota)), | 62 map_(new DomStorageMap(kPerAreaQuota)), |
63 is_initial_import_done_(false), | |
64 is_shutdown_(false), | |
65 is_shallow_copy_(false) { | |
66 DCHECK(!directory.empty()); | |
67 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id); | |
68 FilePath path = directory.Append(DatabaseFileNameFromOrigin(origin_)); | |
69 backing_.reset(new LocalStorageDatabase(path)); | |
70 } | |
71 | |
72 DomStorageArea::DomStorageArea( | |
73 int64 namespace_id, const GURL& origin, | |
74 SessionStorageDatabase* session_storage_backing, | |
75 DomStorageTaskRunner* task_runner) | |
76 : namespace_id_(namespace_id), origin_(origin), | |
77 task_runner_(task_runner), | |
78 map_(new DomStorageMap(kPerAreaQuota)), | |
79 session_storage_backing_(session_storage_backing), | |
80 is_initial_import_done_(false), | |
81 is_shutdown_(false), | |
82 is_shallow_copy_(false) { | |
83 DCHECK(namespace_id != kLocalStorageNamespaceId); | |
84 } | |
85 | |
86 DomStorageArea::DomStorageArea(int64 namespace_id, | |
87 const GURL& origin, | |
88 DomStorageTaskRunner* task_runner) | |
89 : namespace_id_(namespace_id), origin_(origin), | |
90 task_runner_(task_runner), | |
91 map_(new DomStorageMap(kPerAreaQuota)), | |
62 is_initial_import_done_(true), | 92 is_initial_import_done_(true), |
63 is_shutdown_(false) { | 93 is_shutdown_(false), |
64 if (namespace_id == kLocalStorageNamespaceId && !directory.empty()) { | 94 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 } | 95 } |
70 | 96 |
71 DomStorageArea::~DomStorageArea() { | 97 DomStorageArea::~DomStorageArea() { |
72 } | 98 } |
73 | 99 |
74 unsigned DomStorageArea::Length() { | 100 unsigned DomStorageArea::Length() { |
75 if (is_shutdown_) | 101 if (is_shutdown_) |
76 return 0; | 102 return 0; |
77 InitialImportIfNeeded(); | 103 InitialImportIfNeeded(); |
78 return map_->Length(); | 104 return map_->Length(); |
(...skipping 12 matching lines...) Expand all Loading... | |
91 InitialImportIfNeeded(); | 117 InitialImportIfNeeded(); |
92 return map_->GetItem(key); | 118 return map_->GetItem(key); |
93 } | 119 } |
94 | 120 |
95 bool DomStorageArea::SetItem(const string16& key, | 121 bool DomStorageArea::SetItem(const string16& key, |
96 const string16& value, | 122 const string16& value, |
97 NullableString16* old_value) { | 123 NullableString16* old_value) { |
98 if (is_shutdown_) | 124 if (is_shutdown_) |
99 return false; | 125 return false; |
100 InitialImportIfNeeded(); | 126 InitialImportIfNeeded(); |
101 if (!map_->HasOneRef()) | 127 if (is_shallow_copy_) { |
102 map_ = map_->DeepCopy(); | 128 map_ = map_->DeepCopy(); |
129 if (session_storage_backing_.get()) { | |
130 session_storage_backing_->DeepCopy(namespace_id_, origin_); | |
michaeln
2012/04/12 01:48:46
see comments below about serializing deepcopy with
marja
2012/04/19 10:20:50
Done.
| |
131 } | |
132 is_shallow_copy_ = false; | |
133 } | |
103 bool success = map_->SetItem(key, value, old_value); | 134 bool success = map_->SetItem(key, value, old_value); |
104 if (success && backing_.get()) { | 135 if (success && GetBacking()) { |
105 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 136 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
106 commit_batch->changed_values[key] = NullableString16(value, false); | 137 commit_batch->changed_values[key] = NullableString16(value, false); |
107 } | 138 } |
108 return success; | 139 return success; |
109 } | 140 } |
110 | 141 |
111 bool DomStorageArea::RemoveItem(const string16& key, string16* old_value) { | 142 bool DomStorageArea::RemoveItem(const string16& key, string16* old_value) { |
112 if (is_shutdown_) | 143 if (is_shutdown_) |
113 return false; | 144 return false; |
114 InitialImportIfNeeded(); | 145 InitialImportIfNeeded(); |
115 if (!map_->HasOneRef()) | 146 if (is_shallow_copy_) { |
116 map_ = map_->DeepCopy(); | 147 map_ = map_->DeepCopy(); |
148 if (session_storage_backing_.get()) { | |
149 session_storage_backing_->DeepCopy(namespace_id_, origin_); | |
michaeln
2012/04/12 01:48:46
The changes to the backing store made by DeepCopy
marja
2012/04/19 10:20:50
Done. deep_copy_first doens't work, since the same
| |
150 } | |
151 is_shallow_copy_ = false; | |
152 } | |
117 bool success = map_->RemoveItem(key, old_value); | 153 bool success = map_->RemoveItem(key, old_value); |
118 if (success && backing_.get()) { | 154 if (success && GetBacking()) { |
119 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 155 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
120 commit_batch->changed_values[key] = NullableString16(true); | 156 commit_batch->changed_values[key] = NullableString16(true); |
121 } | 157 } |
122 return success; | 158 return success; |
123 } | 159 } |
124 | 160 |
125 bool DomStorageArea::Clear() { | 161 bool DomStorageArea::Clear() { |
126 if (is_shutdown_) | 162 if (is_shutdown_) |
127 return false; | 163 return false; |
128 InitialImportIfNeeded(); | 164 InitialImportIfNeeded(); |
129 if (map_->Length() == 0) | 165 if (map_->Length() == 0) |
130 return false; | 166 return false; |
131 | 167 |
132 map_ = new DomStorageMap(kPerAreaQuota); | 168 map_ = new DomStorageMap(kPerAreaQuota); |
michaeln
2012/04/12 01:48:46
if this area is a 'shallow copy', we'll need to co
marja
2012/04/19 10:20:50
Done.
| |
133 | 169 |
134 if (backing_.get()) { | 170 if (GetBacking()) { |
135 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 171 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
136 commit_batch->clear_all_first = true; | 172 commit_batch->clear_all_first = true; |
137 commit_batch->changed_values.clear(); | 173 commit_batch->changed_values.clear(); |
138 } | 174 } |
139 | 175 |
140 return true; | 176 return true; |
141 } | 177 } |
142 | 178 |
143 DomStorageArea* DomStorageArea::ShallowCopy(int64 destination_namespace_id) { | 179 DomStorageArea* DomStorageArea::ShallowCopy(int64 destination_namespace_id) { |
144 DCHECK_NE(kLocalStorageNamespaceId, namespace_id_); | 180 DCHECK_NE(kLocalStorageNamespaceId, namespace_id_); |
145 DCHECK_NE(kLocalStorageNamespaceId, destination_namespace_id); | 181 DCHECK_NE(kLocalStorageNamespaceId, destination_namespace_id); |
146 DCHECK(!backing_.get()); // SessionNamespaces aren't stored on disk. | 182 DCHECK(session_storage_backing_.get()); |
147 | 183 |
148 DomStorageArea* copy = new DomStorageArea(destination_namespace_id, origin_, | 184 session_storage_backing_->ShallowCopy(namespace_id_, origin_, |
michaeln
2012/04/12 01:48:46
see earlier comments about serializing changes in
marja
2012/04/19 10:20:50
Done.
| |
149 FilePath(), task_runner_); | 185 destination_namespace_id); |
186 | |
187 DomStorageArea* copy = new DomStorageArea( | |
188 destination_namespace_id, origin_, session_storage_backing_, | |
189 task_runner_); | |
190 copy->is_shallow_copy_ = true; | |
150 copy->map_ = map_; | 191 copy->map_ = map_; |
151 copy->is_shutdown_ = is_shutdown_; | 192 copy->is_shutdown_ = is_shutdown_; |
152 return copy; | 193 return copy; |
153 } | 194 } |
154 | 195 |
155 bool DomStorageArea::HasUncommittedChanges() const { | 196 bool DomStorageArea::HasUncommittedChanges() const { |
156 DCHECK(!is_shutdown_); | 197 DCHECK(!is_shutdown_); |
157 return commit_batch_.get() || in_flight_commit_batch_.get(); | 198 return commit_batch_.get() || in_flight_commit_batch_.get(); |
158 } | 199 } |
159 | 200 |
160 void DomStorageArea::DeleteOrigin() { | 201 void DomStorageArea::DeleteOrigin() { |
161 DCHECK(!is_shutdown_); | 202 DCHECK(!is_shutdown_); |
162 if (HasUncommittedChanges()) { | 203 if (HasUncommittedChanges()) { |
163 // TODO(michaeln): This logically deletes the data immediately, | 204 // TODO(michaeln): This logically deletes the data immediately, |
164 // and in a matter of a second, deletes the rows from the backing | 205 // and in a matter of a second, deletes the rows from the backing |
165 // database file, but the file itself will linger until shutdown | 206 // database file, but the file itself will linger until shutdown |
166 // or purge time. Ideally, this should delete the file more | 207 // or purge time. Ideally, this should delete the file more |
167 // quickly. | 208 // quickly. |
168 Clear(); | 209 Clear(); |
169 return; | 210 return; |
170 } | 211 } |
171 map_ = new DomStorageMap(kPerAreaQuota); | 212 map_ = new DomStorageMap(kPerAreaQuota); |
172 if (backing_.get()) { | 213 if (backing_.get()) { |
173 is_initial_import_done_ = false; | 214 is_initial_import_done_ = false; |
174 backing_.reset(new DomStorageDatabase(backing_->file_path())); | 215 backing_.reset(new LocalStorageDatabase(backing_->file_path())); |
175 file_util::Delete(backing_->file_path(), false); | 216 file_util::Delete(backing_->file_path(), false); |
176 file_util::Delete( | 217 file_util::Delete( |
177 DomStorageDatabase::GetJournalFilePath(backing_->file_path()), false); | 218 LocalStorageDatabase::GetJournalFilePath(backing_->file_path()), false); |
219 } else if (session_storage_backing_.get()) { | |
220 session_storage_backing_->DeleteOrigin(namespace_id_, origin_); | |
michaeln
2012/04/12 01:48:46
probably needs to be serialized on the COMMIT_SEQU
marja
2012/04/19 10:20:50
Done.
| |
178 } | 221 } |
179 } | 222 } |
180 | 223 |
181 void DomStorageArea::PurgeMemory() { | 224 void DomStorageArea::PurgeMemory() { |
182 DCHECK(!is_shutdown_); | 225 DCHECK(!is_shutdown_); |
183 if (!is_initial_import_done_ || // We're not using any memory. | 226 if (!is_initial_import_done_ || // We're not using any memory. |
184 !backing_.get() || // We can't purge anything. | 227 !backing_.get() || // We can't purge anything. |
185 HasUncommittedChanges()) // We leave things alone with changes pending. | 228 HasUncommittedChanges()) // We leave things alone with changes pending. |
186 return; | 229 return; |
187 | 230 |
188 // Drop the in memory cache, we'll reload when needed. | 231 // Drop the in memory cache, we'll reload when needed. |
189 is_initial_import_done_ = false; | 232 is_initial_import_done_ = false; |
190 map_ = new DomStorageMap(kPerAreaQuota); | 233 map_ = new DomStorageMap(kPerAreaQuota); |
191 | 234 |
192 // Recreate the database object, this frees up the open sqlite connection | 235 // Recreate the database object, this frees up the open sqlite connection |
193 // and its page cache. | 236 // and its page cache. |
194 backing_.reset(new DomStorageDatabase(backing_->file_path())); | 237 backing_.reset(new LocalStorageDatabase(backing_->file_path())); |
195 } | 238 } |
196 | 239 |
197 void DomStorageArea::Shutdown() { | 240 void DomStorageArea::Shutdown() { |
198 DCHECK(!is_shutdown_); | 241 DCHECK(!is_shutdown_); |
199 is_shutdown_ = true; | 242 is_shutdown_ = true; |
200 map_ = NULL; | 243 map_ = NULL; |
201 if (!backing_.get()) | 244 if (!GetBacking()) |
202 return; | 245 return; |
203 | 246 |
204 bool success = task_runner_->PostShutdownBlockingTask( | 247 bool success = task_runner_->PostShutdownBlockingTask( |
205 FROM_HERE, | 248 FROM_HERE, |
206 DomStorageTaskRunner::COMMIT_SEQUENCE, | 249 DomStorageTaskRunner::COMMIT_SEQUENCE, |
207 base::Bind(&DomStorageArea::ShutdownInCommitSequence, this)); | 250 base::Bind(&DomStorageArea::ShutdownInCommitSequence, this)); |
208 DCHECK(success); | 251 DCHECK(success); |
209 } | 252 } |
210 | 253 |
211 void DomStorageArea::InitialImportIfNeeded() { | 254 void DomStorageArea::InitialImportIfNeeded() { |
212 if (is_initial_import_done_) | 255 if (is_initial_import_done_) |
213 return; | 256 return; |
214 | 257 |
215 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id_); | 258 DCHECK(GetBacking()); |
216 DCHECK(backing_.get()); | |
217 | 259 |
218 ValuesMap initial_values; | 260 ValuesMap initial_values; |
219 backing_->ReadAllValues(&initial_values); | 261 GetBacking()->ReadAllValues(namespace_id_, origin_, &initial_values); |
220 map_->SwapValues(&initial_values); | 262 map_->SwapValues(&initial_values); |
221 is_initial_import_done_ = true; | 263 is_initial_import_done_ = true; |
222 } | 264 } |
223 | 265 |
224 DomStorageArea::CommitBatch* DomStorageArea::CreateCommitBatchIfNeeded() { | 266 DomStorageArea::CommitBatch* DomStorageArea::CreateCommitBatchIfNeeded() { |
225 DCHECK(!is_shutdown_); | 267 DCHECK(!is_shutdown_); |
226 if (!commit_batch_.get()) { | 268 if (!commit_batch_.get()) { |
227 commit_batch_.reset(new CommitBatch()); | 269 commit_batch_.reset(new CommitBatch()); |
228 | 270 |
229 // Start a timer to commit any changes that accrue in the batch, | 271 // 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 | 272 // 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. | 273 // the timer will be started after the current commit has happened. |
232 if (!in_flight_commit_batch_.get()) { | 274 if (!in_flight_commit_batch_.get()) { |
233 task_runner_->PostDelayedTask( | 275 task_runner_->PostDelayedTask( |
234 FROM_HERE, | 276 FROM_HERE, |
235 base::Bind(&DomStorageArea::OnCommitTimer, this), | 277 base::Bind(&DomStorageArea::OnCommitTimer, this), |
236 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); | 278 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); |
237 } | 279 } |
238 } | 280 } |
239 return commit_batch_.get(); | 281 return commit_batch_.get(); |
240 } | 282 } |
241 | 283 |
242 void DomStorageArea::OnCommitTimer() { | 284 void DomStorageArea::OnCommitTimer() { |
243 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id_); | |
244 if (is_shutdown_) | 285 if (is_shutdown_) |
245 return; | 286 return; |
246 | 287 |
247 DCHECK(backing_.get()); | 288 DCHECK(GetBacking()); |
248 DCHECK(commit_batch_.get()); | 289 DCHECK(commit_batch_.get()); |
249 DCHECK(!in_flight_commit_batch_.get()); | 290 DCHECK(!in_flight_commit_batch_.get()); |
250 | 291 |
251 // This method executes on the primary sequence, we schedule | 292 // This method executes on the primary sequence, we schedule |
252 // a task for immediate execution on the commit sequence. | 293 // a task for immediate execution on the commit sequence. |
253 DCHECK(task_runner_->IsRunningOnPrimarySequence()); | 294 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
254 in_flight_commit_batch_ = commit_batch_.Pass(); | 295 in_flight_commit_batch_ = commit_batch_.Pass(); |
255 bool success = task_runner_->PostShutdownBlockingTask( | 296 bool success = task_runner_->PostShutdownBlockingTask( |
256 FROM_HERE, | 297 FROM_HERE, |
257 DomStorageTaskRunner::COMMIT_SEQUENCE, | 298 DomStorageTaskRunner::COMMIT_SEQUENCE, |
258 base::Bind(&DomStorageArea::CommitChanges, this)); | 299 base::Bind(&DomStorageArea::CommitChanges, this)); |
259 DCHECK(success); | 300 DCHECK(success); |
260 } | 301 } |
261 | 302 |
262 void DomStorageArea::CommitChanges() { | 303 void DomStorageArea::CommitChanges() { |
263 // This method executes on the commit sequence. | 304 // This method executes on the commit sequence. |
264 DCHECK(task_runner_->IsRunningOnCommitSequence()); | 305 DCHECK(task_runner_->IsRunningOnCommitSequence()); |
265 DCHECK(in_flight_commit_batch_.get()); | 306 DCHECK(in_flight_commit_batch_.get()); |
266 bool success = backing_->CommitChanges( | 307 bool success = GetBacking()->CommitChanges( |
308 namespace_id_, origin_, | |
267 in_flight_commit_batch_->clear_all_first, | 309 in_flight_commit_batch_->clear_all_first, |
268 in_flight_commit_batch_->changed_values); | 310 in_flight_commit_batch_->changed_values); |
269 DCHECK(success); // TODO(michaeln): what if it fails? | 311 DCHECK(success); // TODO(michaeln): what if it fails? |
270 task_runner_->PostTask( | 312 task_runner_->PostTask( |
271 FROM_HERE, | 313 FROM_HERE, |
272 base::Bind(&DomStorageArea::OnCommitComplete, this)); | 314 base::Bind(&DomStorageArea::OnCommitComplete, this)); |
273 } | 315 } |
274 | 316 |
275 void DomStorageArea::OnCommitComplete() { | 317 void DomStorageArea::OnCommitComplete() { |
276 // We're back on the primary sequence in this method. | 318 // We're back on the primary sequence in this method. |
277 DCHECK(task_runner_->IsRunningOnPrimarySequence()); | 319 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
278 if (is_shutdown_) | 320 if (is_shutdown_) |
279 return; | 321 return; |
280 in_flight_commit_batch_.reset(); | 322 in_flight_commit_batch_.reset(); |
281 if (commit_batch_.get()) { | 323 if (commit_batch_.get()) { |
282 // More changes have accrued, restart the timer. | 324 // More changes have accrued, restart the timer. |
283 task_runner_->PostDelayedTask( | 325 task_runner_->PostDelayedTask( |
284 FROM_HERE, | 326 FROM_HERE, |
285 base::Bind(&DomStorageArea::OnCommitTimer, this), | 327 base::Bind(&DomStorageArea::OnCommitTimer, this), |
286 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); | 328 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); |
287 } | 329 } |
288 } | 330 } |
289 | 331 |
290 void DomStorageArea::ShutdownInCommitSequence() { | 332 void DomStorageArea::ShutdownInCommitSequence() { |
291 // This method executes on the commit sequence. | 333 // This method executes on the commit sequence. |
292 DCHECK(task_runner_->IsRunningOnCommitSequence()); | 334 DCHECK(task_runner_->IsRunningOnCommitSequence()); |
293 DCHECK(backing_.get()); | 335 DCHECK(GetBacking()); |
294 if (commit_batch_.get()) { | 336 if (commit_batch_.get()) { |
295 // Commit any changes that accrued prior to the timer firing. | 337 // Commit any changes that accrued prior to the timer firing. |
296 bool success = backing_->CommitChanges( | 338 bool success = GetBacking()->CommitChanges( |
339 namespace_id_, origin_, | |
297 commit_batch_->clear_all_first, | 340 commit_batch_->clear_all_first, |
298 commit_batch_->changed_values); | 341 commit_batch_->changed_values); |
299 DCHECK(success); | 342 DCHECK(success); |
300 } | 343 } |
301 commit_batch_.reset(); | 344 commit_batch_.reset(); |
302 in_flight_commit_batch_.reset(); | 345 in_flight_commit_batch_.reset(); |
303 backing_.reset(); | 346 backing_.reset(); |
347 session_storage_backing_ = NULL; | |
348 } | |
349 | |
350 DomStorageDatabase* DomStorageArea::GetBacking() const { | |
351 DCHECK(!backing_.get() || !session_storage_backing_.get()); | |
352 if (backing_.get()) | |
353 return backing_.get(); | |
354 return session_storage_backing_.get(); | |
304 } | 355 } |
305 | 356 |
306 } // namespace dom_storage | 357 } // namespace dom_storage |
OLD | NEW |