|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "DOMStorageIPC.h" |
|
7 |
|
8 #include "DOMStorageManager.h" |
|
9 |
|
10 #include "mozilla/dom/ContentChild.h" |
|
11 #include "mozilla/dom/ContentParent.h" |
|
12 #include "mozilla/unused.h" |
|
13 #include "nsIDiskSpaceWatcher.h" |
|
14 #include "nsThreadUtils.h" |
|
15 |
|
16 namespace mozilla { |
|
17 namespace dom { |
|
18 |
|
19 // ---------------------------------------------------------------------------- |
|
20 // Child |
|
21 // ---------------------------------------------------------------------------- |
|
22 |
|
23 NS_IMPL_ADDREF(DOMStorageDBChild) |
|
24 |
|
25 NS_IMETHODIMP_(MozExternalRefCountType) DOMStorageDBChild::Release(void) |
|
26 { |
|
27 NS_PRECONDITION(0 != mRefCnt, "dup release"); |
|
28 nsrefcnt count = --mRefCnt; |
|
29 NS_LOG_RELEASE(this, count, "DOMStorageDBChild"); |
|
30 if (count == 1 && mIPCOpen) { |
|
31 Send__delete__(this); |
|
32 return 0; |
|
33 } |
|
34 if (count == 0) { |
|
35 mRefCnt = 1; |
|
36 delete this; |
|
37 return 0; |
|
38 } |
|
39 return count; |
|
40 } |
|
41 |
|
42 void |
|
43 DOMStorageDBChild::AddIPDLReference() |
|
44 { |
|
45 NS_ABORT_IF_FALSE(!mIPCOpen, "Attempting to retain multiple IPDL references"); |
|
46 mIPCOpen = true; |
|
47 AddRef(); |
|
48 } |
|
49 |
|
50 void |
|
51 DOMStorageDBChild::ReleaseIPDLReference() |
|
52 { |
|
53 NS_ABORT_IF_FALSE(mIPCOpen, "Attempting to release non-existent IPDL reference"); |
|
54 mIPCOpen = false; |
|
55 Release(); |
|
56 } |
|
57 |
|
58 DOMStorageDBChild::DOMStorageDBChild(DOMLocalStorageManager* aManager) |
|
59 : mManager(aManager) |
|
60 , mStatus(NS_OK) |
|
61 , mIPCOpen(false) |
|
62 { |
|
63 } |
|
64 |
|
65 DOMStorageDBChild::~DOMStorageDBChild() |
|
66 { |
|
67 } |
|
68 |
|
69 nsTHashtable<nsCStringHashKey>& |
|
70 DOMStorageDBChild::ScopesHavingData() |
|
71 { |
|
72 if (!mScopesHavingData) { |
|
73 mScopesHavingData = new nsTHashtable<nsCStringHashKey>; |
|
74 } |
|
75 |
|
76 return *mScopesHavingData; |
|
77 } |
|
78 |
|
79 nsresult |
|
80 DOMStorageDBChild::Init() |
|
81 { |
|
82 ContentChild* child = ContentChild::GetSingleton(); |
|
83 AddIPDLReference(); |
|
84 child->SendPStorageConstructor(this); |
|
85 return NS_OK; |
|
86 } |
|
87 |
|
88 nsresult |
|
89 DOMStorageDBChild::Shutdown() |
|
90 { |
|
91 // There is nothing to do here, IPC will release automatically and |
|
92 // the actual thread running on the parent process will also stop |
|
93 // automatically in profile-before-change topic observer. |
|
94 return NS_OK; |
|
95 } |
|
96 |
|
97 void |
|
98 DOMStorageDBChild::AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority) |
|
99 { |
|
100 if (mIPCOpen) { |
|
101 // Adding ref to cache for the time of preload. This ensures a reference to |
|
102 // to the cache and that all keys will load into this cache object. |
|
103 mLoadingCaches.PutEntry(aCache); |
|
104 SendAsyncPreload(aCache->Scope(), aPriority); |
|
105 } else { |
|
106 // No IPC, no love. But the LoadDone call is expected. |
|
107 aCache->LoadDone(NS_ERROR_UNEXPECTED); |
|
108 } |
|
109 } |
|
110 |
|
111 void |
|
112 DOMStorageDBChild::AsyncGetUsage(DOMStorageUsageBridge* aUsage) |
|
113 { |
|
114 if (mIPCOpen) { |
|
115 SendAsyncGetUsage(aUsage->Scope()); |
|
116 } |
|
117 } |
|
118 |
|
119 void |
|
120 DOMStorageDBChild::SyncPreload(DOMStorageCacheBridge* aCache, bool aForceSync) |
|
121 { |
|
122 if (NS_FAILED(mStatus)) { |
|
123 aCache->LoadDone(mStatus); |
|
124 return; |
|
125 } |
|
126 |
|
127 if (!mIPCOpen) { |
|
128 aCache->LoadDone(NS_ERROR_UNEXPECTED); |
|
129 return; |
|
130 } |
|
131 |
|
132 // There is no way to put the child process to a wait state to receive all |
|
133 // incoming async responses from the parent, hence we have to do a sync preload |
|
134 // instead. We are smart though, we only demand keys that are left to load in |
|
135 // case the async preload has already loaded some keys. |
|
136 InfallibleTArray<nsString> keys, values; |
|
137 nsresult rv; |
|
138 SendPreload(aCache->Scope(), aCache->LoadedCount(), &keys, &values, &rv); |
|
139 |
|
140 for (uint32_t i = 0; i < keys.Length(); ++i) { |
|
141 aCache->LoadItem(keys[i], values[i]); |
|
142 } |
|
143 |
|
144 aCache->LoadDone(rv); |
|
145 } |
|
146 |
|
147 nsresult |
|
148 DOMStorageDBChild::AsyncAddItem(DOMStorageCacheBridge* aCache, |
|
149 const nsAString& aKey, |
|
150 const nsAString& aValue) |
|
151 { |
|
152 if (NS_FAILED(mStatus) || !mIPCOpen) { |
|
153 return mStatus; |
|
154 } |
|
155 |
|
156 SendAsyncAddItem(aCache->Scope(), nsString(aKey), nsString(aValue)); |
|
157 ScopesHavingData().PutEntry(aCache->Scope()); |
|
158 return NS_OK; |
|
159 } |
|
160 |
|
161 nsresult |
|
162 DOMStorageDBChild::AsyncUpdateItem(DOMStorageCacheBridge* aCache, |
|
163 const nsAString& aKey, |
|
164 const nsAString& aValue) |
|
165 { |
|
166 if (NS_FAILED(mStatus) || !mIPCOpen) { |
|
167 return mStatus; |
|
168 } |
|
169 |
|
170 SendAsyncUpdateItem(aCache->Scope(), nsString(aKey), nsString(aValue)); |
|
171 ScopesHavingData().PutEntry(aCache->Scope()); |
|
172 return NS_OK; |
|
173 } |
|
174 |
|
175 nsresult |
|
176 DOMStorageDBChild::AsyncRemoveItem(DOMStorageCacheBridge* aCache, |
|
177 const nsAString& aKey) |
|
178 { |
|
179 if (NS_FAILED(mStatus) || !mIPCOpen) { |
|
180 return mStatus; |
|
181 } |
|
182 |
|
183 SendAsyncRemoveItem(aCache->Scope(), nsString(aKey)); |
|
184 return NS_OK; |
|
185 } |
|
186 |
|
187 nsresult |
|
188 DOMStorageDBChild::AsyncClear(DOMStorageCacheBridge* aCache) |
|
189 { |
|
190 if (NS_FAILED(mStatus) || !mIPCOpen) { |
|
191 return mStatus; |
|
192 } |
|
193 |
|
194 SendAsyncClear(aCache->Scope()); |
|
195 ScopesHavingData().RemoveEntry(aCache->Scope()); |
|
196 return NS_OK; |
|
197 } |
|
198 |
|
199 bool |
|
200 DOMStorageDBChild::ShouldPreloadScope(const nsACString& aScope) |
|
201 { |
|
202 // Return true if we didn't receive the aScope list yet. |
|
203 // I tend to rather preserve a bit of early-after-start performance |
|
204 // then a bit of memory here. |
|
205 return !mScopesHavingData || mScopesHavingData->Contains(aScope); |
|
206 } |
|
207 |
|
208 bool |
|
209 DOMStorageDBChild::RecvObserve(const nsCString& aTopic, |
|
210 const nsCString& aScopePrefix) |
|
211 { |
|
212 DOMStorageObserver::Self()->Notify(aTopic.get(), aScopePrefix); |
|
213 return true; |
|
214 } |
|
215 |
|
216 bool |
|
217 DOMStorageDBChild::RecvScopesHavingData(const InfallibleTArray<nsCString>& aScopes) |
|
218 { |
|
219 for (uint32_t i = 0; i < aScopes.Length(); ++i) { |
|
220 ScopesHavingData().PutEntry(aScopes[i]); |
|
221 } |
|
222 |
|
223 return true; |
|
224 } |
|
225 |
|
226 bool |
|
227 DOMStorageDBChild::RecvLoadItem(const nsCString& aScope, |
|
228 const nsString& aKey, |
|
229 const nsString& aValue) |
|
230 { |
|
231 DOMStorageCache* aCache = mManager->GetCache(aScope); |
|
232 if (aCache) { |
|
233 aCache->LoadItem(aKey, aValue); |
|
234 } |
|
235 |
|
236 return true; |
|
237 } |
|
238 |
|
239 bool |
|
240 DOMStorageDBChild::RecvLoadDone(const nsCString& aScope, const nsresult& aRv) |
|
241 { |
|
242 DOMStorageCache* aCache = mManager->GetCache(aScope); |
|
243 if (aCache) { |
|
244 aCache->LoadDone(aRv); |
|
245 |
|
246 // Just drop reference to this cache now since the load is done. |
|
247 mLoadingCaches.RemoveEntry(static_cast<DOMStorageCacheBridge*>(aCache)); |
|
248 } |
|
249 |
|
250 return true; |
|
251 } |
|
252 |
|
253 bool |
|
254 DOMStorageDBChild::RecvLoadUsage(const nsCString& aScope, const int64_t& aUsage) |
|
255 { |
|
256 nsRefPtr<DOMStorageUsageBridge> scopeUsage = mManager->GetScopeUsage(aScope); |
|
257 scopeUsage->LoadUsage(aUsage); |
|
258 return true; |
|
259 } |
|
260 |
|
261 bool |
|
262 DOMStorageDBChild::RecvError(const nsresult& aRv) |
|
263 { |
|
264 mStatus = aRv; |
|
265 return true; |
|
266 } |
|
267 |
|
268 // ---------------------------------------------------------------------------- |
|
269 // Parent |
|
270 // ---------------------------------------------------------------------------- |
|
271 |
|
272 NS_IMPL_ADDREF(DOMStorageDBParent) |
|
273 NS_IMPL_RELEASE(DOMStorageDBParent) |
|
274 |
|
275 void |
|
276 DOMStorageDBParent::AddIPDLReference() |
|
277 { |
|
278 NS_ABORT_IF_FALSE(!mIPCOpen, "Attempting to retain multiple IPDL references"); |
|
279 mIPCOpen = true; |
|
280 AddRef(); |
|
281 } |
|
282 |
|
283 void |
|
284 DOMStorageDBParent::ReleaseIPDLReference() |
|
285 { |
|
286 NS_ABORT_IF_FALSE(mIPCOpen, "Attempting to release non-existent IPDL reference"); |
|
287 mIPCOpen = false; |
|
288 Release(); |
|
289 } |
|
290 |
|
291 namespace { // anon |
|
292 |
|
293 class SendInitialChildDataRunnable : public nsRunnable |
|
294 { |
|
295 public: |
|
296 SendInitialChildDataRunnable(DOMStorageDBParent* aParent) |
|
297 : mParent(aParent) |
|
298 {} |
|
299 |
|
300 private: |
|
301 NS_IMETHOD Run() |
|
302 { |
|
303 if (!mParent->IPCOpen()) { |
|
304 return NS_OK; |
|
305 } |
|
306 |
|
307 DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); |
|
308 if (db) { |
|
309 InfallibleTArray<nsCString> scopes; |
|
310 db->GetScopesHavingData(&scopes); |
|
311 mozilla::unused << mParent->SendScopesHavingData(scopes); |
|
312 } |
|
313 |
|
314 // We need to check if the device is in a low disk space situation, so |
|
315 // we can forbid in that case any write in localStorage. |
|
316 nsCOMPtr<nsIDiskSpaceWatcher> diskSpaceWatcher = |
|
317 do_GetService("@mozilla.org/toolkit/disk-space-watcher;1"); |
|
318 if (!diskSpaceWatcher) { |
|
319 NS_WARNING("Could not get disk information from DiskSpaceWatcher"); |
|
320 return NS_OK; |
|
321 } |
|
322 bool lowDiskSpace = false; |
|
323 diskSpaceWatcher->GetIsDiskFull(&lowDiskSpace); |
|
324 if (lowDiskSpace) { |
|
325 mozilla::unused << mParent->SendObserve( |
|
326 nsDependentCString("low-disk-space"), EmptyCString()); |
|
327 } |
|
328 |
|
329 return NS_OK; |
|
330 } |
|
331 |
|
332 nsRefPtr<DOMStorageDBParent> mParent; |
|
333 }; |
|
334 |
|
335 } // anon |
|
336 |
|
337 DOMStorageDBParent::DOMStorageDBParent() |
|
338 : mIPCOpen(false) |
|
339 { |
|
340 DOMStorageObserver* observer = DOMStorageObserver::Self(); |
|
341 if (observer) { |
|
342 observer->AddSink(this); |
|
343 } |
|
344 |
|
345 // We are always open by IPC only |
|
346 AddIPDLReference(); |
|
347 |
|
348 // Cannot send directly from here since the channel |
|
349 // is not completely built at this moment. |
|
350 nsRefPtr<SendInitialChildDataRunnable> r = |
|
351 new SendInitialChildDataRunnable(this); |
|
352 NS_DispatchToCurrentThread(r); |
|
353 } |
|
354 |
|
355 DOMStorageDBParent::~DOMStorageDBParent() |
|
356 { |
|
357 DOMStorageObserver* observer = DOMStorageObserver::Self(); |
|
358 if (observer) { |
|
359 observer->RemoveSink(this); |
|
360 } |
|
361 } |
|
362 |
|
363 mozilla::ipc::IProtocol* |
|
364 DOMStorageDBParent::CloneProtocol(Channel* aChannel, |
|
365 mozilla::ipc::ProtocolCloneContext* aCtx) |
|
366 { |
|
367 ContentParent* contentParent = aCtx->GetContentParent(); |
|
368 nsAutoPtr<PStorageParent> actor(contentParent->AllocPStorageParent()); |
|
369 if (!actor || !contentParent->RecvPStorageConstructor(actor)) { |
|
370 return nullptr; |
|
371 } |
|
372 return actor.forget(); |
|
373 } |
|
374 |
|
375 DOMStorageDBParent::CacheParentBridge* |
|
376 DOMStorageDBParent::NewCache(const nsACString& aScope) |
|
377 { |
|
378 return new CacheParentBridge(this, aScope); |
|
379 } |
|
380 |
|
381 bool |
|
382 DOMStorageDBParent::RecvAsyncPreload(const nsCString& aScope, const bool& aPriority) |
|
383 { |
|
384 DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); |
|
385 if (!db) { |
|
386 return false; |
|
387 } |
|
388 |
|
389 db->AsyncPreload(NewCache(aScope), aPriority); |
|
390 return true; |
|
391 } |
|
392 |
|
393 bool |
|
394 DOMStorageDBParent::RecvAsyncGetUsage(const nsCString& aScope) |
|
395 { |
|
396 DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); |
|
397 if (!db) { |
|
398 return false; |
|
399 } |
|
400 |
|
401 // The object releases it self in LoadUsage method |
|
402 nsRefPtr<UsageParentBridge> usage = new UsageParentBridge(this, aScope); |
|
403 db->AsyncGetUsage(usage); |
|
404 return true; |
|
405 } |
|
406 |
|
407 namespace { // anon |
|
408 |
|
409 // We need another implementation of DOMStorageCacheBridge to do |
|
410 // synchronous IPC preload. This class just receives Load* notifications |
|
411 // and fills the returning arguments of RecvPreload with the database |
|
412 // values for us. |
|
413 class SyncLoadCacheHelper : public DOMStorageCacheBridge |
|
414 { |
|
415 public: |
|
416 SyncLoadCacheHelper(const nsCString& aScope, |
|
417 uint32_t aAlreadyLoadedCount, |
|
418 InfallibleTArray<nsString>* aKeys, |
|
419 InfallibleTArray<nsString>* aValues, |
|
420 nsresult* rv) |
|
421 : mMonitor("DOM Storage SyncLoad IPC") |
|
422 , mScope(aScope) |
|
423 , mKeys(aKeys) |
|
424 , mValues(aValues) |
|
425 , mRv(rv) |
|
426 , mLoaded(false) |
|
427 , mLoadedCount(aAlreadyLoadedCount) |
|
428 { |
|
429 // Precaution |
|
430 *mRv = NS_ERROR_UNEXPECTED; |
|
431 } |
|
432 |
|
433 virtual const nsCString& Scope() const { return mScope; } |
|
434 virtual bool Loaded() { return mLoaded; } |
|
435 virtual uint32_t LoadedCount() { return mLoadedCount; } |
|
436 virtual bool LoadItem(const nsAString& aKey, const nsString& aValue) |
|
437 { |
|
438 // Called on the aCache background thread |
|
439 if (mLoaded) { |
|
440 return false; |
|
441 } |
|
442 |
|
443 ++mLoadedCount; |
|
444 mKeys->AppendElement(aKey); |
|
445 mValues->AppendElement(aValue); |
|
446 return true; |
|
447 } |
|
448 |
|
449 virtual void LoadDone(nsresult aRv) |
|
450 { |
|
451 // Called on the aCache background thread |
|
452 MonitorAutoLock monitor(mMonitor); |
|
453 mLoaded = true; |
|
454 *mRv = aRv; |
|
455 monitor.Notify(); |
|
456 } |
|
457 |
|
458 virtual void LoadWait() |
|
459 { |
|
460 // Called on the main thread, exits after LoadDone() call |
|
461 MonitorAutoLock monitor(mMonitor); |
|
462 while (!mLoaded) { |
|
463 monitor.Wait(); |
|
464 } |
|
465 } |
|
466 |
|
467 private: |
|
468 Monitor mMonitor; |
|
469 nsCString mScope; |
|
470 InfallibleTArray<nsString>* mKeys; |
|
471 InfallibleTArray<nsString>* mValues; |
|
472 nsresult* mRv; |
|
473 bool mLoaded; |
|
474 uint32_t mLoadedCount; |
|
475 }; |
|
476 |
|
477 } // anon |
|
478 |
|
479 bool |
|
480 DOMStorageDBParent::RecvPreload(const nsCString& aScope, |
|
481 const uint32_t& aAlreadyLoadedCount, |
|
482 InfallibleTArray<nsString>* aKeys, |
|
483 InfallibleTArray<nsString>* aValues, |
|
484 nsresult* aRv) |
|
485 { |
|
486 DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); |
|
487 if (!db) { |
|
488 return false; |
|
489 } |
|
490 |
|
491 nsRefPtr<SyncLoadCacheHelper> cache( |
|
492 new SyncLoadCacheHelper(aScope, aAlreadyLoadedCount, aKeys, aValues, aRv)); |
|
493 |
|
494 db->SyncPreload(cache, true); |
|
495 return true; |
|
496 } |
|
497 |
|
498 bool |
|
499 DOMStorageDBParent::RecvAsyncAddItem(const nsCString& aScope, |
|
500 const nsString& aKey, |
|
501 const nsString& aValue) |
|
502 { |
|
503 DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); |
|
504 if (!db) { |
|
505 return false; |
|
506 } |
|
507 |
|
508 nsresult rv = db->AsyncAddItem(NewCache(aScope), aKey, aValue); |
|
509 if (NS_FAILED(rv) && mIPCOpen) { |
|
510 mozilla::unused << SendError(rv); |
|
511 } |
|
512 |
|
513 return true; |
|
514 } |
|
515 |
|
516 bool |
|
517 DOMStorageDBParent::RecvAsyncUpdateItem(const nsCString& aScope, |
|
518 const nsString& aKey, |
|
519 const nsString& aValue) |
|
520 { |
|
521 DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); |
|
522 if (!db) { |
|
523 return false; |
|
524 } |
|
525 |
|
526 nsresult rv = db->AsyncUpdateItem(NewCache(aScope), aKey, aValue); |
|
527 if (NS_FAILED(rv) && mIPCOpen) { |
|
528 mozilla::unused << SendError(rv); |
|
529 } |
|
530 |
|
531 return true; |
|
532 } |
|
533 |
|
534 bool |
|
535 DOMStorageDBParent::RecvAsyncRemoveItem(const nsCString& aScope, |
|
536 const nsString& aKey) |
|
537 { |
|
538 DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); |
|
539 if (!db) { |
|
540 return false; |
|
541 } |
|
542 |
|
543 nsresult rv = db->AsyncRemoveItem(NewCache(aScope), aKey); |
|
544 if (NS_FAILED(rv) && mIPCOpen) { |
|
545 mozilla::unused << SendError(rv); |
|
546 } |
|
547 |
|
548 return true; |
|
549 } |
|
550 |
|
551 bool |
|
552 DOMStorageDBParent::RecvAsyncClear(const nsCString& aScope) |
|
553 { |
|
554 DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); |
|
555 if (!db) { |
|
556 return false; |
|
557 } |
|
558 |
|
559 nsresult rv = db->AsyncClear(NewCache(aScope)); |
|
560 if (NS_FAILED(rv) && mIPCOpen) { |
|
561 mozilla::unused << SendError(rv); |
|
562 } |
|
563 |
|
564 return true; |
|
565 } |
|
566 |
|
567 bool |
|
568 DOMStorageDBParent::RecvAsyncFlush() |
|
569 { |
|
570 DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); |
|
571 if (!db) { |
|
572 return false; |
|
573 } |
|
574 |
|
575 db->AsyncFlush(); |
|
576 return true; |
|
577 } |
|
578 |
|
579 // DOMStorageObserverSink |
|
580 |
|
581 nsresult |
|
582 DOMStorageDBParent::Observe(const char* aTopic, |
|
583 const nsACString& aScopePrefix) |
|
584 { |
|
585 if (mIPCOpen) { |
|
586 mozilla::unused << SendObserve(nsDependentCString(aTopic), |
|
587 nsCString(aScopePrefix)); |
|
588 } |
|
589 |
|
590 return NS_OK; |
|
591 } |
|
592 |
|
593 namespace { // anon |
|
594 |
|
595 // Results must be sent back on the main thread |
|
596 class LoadRunnable : public nsRunnable |
|
597 { |
|
598 public: |
|
599 enum TaskType { |
|
600 loadItem, |
|
601 loadDone |
|
602 }; |
|
603 |
|
604 LoadRunnable(DOMStorageDBParent* aParent, |
|
605 TaskType aType, |
|
606 const nsACString& aScope, |
|
607 const nsAString& aKey = EmptyString(), |
|
608 const nsAString& aValue = EmptyString()) |
|
609 : mParent(aParent) |
|
610 , mType(aType) |
|
611 , mScope(aScope) |
|
612 , mKey(aKey) |
|
613 , mValue(aValue) |
|
614 { } |
|
615 |
|
616 LoadRunnable(DOMStorageDBParent* aParent, |
|
617 TaskType aType, |
|
618 const nsACString& aScope, |
|
619 nsresult aRv) |
|
620 : mParent(aParent) |
|
621 , mType(aType) |
|
622 , mScope(aScope) |
|
623 , mRv(aRv) |
|
624 { } |
|
625 |
|
626 private: |
|
627 nsRefPtr<DOMStorageDBParent> mParent; |
|
628 TaskType mType; |
|
629 nsCString mScope; |
|
630 nsString mKey; |
|
631 nsString mValue; |
|
632 nsresult mRv; |
|
633 |
|
634 NS_IMETHOD Run() |
|
635 { |
|
636 if (!mParent->IPCOpen()) { |
|
637 return NS_OK; |
|
638 } |
|
639 |
|
640 switch (mType) |
|
641 { |
|
642 case loadItem: |
|
643 mozilla::unused << mParent->SendLoadItem(mScope, mKey, mValue); |
|
644 break; |
|
645 case loadDone: |
|
646 mozilla::unused << mParent->SendLoadDone(mScope, mRv); |
|
647 break; |
|
648 } |
|
649 |
|
650 return NS_OK; |
|
651 } |
|
652 }; |
|
653 |
|
654 } // anon |
|
655 |
|
656 // DOMStorageDBParent::CacheParentBridge |
|
657 |
|
658 bool |
|
659 DOMStorageDBParent::CacheParentBridge::LoadItem(const nsAString& aKey, const nsString& aValue) |
|
660 { |
|
661 if (mLoaded) { |
|
662 return false; |
|
663 } |
|
664 |
|
665 ++mLoadedCount; |
|
666 |
|
667 nsRefPtr<LoadRunnable> r = |
|
668 new LoadRunnable(mParent, LoadRunnable::loadItem, mScope, aKey, aValue); |
|
669 NS_DispatchToMainThread(r); |
|
670 return true; |
|
671 } |
|
672 |
|
673 void |
|
674 DOMStorageDBParent::CacheParentBridge::LoadDone(nsresult aRv) |
|
675 { |
|
676 // Prevent send of duplicate LoadDone. |
|
677 if (mLoaded) { |
|
678 return; |
|
679 } |
|
680 |
|
681 mLoaded = true; |
|
682 |
|
683 nsRefPtr<LoadRunnable> r = |
|
684 new LoadRunnable(mParent, LoadRunnable::loadDone, mScope, aRv); |
|
685 NS_DispatchToMainThread(r); |
|
686 } |
|
687 |
|
688 void |
|
689 DOMStorageDBParent::CacheParentBridge::LoadWait() |
|
690 { |
|
691 // Should never be called on this implementation |
|
692 MOZ_ASSERT(false); |
|
693 } |
|
694 |
|
695 // DOMStorageDBParent::UsageParentBridge |
|
696 |
|
697 namespace { // anon |
|
698 |
|
699 class UsageRunnable : public nsRunnable |
|
700 { |
|
701 public: |
|
702 UsageRunnable(DOMStorageDBParent* aParent, const nsACString& aScope, const int64_t& aUsage) |
|
703 : mParent(aParent) |
|
704 , mScope(aScope) |
|
705 , mUsage(aUsage) |
|
706 {} |
|
707 |
|
708 private: |
|
709 NS_IMETHOD Run() |
|
710 { |
|
711 if (!mParent->IPCOpen()) { |
|
712 return NS_OK; |
|
713 } |
|
714 |
|
715 mozilla::unused << mParent->SendLoadUsage(mScope, mUsage); |
|
716 return NS_OK; |
|
717 } |
|
718 |
|
719 nsRefPtr<DOMStorageDBParent> mParent; |
|
720 nsCString mScope; |
|
721 int64_t mUsage; |
|
722 }; |
|
723 |
|
724 } // anon |
|
725 |
|
726 void |
|
727 DOMStorageDBParent::UsageParentBridge::LoadUsage(const int64_t aUsage) |
|
728 { |
|
729 nsRefPtr<UsageRunnable> r = new UsageRunnable(mParent, mScope, aUsage); |
|
730 NS_DispatchToMainThread(r); |
|
731 } |
|
732 |
|
733 } // ::dom |
|
734 } // ::mozilla |