1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/src/storage/DOMStorageIPC.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,734 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "DOMStorageIPC.h" 1.10 + 1.11 +#include "DOMStorageManager.h" 1.12 + 1.13 +#include "mozilla/dom/ContentChild.h" 1.14 +#include "mozilla/dom/ContentParent.h" 1.15 +#include "mozilla/unused.h" 1.16 +#include "nsIDiskSpaceWatcher.h" 1.17 +#include "nsThreadUtils.h" 1.18 + 1.19 +namespace mozilla { 1.20 +namespace dom { 1.21 + 1.22 +// ---------------------------------------------------------------------------- 1.23 +// Child 1.24 +// ---------------------------------------------------------------------------- 1.25 + 1.26 +NS_IMPL_ADDREF(DOMStorageDBChild) 1.27 + 1.28 +NS_IMETHODIMP_(MozExternalRefCountType) DOMStorageDBChild::Release(void) 1.29 +{ 1.30 + NS_PRECONDITION(0 != mRefCnt, "dup release"); 1.31 + nsrefcnt count = --mRefCnt; 1.32 + NS_LOG_RELEASE(this, count, "DOMStorageDBChild"); 1.33 + if (count == 1 && mIPCOpen) { 1.34 + Send__delete__(this); 1.35 + return 0; 1.36 + } 1.37 + if (count == 0) { 1.38 + mRefCnt = 1; 1.39 + delete this; 1.40 + return 0; 1.41 + } 1.42 + return count; 1.43 +} 1.44 + 1.45 +void 1.46 +DOMStorageDBChild::AddIPDLReference() 1.47 +{ 1.48 + NS_ABORT_IF_FALSE(!mIPCOpen, "Attempting to retain multiple IPDL references"); 1.49 + mIPCOpen = true; 1.50 + AddRef(); 1.51 +} 1.52 + 1.53 +void 1.54 +DOMStorageDBChild::ReleaseIPDLReference() 1.55 +{ 1.56 + NS_ABORT_IF_FALSE(mIPCOpen, "Attempting to release non-existent IPDL reference"); 1.57 + mIPCOpen = false; 1.58 + Release(); 1.59 +} 1.60 + 1.61 +DOMStorageDBChild::DOMStorageDBChild(DOMLocalStorageManager* aManager) 1.62 + : mManager(aManager) 1.63 + , mStatus(NS_OK) 1.64 + , mIPCOpen(false) 1.65 +{ 1.66 +} 1.67 + 1.68 +DOMStorageDBChild::~DOMStorageDBChild() 1.69 +{ 1.70 +} 1.71 + 1.72 +nsTHashtable<nsCStringHashKey>& 1.73 +DOMStorageDBChild::ScopesHavingData() 1.74 +{ 1.75 + if (!mScopesHavingData) { 1.76 + mScopesHavingData = new nsTHashtable<nsCStringHashKey>; 1.77 + } 1.78 + 1.79 + return *mScopesHavingData; 1.80 +} 1.81 + 1.82 +nsresult 1.83 +DOMStorageDBChild::Init() 1.84 +{ 1.85 + ContentChild* child = ContentChild::GetSingleton(); 1.86 + AddIPDLReference(); 1.87 + child->SendPStorageConstructor(this); 1.88 + return NS_OK; 1.89 +} 1.90 + 1.91 +nsresult 1.92 +DOMStorageDBChild::Shutdown() 1.93 +{ 1.94 + // There is nothing to do here, IPC will release automatically and 1.95 + // the actual thread running on the parent process will also stop 1.96 + // automatically in profile-before-change topic observer. 1.97 + return NS_OK; 1.98 +} 1.99 + 1.100 +void 1.101 +DOMStorageDBChild::AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority) 1.102 +{ 1.103 + if (mIPCOpen) { 1.104 + // Adding ref to cache for the time of preload. This ensures a reference to 1.105 + // to the cache and that all keys will load into this cache object. 1.106 + mLoadingCaches.PutEntry(aCache); 1.107 + SendAsyncPreload(aCache->Scope(), aPriority); 1.108 + } else { 1.109 + // No IPC, no love. But the LoadDone call is expected. 1.110 + aCache->LoadDone(NS_ERROR_UNEXPECTED); 1.111 + } 1.112 +} 1.113 + 1.114 +void 1.115 +DOMStorageDBChild::AsyncGetUsage(DOMStorageUsageBridge* aUsage) 1.116 +{ 1.117 + if (mIPCOpen) { 1.118 + SendAsyncGetUsage(aUsage->Scope()); 1.119 + } 1.120 +} 1.121 + 1.122 +void 1.123 +DOMStorageDBChild::SyncPreload(DOMStorageCacheBridge* aCache, bool aForceSync) 1.124 +{ 1.125 + if (NS_FAILED(mStatus)) { 1.126 + aCache->LoadDone(mStatus); 1.127 + return; 1.128 + } 1.129 + 1.130 + if (!mIPCOpen) { 1.131 + aCache->LoadDone(NS_ERROR_UNEXPECTED); 1.132 + return; 1.133 + } 1.134 + 1.135 + // There is no way to put the child process to a wait state to receive all 1.136 + // incoming async responses from the parent, hence we have to do a sync preload 1.137 + // instead. We are smart though, we only demand keys that are left to load in 1.138 + // case the async preload has already loaded some keys. 1.139 + InfallibleTArray<nsString> keys, values; 1.140 + nsresult rv; 1.141 + SendPreload(aCache->Scope(), aCache->LoadedCount(), &keys, &values, &rv); 1.142 + 1.143 + for (uint32_t i = 0; i < keys.Length(); ++i) { 1.144 + aCache->LoadItem(keys[i], values[i]); 1.145 + } 1.146 + 1.147 + aCache->LoadDone(rv); 1.148 +} 1.149 + 1.150 +nsresult 1.151 +DOMStorageDBChild::AsyncAddItem(DOMStorageCacheBridge* aCache, 1.152 + const nsAString& aKey, 1.153 + const nsAString& aValue) 1.154 +{ 1.155 + if (NS_FAILED(mStatus) || !mIPCOpen) { 1.156 + return mStatus; 1.157 + } 1.158 + 1.159 + SendAsyncAddItem(aCache->Scope(), nsString(aKey), nsString(aValue)); 1.160 + ScopesHavingData().PutEntry(aCache->Scope()); 1.161 + return NS_OK; 1.162 +} 1.163 + 1.164 +nsresult 1.165 +DOMStorageDBChild::AsyncUpdateItem(DOMStorageCacheBridge* aCache, 1.166 + const nsAString& aKey, 1.167 + const nsAString& aValue) 1.168 +{ 1.169 + if (NS_FAILED(mStatus) || !mIPCOpen) { 1.170 + return mStatus; 1.171 + } 1.172 + 1.173 + SendAsyncUpdateItem(aCache->Scope(), nsString(aKey), nsString(aValue)); 1.174 + ScopesHavingData().PutEntry(aCache->Scope()); 1.175 + return NS_OK; 1.176 +} 1.177 + 1.178 +nsresult 1.179 +DOMStorageDBChild::AsyncRemoveItem(DOMStorageCacheBridge* aCache, 1.180 + const nsAString& aKey) 1.181 +{ 1.182 + if (NS_FAILED(mStatus) || !mIPCOpen) { 1.183 + return mStatus; 1.184 + } 1.185 + 1.186 + SendAsyncRemoveItem(aCache->Scope(), nsString(aKey)); 1.187 + return NS_OK; 1.188 +} 1.189 + 1.190 +nsresult 1.191 +DOMStorageDBChild::AsyncClear(DOMStorageCacheBridge* aCache) 1.192 +{ 1.193 + if (NS_FAILED(mStatus) || !mIPCOpen) { 1.194 + return mStatus; 1.195 + } 1.196 + 1.197 + SendAsyncClear(aCache->Scope()); 1.198 + ScopesHavingData().RemoveEntry(aCache->Scope()); 1.199 + return NS_OK; 1.200 +} 1.201 + 1.202 +bool 1.203 +DOMStorageDBChild::ShouldPreloadScope(const nsACString& aScope) 1.204 +{ 1.205 + // Return true if we didn't receive the aScope list yet. 1.206 + // I tend to rather preserve a bit of early-after-start performance 1.207 + // then a bit of memory here. 1.208 + return !mScopesHavingData || mScopesHavingData->Contains(aScope); 1.209 +} 1.210 + 1.211 +bool 1.212 +DOMStorageDBChild::RecvObserve(const nsCString& aTopic, 1.213 + const nsCString& aScopePrefix) 1.214 +{ 1.215 + DOMStorageObserver::Self()->Notify(aTopic.get(), aScopePrefix); 1.216 + return true; 1.217 +} 1.218 + 1.219 +bool 1.220 +DOMStorageDBChild::RecvScopesHavingData(const InfallibleTArray<nsCString>& aScopes) 1.221 +{ 1.222 + for (uint32_t i = 0; i < aScopes.Length(); ++i) { 1.223 + ScopesHavingData().PutEntry(aScopes[i]); 1.224 + } 1.225 + 1.226 + return true; 1.227 +} 1.228 + 1.229 +bool 1.230 +DOMStorageDBChild::RecvLoadItem(const nsCString& aScope, 1.231 + const nsString& aKey, 1.232 + const nsString& aValue) 1.233 +{ 1.234 + DOMStorageCache* aCache = mManager->GetCache(aScope); 1.235 + if (aCache) { 1.236 + aCache->LoadItem(aKey, aValue); 1.237 + } 1.238 + 1.239 + return true; 1.240 +} 1.241 + 1.242 +bool 1.243 +DOMStorageDBChild::RecvLoadDone(const nsCString& aScope, const nsresult& aRv) 1.244 +{ 1.245 + DOMStorageCache* aCache = mManager->GetCache(aScope); 1.246 + if (aCache) { 1.247 + aCache->LoadDone(aRv); 1.248 + 1.249 + // Just drop reference to this cache now since the load is done. 1.250 + mLoadingCaches.RemoveEntry(static_cast<DOMStorageCacheBridge*>(aCache)); 1.251 + } 1.252 + 1.253 + return true; 1.254 +} 1.255 + 1.256 +bool 1.257 +DOMStorageDBChild::RecvLoadUsage(const nsCString& aScope, const int64_t& aUsage) 1.258 +{ 1.259 + nsRefPtr<DOMStorageUsageBridge> scopeUsage = mManager->GetScopeUsage(aScope); 1.260 + scopeUsage->LoadUsage(aUsage); 1.261 + return true; 1.262 +} 1.263 + 1.264 +bool 1.265 +DOMStorageDBChild::RecvError(const nsresult& aRv) 1.266 +{ 1.267 + mStatus = aRv; 1.268 + return true; 1.269 +} 1.270 + 1.271 +// ---------------------------------------------------------------------------- 1.272 +// Parent 1.273 +// ---------------------------------------------------------------------------- 1.274 + 1.275 +NS_IMPL_ADDREF(DOMStorageDBParent) 1.276 +NS_IMPL_RELEASE(DOMStorageDBParent) 1.277 + 1.278 +void 1.279 +DOMStorageDBParent::AddIPDLReference() 1.280 +{ 1.281 + NS_ABORT_IF_FALSE(!mIPCOpen, "Attempting to retain multiple IPDL references"); 1.282 + mIPCOpen = true; 1.283 + AddRef(); 1.284 +} 1.285 + 1.286 +void 1.287 +DOMStorageDBParent::ReleaseIPDLReference() 1.288 +{ 1.289 + NS_ABORT_IF_FALSE(mIPCOpen, "Attempting to release non-existent IPDL reference"); 1.290 + mIPCOpen = false; 1.291 + Release(); 1.292 +} 1.293 + 1.294 +namespace { // anon 1.295 + 1.296 +class SendInitialChildDataRunnable : public nsRunnable 1.297 +{ 1.298 +public: 1.299 + SendInitialChildDataRunnable(DOMStorageDBParent* aParent) 1.300 + : mParent(aParent) 1.301 + {} 1.302 + 1.303 +private: 1.304 + NS_IMETHOD Run() 1.305 + { 1.306 + if (!mParent->IPCOpen()) { 1.307 + return NS_OK; 1.308 + } 1.309 + 1.310 + DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); 1.311 + if (db) { 1.312 + InfallibleTArray<nsCString> scopes; 1.313 + db->GetScopesHavingData(&scopes); 1.314 + mozilla::unused << mParent->SendScopesHavingData(scopes); 1.315 + } 1.316 + 1.317 + // We need to check if the device is in a low disk space situation, so 1.318 + // we can forbid in that case any write in localStorage. 1.319 + nsCOMPtr<nsIDiskSpaceWatcher> diskSpaceWatcher = 1.320 + do_GetService("@mozilla.org/toolkit/disk-space-watcher;1"); 1.321 + if (!diskSpaceWatcher) { 1.322 + NS_WARNING("Could not get disk information from DiskSpaceWatcher"); 1.323 + return NS_OK; 1.324 + } 1.325 + bool lowDiskSpace = false; 1.326 + diskSpaceWatcher->GetIsDiskFull(&lowDiskSpace); 1.327 + if (lowDiskSpace) { 1.328 + mozilla::unused << mParent->SendObserve( 1.329 + nsDependentCString("low-disk-space"), EmptyCString()); 1.330 + } 1.331 + 1.332 + return NS_OK; 1.333 + } 1.334 + 1.335 + nsRefPtr<DOMStorageDBParent> mParent; 1.336 +}; 1.337 + 1.338 +} // anon 1.339 + 1.340 +DOMStorageDBParent::DOMStorageDBParent() 1.341 +: mIPCOpen(false) 1.342 +{ 1.343 + DOMStorageObserver* observer = DOMStorageObserver::Self(); 1.344 + if (observer) { 1.345 + observer->AddSink(this); 1.346 + } 1.347 + 1.348 + // We are always open by IPC only 1.349 + AddIPDLReference(); 1.350 + 1.351 + // Cannot send directly from here since the channel 1.352 + // is not completely built at this moment. 1.353 + nsRefPtr<SendInitialChildDataRunnable> r = 1.354 + new SendInitialChildDataRunnable(this); 1.355 + NS_DispatchToCurrentThread(r); 1.356 +} 1.357 + 1.358 +DOMStorageDBParent::~DOMStorageDBParent() 1.359 +{ 1.360 + DOMStorageObserver* observer = DOMStorageObserver::Self(); 1.361 + if (observer) { 1.362 + observer->RemoveSink(this); 1.363 + } 1.364 +} 1.365 + 1.366 +mozilla::ipc::IProtocol* 1.367 +DOMStorageDBParent::CloneProtocol(Channel* aChannel, 1.368 + mozilla::ipc::ProtocolCloneContext* aCtx) 1.369 +{ 1.370 + ContentParent* contentParent = aCtx->GetContentParent(); 1.371 + nsAutoPtr<PStorageParent> actor(contentParent->AllocPStorageParent()); 1.372 + if (!actor || !contentParent->RecvPStorageConstructor(actor)) { 1.373 + return nullptr; 1.374 + } 1.375 + return actor.forget(); 1.376 +} 1.377 + 1.378 +DOMStorageDBParent::CacheParentBridge* 1.379 +DOMStorageDBParent::NewCache(const nsACString& aScope) 1.380 +{ 1.381 + return new CacheParentBridge(this, aScope); 1.382 +} 1.383 + 1.384 +bool 1.385 +DOMStorageDBParent::RecvAsyncPreload(const nsCString& aScope, const bool& aPriority) 1.386 +{ 1.387 + DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); 1.388 + if (!db) { 1.389 + return false; 1.390 + } 1.391 + 1.392 + db->AsyncPreload(NewCache(aScope), aPriority); 1.393 + return true; 1.394 +} 1.395 + 1.396 +bool 1.397 +DOMStorageDBParent::RecvAsyncGetUsage(const nsCString& aScope) 1.398 +{ 1.399 + DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); 1.400 + if (!db) { 1.401 + return false; 1.402 + } 1.403 + 1.404 + // The object releases it self in LoadUsage method 1.405 + nsRefPtr<UsageParentBridge> usage = new UsageParentBridge(this, aScope); 1.406 + db->AsyncGetUsage(usage); 1.407 + return true; 1.408 +} 1.409 + 1.410 +namespace { // anon 1.411 + 1.412 +// We need another implementation of DOMStorageCacheBridge to do 1.413 +// synchronous IPC preload. This class just receives Load* notifications 1.414 +// and fills the returning arguments of RecvPreload with the database 1.415 +// values for us. 1.416 +class SyncLoadCacheHelper : public DOMStorageCacheBridge 1.417 +{ 1.418 +public: 1.419 + SyncLoadCacheHelper(const nsCString& aScope, 1.420 + uint32_t aAlreadyLoadedCount, 1.421 + InfallibleTArray<nsString>* aKeys, 1.422 + InfallibleTArray<nsString>* aValues, 1.423 + nsresult* rv) 1.424 + : mMonitor("DOM Storage SyncLoad IPC") 1.425 + , mScope(aScope) 1.426 + , mKeys(aKeys) 1.427 + , mValues(aValues) 1.428 + , mRv(rv) 1.429 + , mLoaded(false) 1.430 + , mLoadedCount(aAlreadyLoadedCount) 1.431 + { 1.432 + // Precaution 1.433 + *mRv = NS_ERROR_UNEXPECTED; 1.434 + } 1.435 + 1.436 + virtual const nsCString& Scope() const { return mScope; } 1.437 + virtual bool Loaded() { return mLoaded; } 1.438 + virtual uint32_t LoadedCount() { return mLoadedCount; } 1.439 + virtual bool LoadItem(const nsAString& aKey, const nsString& aValue) 1.440 + { 1.441 + // Called on the aCache background thread 1.442 + if (mLoaded) { 1.443 + return false; 1.444 + } 1.445 + 1.446 + ++mLoadedCount; 1.447 + mKeys->AppendElement(aKey); 1.448 + mValues->AppendElement(aValue); 1.449 + return true; 1.450 + } 1.451 + 1.452 + virtual void LoadDone(nsresult aRv) 1.453 + { 1.454 + // Called on the aCache background thread 1.455 + MonitorAutoLock monitor(mMonitor); 1.456 + mLoaded = true; 1.457 + *mRv = aRv; 1.458 + monitor.Notify(); 1.459 + } 1.460 + 1.461 + virtual void LoadWait() 1.462 + { 1.463 + // Called on the main thread, exits after LoadDone() call 1.464 + MonitorAutoLock monitor(mMonitor); 1.465 + while (!mLoaded) { 1.466 + monitor.Wait(); 1.467 + } 1.468 + } 1.469 + 1.470 +private: 1.471 + Monitor mMonitor; 1.472 + nsCString mScope; 1.473 + InfallibleTArray<nsString>* mKeys; 1.474 + InfallibleTArray<nsString>* mValues; 1.475 + nsresult* mRv; 1.476 + bool mLoaded; 1.477 + uint32_t mLoadedCount; 1.478 +}; 1.479 + 1.480 +} // anon 1.481 + 1.482 +bool 1.483 +DOMStorageDBParent::RecvPreload(const nsCString& aScope, 1.484 + const uint32_t& aAlreadyLoadedCount, 1.485 + InfallibleTArray<nsString>* aKeys, 1.486 + InfallibleTArray<nsString>* aValues, 1.487 + nsresult* aRv) 1.488 +{ 1.489 + DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); 1.490 + if (!db) { 1.491 + return false; 1.492 + } 1.493 + 1.494 + nsRefPtr<SyncLoadCacheHelper> cache( 1.495 + new SyncLoadCacheHelper(aScope, aAlreadyLoadedCount, aKeys, aValues, aRv)); 1.496 + 1.497 + db->SyncPreload(cache, true); 1.498 + return true; 1.499 +} 1.500 + 1.501 +bool 1.502 +DOMStorageDBParent::RecvAsyncAddItem(const nsCString& aScope, 1.503 + const nsString& aKey, 1.504 + const nsString& aValue) 1.505 +{ 1.506 + DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); 1.507 + if (!db) { 1.508 + return false; 1.509 + } 1.510 + 1.511 + nsresult rv = db->AsyncAddItem(NewCache(aScope), aKey, aValue); 1.512 + if (NS_FAILED(rv) && mIPCOpen) { 1.513 + mozilla::unused << SendError(rv); 1.514 + } 1.515 + 1.516 + return true; 1.517 +} 1.518 + 1.519 +bool 1.520 +DOMStorageDBParent::RecvAsyncUpdateItem(const nsCString& aScope, 1.521 + const nsString& aKey, 1.522 + const nsString& aValue) 1.523 +{ 1.524 + DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); 1.525 + if (!db) { 1.526 + return false; 1.527 + } 1.528 + 1.529 + nsresult rv = db->AsyncUpdateItem(NewCache(aScope), aKey, aValue); 1.530 + if (NS_FAILED(rv) && mIPCOpen) { 1.531 + mozilla::unused << SendError(rv); 1.532 + } 1.533 + 1.534 + return true; 1.535 +} 1.536 + 1.537 +bool 1.538 +DOMStorageDBParent::RecvAsyncRemoveItem(const nsCString& aScope, 1.539 + const nsString& aKey) 1.540 +{ 1.541 + DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); 1.542 + if (!db) { 1.543 + return false; 1.544 + } 1.545 + 1.546 + nsresult rv = db->AsyncRemoveItem(NewCache(aScope), aKey); 1.547 + if (NS_FAILED(rv) && mIPCOpen) { 1.548 + mozilla::unused << SendError(rv); 1.549 + } 1.550 + 1.551 + return true; 1.552 +} 1.553 + 1.554 +bool 1.555 +DOMStorageDBParent::RecvAsyncClear(const nsCString& aScope) 1.556 +{ 1.557 + DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); 1.558 + if (!db) { 1.559 + return false; 1.560 + } 1.561 + 1.562 + nsresult rv = db->AsyncClear(NewCache(aScope)); 1.563 + if (NS_FAILED(rv) && mIPCOpen) { 1.564 + mozilla::unused << SendError(rv); 1.565 + } 1.566 + 1.567 + return true; 1.568 +} 1.569 + 1.570 +bool 1.571 +DOMStorageDBParent::RecvAsyncFlush() 1.572 +{ 1.573 + DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); 1.574 + if (!db) { 1.575 + return false; 1.576 + } 1.577 + 1.578 + db->AsyncFlush(); 1.579 + return true; 1.580 +} 1.581 + 1.582 +// DOMStorageObserverSink 1.583 + 1.584 +nsresult 1.585 +DOMStorageDBParent::Observe(const char* aTopic, 1.586 + const nsACString& aScopePrefix) 1.587 +{ 1.588 + if (mIPCOpen) { 1.589 + mozilla::unused << SendObserve(nsDependentCString(aTopic), 1.590 + nsCString(aScopePrefix)); 1.591 + } 1.592 + 1.593 + return NS_OK; 1.594 +} 1.595 + 1.596 +namespace { // anon 1.597 + 1.598 +// Results must be sent back on the main thread 1.599 +class LoadRunnable : public nsRunnable 1.600 +{ 1.601 +public: 1.602 + enum TaskType { 1.603 + loadItem, 1.604 + loadDone 1.605 + }; 1.606 + 1.607 + LoadRunnable(DOMStorageDBParent* aParent, 1.608 + TaskType aType, 1.609 + const nsACString& aScope, 1.610 + const nsAString& aKey = EmptyString(), 1.611 + const nsAString& aValue = EmptyString()) 1.612 + : mParent(aParent) 1.613 + , mType(aType) 1.614 + , mScope(aScope) 1.615 + , mKey(aKey) 1.616 + , mValue(aValue) 1.617 + { } 1.618 + 1.619 + LoadRunnable(DOMStorageDBParent* aParent, 1.620 + TaskType aType, 1.621 + const nsACString& aScope, 1.622 + nsresult aRv) 1.623 + : mParent(aParent) 1.624 + , mType(aType) 1.625 + , mScope(aScope) 1.626 + , mRv(aRv) 1.627 + { } 1.628 + 1.629 +private: 1.630 + nsRefPtr<DOMStorageDBParent> mParent; 1.631 + TaskType mType; 1.632 + nsCString mScope; 1.633 + nsString mKey; 1.634 + nsString mValue; 1.635 + nsresult mRv; 1.636 + 1.637 + NS_IMETHOD Run() 1.638 + { 1.639 + if (!mParent->IPCOpen()) { 1.640 + return NS_OK; 1.641 + } 1.642 + 1.643 + switch (mType) 1.644 + { 1.645 + case loadItem: 1.646 + mozilla::unused << mParent->SendLoadItem(mScope, mKey, mValue); 1.647 + break; 1.648 + case loadDone: 1.649 + mozilla::unused << mParent->SendLoadDone(mScope, mRv); 1.650 + break; 1.651 + } 1.652 + 1.653 + return NS_OK; 1.654 + } 1.655 +}; 1.656 + 1.657 +} // anon 1.658 + 1.659 +// DOMStorageDBParent::CacheParentBridge 1.660 + 1.661 +bool 1.662 +DOMStorageDBParent::CacheParentBridge::LoadItem(const nsAString& aKey, const nsString& aValue) 1.663 +{ 1.664 + if (mLoaded) { 1.665 + return false; 1.666 + } 1.667 + 1.668 + ++mLoadedCount; 1.669 + 1.670 + nsRefPtr<LoadRunnable> r = 1.671 + new LoadRunnable(mParent, LoadRunnable::loadItem, mScope, aKey, aValue); 1.672 + NS_DispatchToMainThread(r); 1.673 + return true; 1.674 +} 1.675 + 1.676 +void 1.677 +DOMStorageDBParent::CacheParentBridge::LoadDone(nsresult aRv) 1.678 +{ 1.679 + // Prevent send of duplicate LoadDone. 1.680 + if (mLoaded) { 1.681 + return; 1.682 + } 1.683 + 1.684 + mLoaded = true; 1.685 + 1.686 + nsRefPtr<LoadRunnable> r = 1.687 + new LoadRunnable(mParent, LoadRunnable::loadDone, mScope, aRv); 1.688 + NS_DispatchToMainThread(r); 1.689 +} 1.690 + 1.691 +void 1.692 +DOMStorageDBParent::CacheParentBridge::LoadWait() 1.693 +{ 1.694 + // Should never be called on this implementation 1.695 + MOZ_ASSERT(false); 1.696 +} 1.697 + 1.698 +// DOMStorageDBParent::UsageParentBridge 1.699 + 1.700 +namespace { // anon 1.701 + 1.702 +class UsageRunnable : public nsRunnable 1.703 +{ 1.704 +public: 1.705 + UsageRunnable(DOMStorageDBParent* aParent, const nsACString& aScope, const int64_t& aUsage) 1.706 + : mParent(aParent) 1.707 + , mScope(aScope) 1.708 + , mUsage(aUsage) 1.709 + {} 1.710 + 1.711 +private: 1.712 + NS_IMETHOD Run() 1.713 + { 1.714 + if (!mParent->IPCOpen()) { 1.715 + return NS_OK; 1.716 + } 1.717 + 1.718 + mozilla::unused << mParent->SendLoadUsage(mScope, mUsage); 1.719 + return NS_OK; 1.720 + } 1.721 + 1.722 + nsRefPtr<DOMStorageDBParent> mParent; 1.723 + nsCString mScope; 1.724 + int64_t mUsage; 1.725 +}; 1.726 + 1.727 +} // anon 1.728 + 1.729 +void 1.730 +DOMStorageDBParent::UsageParentBridge::LoadUsage(const int64_t aUsage) 1.731 +{ 1.732 + nsRefPtr<UsageRunnable> r = new UsageRunnable(mParent, mScope, aUsage); 1.733 + NS_DispatchToMainThread(r); 1.734 +} 1.735 + 1.736 +} // ::dom 1.737 +} // ::mozilla