1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/cache2/OldWrappers.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1063 @@ 1.4 +// Stuff to link the old imp to the new api - will go away! 1.5 + 1.6 +#include "CacheLog.h" 1.7 +#include "OldWrappers.h" 1.8 +#include "CacheStorage.h" 1.9 +#include "CacheStorageService.h" 1.10 +#include "LoadContextInfo.h" 1.11 + 1.12 +#include "nsIURI.h" 1.13 +#include "nsICacheService.h" 1.14 +#include "nsICacheSession.h" 1.15 +#include "nsIApplicationCache.h" 1.16 +#include "nsIApplicationCacheService.h" 1.17 +#include "nsIStreamTransportService.h" 1.18 +#include "nsIFile.h" 1.19 +#include "nsICacheEntryDoomCallback.h" 1.20 +#include "nsICacheListener.h" 1.21 +#include "nsICacheStorageVisitor.h" 1.22 + 1.23 +#include "nsServiceManagerUtils.h" 1.24 +#include "nsNetCID.h" 1.25 +#include "nsProxyRelease.h" 1.26 +#include "mozilla/Telemetry.h" 1.27 + 1.28 +static NS_DEFINE_CID(kStreamTransportServiceCID, 1.29 + NS_STREAMTRANSPORTSERVICE_CID); 1.30 + 1.31 +static uint32_t const CHECK_MULTITHREADED = nsICacheStorage::CHECK_MULTITHREADED; 1.32 + 1.33 +namespace mozilla { 1.34 +namespace net { 1.35 + 1.36 +namespace { // anon 1.37 + 1.38 +// Fires the doom callback back on the main thread 1.39 +// after the cache I/O thread is looped. 1.40 + 1.41 +class DoomCallbackSynchronizer : public nsRunnable 1.42 +{ 1.43 +public: 1.44 + DoomCallbackSynchronizer(nsICacheEntryDoomCallback* cb) : mCB(cb) 1.45 + { 1.46 + MOZ_COUNT_CTOR(DoomCallbackSynchronizer); 1.47 + } 1.48 + nsresult Dispatch(); 1.49 + 1.50 +private: 1.51 + virtual ~DoomCallbackSynchronizer() 1.52 + { 1.53 + MOZ_COUNT_DTOR(DoomCallbackSynchronizer); 1.54 + } 1.55 + 1.56 + NS_DECL_NSIRUNNABLE 1.57 + nsCOMPtr<nsICacheEntryDoomCallback> mCB; 1.58 +}; 1.59 + 1.60 +nsresult DoomCallbackSynchronizer::Dispatch() 1.61 +{ 1.62 + nsresult rv; 1.63 + 1.64 + nsCOMPtr<nsICacheService> serv = 1.65 + do_GetService(NS_CACHESERVICE_CONTRACTID, &rv); 1.66 + NS_ENSURE_SUCCESS(rv, rv); 1.67 + 1.68 + nsCOMPtr<nsIEventTarget> eventTarget; 1.69 + rv = serv->GetCacheIOTarget(getter_AddRefs(eventTarget)); 1.70 + NS_ENSURE_SUCCESS(rv, rv); 1.71 + 1.72 + rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL); 1.73 + NS_ENSURE_SUCCESS(rv, rv); 1.74 + 1.75 + return NS_OK; 1.76 +} 1.77 + 1.78 +NS_IMETHODIMP DoomCallbackSynchronizer::Run() 1.79 +{ 1.80 + if (!NS_IsMainThread()) { 1.81 + NS_DispatchToMainThread(this); 1.82 + } 1.83 + else { 1.84 + if (mCB) 1.85 + mCB->OnCacheEntryDoomed(NS_OK); 1.86 + } 1.87 + return NS_OK; 1.88 +} 1.89 + 1.90 +// Receives doom callback from the old API and forwards to the new API 1.91 + 1.92 +class DoomCallbackWrapper : public nsICacheListener 1.93 +{ 1.94 + NS_DECL_THREADSAFE_ISUPPORTS 1.95 + NS_DECL_NSICACHELISTENER 1.96 + 1.97 + DoomCallbackWrapper(nsICacheEntryDoomCallback* cb) : mCB(cb) 1.98 + { 1.99 + MOZ_COUNT_CTOR(DoomCallbackWrapper); 1.100 + } 1.101 + 1.102 +private: 1.103 + virtual ~DoomCallbackWrapper() 1.104 + { 1.105 + MOZ_COUNT_DTOR(DoomCallbackWrapper); 1.106 + } 1.107 + 1.108 + nsCOMPtr<nsICacheEntryDoomCallback> mCB; 1.109 +}; 1.110 + 1.111 +NS_IMPL_ISUPPORTS(DoomCallbackWrapper, nsICacheListener); 1.112 + 1.113 +NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryAvailable(nsICacheEntryDescriptor *descriptor, 1.114 + nsCacheAccessMode accessGranted, 1.115 + nsresult status) 1.116 +{ 1.117 + return NS_OK; 1.118 +} 1.119 + 1.120 +NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryDoomed(nsresult status) 1.121 +{ 1.122 + if (!mCB) 1.123 + return NS_ERROR_NULL_POINTER; 1.124 + 1.125 + mCB->OnCacheEntryDoomed(status); 1.126 + mCB = nullptr; 1.127 + return NS_OK; 1.128 +} 1.129 + 1.130 +// Receives visit callbacks from the old API and forwards it to the new API 1.131 + 1.132 +class VisitCallbackWrapper : public nsICacheVisitor 1.133 +{ 1.134 + NS_DECL_THREADSAFE_ISUPPORTS 1.135 + NS_DECL_NSICACHEVISITOR 1.136 + 1.137 + VisitCallbackWrapper(char* const deviceID, 1.138 + nsICacheStorageVisitor* cb, 1.139 + bool visitEntries) 1.140 + : mCB(cb) 1.141 + , mVisitEntries(visitEntries) 1.142 + , mDeviceID(deviceID) 1.143 + { 1.144 + MOZ_COUNT_CTOR(VisitCallbackWrapper); 1.145 + } 1.146 + 1.147 +private: 1.148 + virtual ~VisitCallbackWrapper(); 1.149 + nsCOMPtr<nsICacheStorageVisitor> mCB; 1.150 + bool mVisitEntries; 1.151 + char* const mDeviceID; 1.152 +}; 1.153 + 1.154 +NS_IMPL_ISUPPORTS(VisitCallbackWrapper, nsICacheVisitor) 1.155 + 1.156 +VisitCallbackWrapper::~VisitCallbackWrapper() 1.157 +{ 1.158 + if (mVisitEntries) 1.159 + mCB->OnCacheEntryVisitCompleted(); 1.160 + 1.161 + MOZ_COUNT_DTOR(VisitCallbackWrapper); 1.162 +} 1.163 + 1.164 +NS_IMETHODIMP VisitCallbackWrapper::VisitDevice(const char * deviceID, 1.165 + nsICacheDeviceInfo *deviceInfo, 1.166 + bool *_retval) 1.167 +{ 1.168 + if (!mCB) 1.169 + return NS_ERROR_NULL_POINTER; 1.170 + 1.171 + *_retval = false; 1.172 + if (strcmp(deviceID, mDeviceID)) { 1.173 + // Not the device we want to visit 1.174 + return NS_OK; 1.175 + } 1.176 + 1.177 + nsresult rv; 1.178 + 1.179 + uint32_t entryCount; 1.180 + rv = deviceInfo->GetEntryCount(&entryCount); 1.181 + NS_ENSURE_SUCCESS(rv, rv); 1.182 + 1.183 + uint32_t totalSize; 1.184 + rv = deviceInfo->GetTotalSize(&totalSize); 1.185 + NS_ENSURE_SUCCESS(rv, rv); 1.186 + 1.187 + mCB->OnCacheStorageInfo(entryCount, totalSize); 1.188 + *_retval = mVisitEntries; 1.189 + 1.190 + return NS_OK; 1.191 +} 1.192 + 1.193 +NS_IMETHODIMP VisitCallbackWrapper::VisitEntry(const char * deviceID, 1.194 + nsICacheEntryInfo *entryInfo, 1.195 + bool *_retval) 1.196 +{ 1.197 + MOZ_ASSERT(!strcmp(deviceID, mDeviceID)); 1.198 + 1.199 + nsRefPtr<_OldCacheEntryWrapper> wrapper = new _OldCacheEntryWrapper(entryInfo); 1.200 + nsresult rv = mCB->OnCacheEntryInfo(wrapper); 1.201 + *_retval = NS_SUCCEEDED(rv); 1.202 + 1.203 + return NS_OK; 1.204 +} 1.205 + 1.206 +} // anon 1.207 + 1.208 + 1.209 +// _OldGetDiskConsumption 1.210 + 1.211 +//static 1.212 +nsresult _OldGetDiskConsumption::Get(nsICacheStorageConsumptionObserver* aCallback) 1.213 +{ 1.214 + nsresult rv; 1.215 + 1.216 + nsCOMPtr<nsICacheService> serv = 1.217 + do_GetService(NS_CACHESERVICE_CONTRACTID, &rv); 1.218 + NS_ENSURE_SUCCESS(rv, rv); 1.219 + 1.220 + nsRefPtr<_OldGetDiskConsumption> cb = new _OldGetDiskConsumption(aCallback); 1.221 + 1.222 + // _OldGetDiskConsumption stores the found size value, but until dispatched 1.223 + // to the main thread it doesn't call on the consupmtion observer. See bellow. 1.224 + rv = serv->VisitEntries(cb); 1.225 + NS_ENSURE_SUCCESS(rv, rv); 1.226 + 1.227 + // We are called from CacheStorageService::AsyncGetDiskConsumption whose IDL 1.228 + // documentation claims the callback is always delievered asynchronously 1.229 + // back to the main thread. Despite we know the result synchronosusly when 1.230 + // querying the old cache, we need to stand the word and dispatch the result 1.231 + // to the main thread asynchronously. Hence the dispatch here. 1.232 + return NS_DispatchToMainThread(cb); 1.233 +} 1.234 + 1.235 +NS_IMPL_ISUPPORTS_INHERITED(_OldGetDiskConsumption, 1.236 + nsRunnable, 1.237 + nsICacheVisitor) 1.238 + 1.239 +_OldGetDiskConsumption::_OldGetDiskConsumption( 1.240 + nsICacheStorageConsumptionObserver* aCallback) 1.241 + : mCallback(aCallback) 1.242 + , mSize(0) 1.243 +{ 1.244 +} 1.245 + 1.246 +NS_IMETHODIMP 1.247 +_OldGetDiskConsumption::Run() 1.248 +{ 1.249 + mCallback->OnNetworkCacheDiskConsumption(mSize); 1.250 + return NS_OK; 1.251 +} 1.252 + 1.253 +NS_IMETHODIMP 1.254 +_OldGetDiskConsumption::VisitDevice(const char * deviceID, 1.255 + nsICacheDeviceInfo *deviceInfo, 1.256 + bool *_retval) 1.257 +{ 1.258 + if (!strcmp(deviceID, "disk")) { 1.259 + uint32_t size; 1.260 + nsresult rv = deviceInfo->GetTotalSize(&size); 1.261 + if (NS_SUCCEEDED(rv)) 1.262 + mSize = (int64_t)size; 1.263 + } 1.264 + 1.265 + *_retval = false; 1.266 + return NS_OK; 1.267 +} 1.268 + 1.269 +NS_IMETHODIMP 1.270 +_OldGetDiskConsumption::VisitEntry(const char * deviceID, 1.271 + nsICacheEntryInfo *entryInfo, 1.272 + bool *_retval) 1.273 +{ 1.274 + MOZ_CRASH("Unexpected"); 1.275 + return NS_OK; 1.276 +} 1.277 + 1.278 + 1.279 +// _OldCacheEntryWrapper 1.280 + 1.281 +_OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryDescriptor* desc) 1.282 +: mOldDesc(desc), mOldInfo(desc) 1.283 +{ 1.284 + MOZ_COUNT_CTOR(_OldCacheEntryWrapper); 1.285 + LOG(("Creating _OldCacheEntryWrapper %p for descriptor %p", this, desc)); 1.286 +} 1.287 + 1.288 +_OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryInfo* info) 1.289 +: mOldDesc(nullptr), mOldInfo(info) 1.290 +{ 1.291 + MOZ_COUNT_CTOR(_OldCacheEntryWrapper); 1.292 + LOG(("Creating _OldCacheEntryWrapper %p for info %p", this, info)); 1.293 +} 1.294 + 1.295 +_OldCacheEntryWrapper::~_OldCacheEntryWrapper() 1.296 +{ 1.297 + MOZ_COUNT_DTOR(_OldCacheEntryWrapper); 1.298 + LOG(("Destroying _OldCacheEntryWrapper %p for descriptor %p", this, mOldInfo.get())); 1.299 +} 1.300 + 1.301 +NS_IMPL_ISUPPORTS(_OldCacheEntryWrapper, nsICacheEntry) 1.302 + 1.303 +NS_IMETHODIMP _OldCacheEntryWrapper::AsyncDoom(nsICacheEntryDoomCallback* listener) 1.304 +{ 1.305 + nsRefPtr<DoomCallbackWrapper> cb = listener 1.306 + ? new DoomCallbackWrapper(listener) 1.307 + : nullptr; 1.308 + return AsyncDoom(cb); 1.309 +} 1.310 + 1.311 +NS_IMETHODIMP _OldCacheEntryWrapper::GetDataSize(int64_t *aSize) 1.312 +{ 1.313 + uint32_t size; 1.314 + nsresult rv = GetDataSize(&size); 1.315 + if (NS_FAILED(rv)) 1.316 + return rv; 1.317 + 1.318 + *aSize = size; 1.319 + return NS_OK; 1.320 +} 1.321 + 1.322 +NS_IMETHODIMP _OldCacheEntryWrapper::GetPersistent(bool *aPersistToDisk) 1.323 +{ 1.324 + if (!mOldDesc) { 1.325 + return NS_ERROR_NULL_POINTER; 1.326 + } 1.327 + 1.328 + nsresult rv; 1.329 + 1.330 + nsCacheStoragePolicy policy; 1.331 + rv = mOldDesc->GetStoragePolicy(&policy); 1.332 + NS_ENSURE_SUCCESS(rv, rv); 1.333 + 1.334 + *aPersistToDisk = policy != nsICache::STORE_IN_MEMORY; 1.335 + 1.336 + return NS_OK; 1.337 +} 1.338 + 1.339 +NS_IMETHODIMP _OldCacheEntryWrapper::Recreate(bool aMemoryOnly, 1.340 + nsICacheEntry** aResult) 1.341 +{ 1.342 + NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NOT_AVAILABLE); 1.343 + 1.344 + nsCacheAccessMode mode; 1.345 + nsresult rv = mOldDesc->GetAccessGranted(&mode); 1.346 + NS_ENSURE_SUCCESS(rv, rv); 1.347 + 1.348 + if (!(mode & nsICache::ACCESS_WRITE)) 1.349 + return NS_ERROR_NOT_AVAILABLE; 1.350 + 1.351 + LOG(("_OldCacheEntryWrapper::Recreate [this=%p]", this)); 1.352 + 1.353 + if (aMemoryOnly) 1.354 + mOldDesc->SetStoragePolicy(nsICache::STORE_IN_MEMORY); 1.355 + 1.356 + nsCOMPtr<nsICacheEntry> self(this); 1.357 + self.forget(aResult); 1.358 + return NS_OK; 1.359 +} 1.360 + 1.361 +NS_IMETHODIMP _OldCacheEntryWrapper::OpenInputStream(int64_t offset, 1.362 + nsIInputStream * *_retval) 1.363 +{ 1.364 + if (offset > PR_UINT32_MAX) 1.365 + return NS_ERROR_INVALID_ARG; 1.366 + 1.367 + return OpenInputStream(uint32_t(offset), _retval); 1.368 +} 1.369 +NS_IMETHODIMP _OldCacheEntryWrapper::OpenOutputStream(int64_t offset, 1.370 + nsIOutputStream * *_retval) 1.371 +{ 1.372 + if (offset > PR_UINT32_MAX) 1.373 + return NS_ERROR_INVALID_ARG; 1.374 + 1.375 + return OpenOutputStream(uint32_t(offset), _retval); 1.376 +} 1.377 + 1.378 +NS_IMETHODIMP _OldCacheEntryWrapper::MaybeMarkValid() 1.379 +{ 1.380 + LOG(("_OldCacheEntryWrapper::MaybeMarkValid [this=%p]", this)); 1.381 + 1.382 + NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NULL_POINTER); 1.383 + 1.384 + nsCacheAccessMode mode; 1.385 + nsresult rv = mOldDesc->GetAccessGranted(&mode); 1.386 + NS_ENSURE_SUCCESS(rv, rv); 1.387 + 1.388 + if (mode & nsICache::ACCESS_WRITE) { 1.389 + LOG(("Marking cache entry valid [entry=%p, descr=%p]", this, mOldDesc)); 1.390 + return mOldDesc->MarkValid(); 1.391 + } 1.392 + 1.393 + LOG(("Not marking read-only cache entry valid [entry=%p, descr=%p]", this, mOldDesc)); 1.394 + return NS_OK; 1.395 +} 1.396 + 1.397 +NS_IMETHODIMP _OldCacheEntryWrapper::HasWriteAccess(bool aWriteAllowed_unused, bool *aWriteAccess) 1.398 +{ 1.399 + NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NULL_POINTER); 1.400 + NS_ENSURE_ARG(aWriteAccess); 1.401 + 1.402 + nsCacheAccessMode mode; 1.403 + nsresult rv = mOldDesc->GetAccessGranted(&mode); 1.404 + NS_ENSURE_SUCCESS(rv, rv); 1.405 + 1.406 + *aWriteAccess = !!(mode & nsICache::ACCESS_WRITE); 1.407 + 1.408 + LOG(("_OldCacheEntryWrapper::HasWriteAccess [this=%p, write-access=%d]", this, *aWriteAccess)); 1.409 + 1.410 + return NS_OK; 1.411 +} 1.412 + 1.413 + 1.414 +namespace { // anon 1.415 + 1.416 +nsresult 1.417 +GetCacheSessionNameForStoragePolicy( 1.418 + nsCSubstring const &scheme, 1.419 + nsCacheStoragePolicy storagePolicy, 1.420 + bool isPrivate, 1.421 + uint32_t appId, 1.422 + bool inBrowser, 1.423 + nsACString& sessionName) 1.424 +{ 1.425 + MOZ_ASSERT(!isPrivate || storagePolicy == nsICache::STORE_IN_MEMORY); 1.426 + 1.427 + // HTTP 1.428 + if (scheme.Equals(NS_LITERAL_CSTRING("http")) || 1.429 + scheme.Equals(NS_LITERAL_CSTRING("https"))) { 1.430 + switch (storagePolicy) { 1.431 + case nsICache::STORE_IN_MEMORY: 1.432 + if (isPrivate) 1.433 + sessionName.Assign(NS_LITERAL_CSTRING("HTTP-memory-only-PB")); 1.434 + else 1.435 + sessionName.Assign(NS_LITERAL_CSTRING("HTTP-memory-only")); 1.436 + break; 1.437 + case nsICache::STORE_OFFLINE: 1.438 + // XXX This is actually never used, only added to prevent 1.439 + // any compatibility damage. 1.440 + sessionName.Assign(NS_LITERAL_CSTRING("HTTP-offline")); 1.441 + break; 1.442 + default: 1.443 + sessionName.Assign(NS_LITERAL_CSTRING("HTTP")); 1.444 + break; 1.445 + } 1.446 + } 1.447 + // WYCIWYG 1.448 + else if (scheme.Equals(NS_LITERAL_CSTRING("wyciwyg"))) { 1.449 + if (isPrivate) 1.450 + sessionName.Assign(NS_LITERAL_CSTRING("wyciwyg-private")); 1.451 + else 1.452 + sessionName.Assign(NS_LITERAL_CSTRING("wyciwyg")); 1.453 + } 1.454 + // FTP 1.455 + else if (scheme.Equals(NS_LITERAL_CSTRING("ftp"))) { 1.456 + if (isPrivate) 1.457 + sessionName.Assign(NS_LITERAL_CSTRING("FTP-private")); 1.458 + else 1.459 + sessionName.Assign(NS_LITERAL_CSTRING("FTP")); 1.460 + } 1.461 + // all remaining URL scheme 1.462 + else { 1.463 + // Since with the new API a consumer cannot specify its own session name 1.464 + // and partitioning of the cache is handled stricly only by the cache 1.465 + // back-end internally, we will use a separate session name to pretend 1.466 + // functionality of the new API wrapping the Darin's cache for all other 1.467 + // URL schemes. 1.468 + // Deliberately omitting |anonymous| since other session types don't 1.469 + // recognize it too. 1.470 + sessionName.Assign(NS_LITERAL_CSTRING("other")); 1.471 + if (isPrivate) 1.472 + sessionName.Append(NS_LITERAL_CSTRING("-private")); 1.473 + } 1.474 + 1.475 + if (appId != nsILoadContextInfo::NO_APP_ID || inBrowser) { 1.476 + sessionName.Append('~'); 1.477 + sessionName.AppendInt(appId); 1.478 + sessionName.Append('~'); 1.479 + sessionName.AppendInt(inBrowser); 1.480 + } 1.481 + 1.482 + return NS_OK; 1.483 +} 1.484 + 1.485 +nsresult 1.486 +GetCacheSession(nsCSubstring const &aScheme, 1.487 + bool aWriteToDisk, 1.488 + nsILoadContextInfo* aLoadInfo, 1.489 + nsIApplicationCache* aAppCache, 1.490 + nsICacheSession** _result) 1.491 +{ 1.492 + nsresult rv; 1.493 + 1.494 + nsCacheStoragePolicy storagePolicy; 1.495 + if (aAppCache) 1.496 + storagePolicy = nsICache::STORE_OFFLINE; 1.497 + else if (!aWriteToDisk || aLoadInfo->IsPrivate()) 1.498 + storagePolicy = nsICache::STORE_IN_MEMORY; 1.499 + else 1.500 + storagePolicy = nsICache::STORE_ANYWHERE; 1.501 + 1.502 + nsAutoCString clientId; 1.503 + if (aAppCache) { 1.504 + aAppCache->GetClientID(clientId); 1.505 + } 1.506 + else { 1.507 + rv = GetCacheSessionNameForStoragePolicy( 1.508 + aScheme, 1.509 + storagePolicy, 1.510 + aLoadInfo->IsPrivate(), 1.511 + aLoadInfo->AppId(), 1.512 + aLoadInfo->IsInBrowserElement(), 1.513 + clientId); 1.514 + NS_ENSURE_SUCCESS(rv, rv); 1.515 + } 1.516 + 1.517 + LOG((" GetCacheSession for client=%s, policy=%d", clientId.get(), storagePolicy)); 1.518 + 1.519 + nsCOMPtr<nsICacheService> serv = 1.520 + do_GetService(NS_CACHESERVICE_CONTRACTID, &rv); 1.521 + NS_ENSURE_SUCCESS(rv, rv); 1.522 + 1.523 + nsCOMPtr<nsICacheSession> session; 1.524 + rv = serv->CreateSession(clientId.get(), 1.525 + storagePolicy, 1.526 + nsICache::STREAM_BASED, 1.527 + getter_AddRefs(session)); 1.528 + NS_ENSURE_SUCCESS(rv, rv); 1.529 + 1.530 + rv = session->SetIsPrivate(aLoadInfo->IsPrivate()); 1.531 + NS_ENSURE_SUCCESS(rv, rv); 1.532 + 1.533 + rv = session->SetDoomEntriesIfExpired(false); 1.534 + NS_ENSURE_SUCCESS(rv, rv); 1.535 + 1.536 + if (aAppCache) { 1.537 + nsCOMPtr<nsIFile> profileDirectory; 1.538 + aAppCache->GetProfileDirectory(getter_AddRefs(profileDirectory)); 1.539 + if (profileDirectory) 1.540 + rv = session->SetProfileDirectory(profileDirectory); 1.541 + NS_ENSURE_SUCCESS(rv, rv); 1.542 + } 1.543 + 1.544 + session.forget(_result); 1.545 + return NS_OK; 1.546 +} 1.547 + 1.548 +} // anon 1.549 + 1.550 + 1.551 +NS_IMPL_ISUPPORTS_INHERITED(_OldCacheLoad, nsRunnable, nsICacheListener) 1.552 + 1.553 +_OldCacheLoad::_OldCacheLoad(nsCSubstring const& aScheme, 1.554 + nsCSubstring const& aCacheKey, 1.555 + nsICacheEntryOpenCallback* aCallback, 1.556 + nsIApplicationCache* aAppCache, 1.557 + nsILoadContextInfo* aLoadInfo, 1.558 + bool aWriteToDisk, 1.559 + uint32_t aFlags) 1.560 + : mScheme(aScheme) 1.561 + , mCacheKey(aCacheKey) 1.562 + , mCallback(aCallback) 1.563 + , mLoadInfo(GetLoadContextInfo(aLoadInfo)) 1.564 + , mFlags(aFlags) 1.565 + , mWriteToDisk(aWriteToDisk) 1.566 + , mNew(true) 1.567 + , mOpening(true) 1.568 + , mSync(false) 1.569 + , mStatus(NS_ERROR_UNEXPECTED) 1.570 + , mRunCount(0) 1.571 + , mAppCache(aAppCache) 1.572 +{ 1.573 + MOZ_COUNT_CTOR(_OldCacheLoad); 1.574 +} 1.575 + 1.576 +_OldCacheLoad::~_OldCacheLoad() 1.577 +{ 1.578 + ProxyReleaseMainThread(mAppCache); 1.579 + MOZ_COUNT_DTOR(_OldCacheLoad); 1.580 +} 1.581 + 1.582 +nsresult _OldCacheLoad::Start() 1.583 +{ 1.584 + LOG(("_OldCacheLoad::Start [this=%p, key=%s]", this, mCacheKey.get())); 1.585 + 1.586 + mLoadStart = mozilla::TimeStamp::Now(); 1.587 + 1.588 + nsresult rv; 1.589 + 1.590 + // Consumers that can invoke this code as first and off the main thread 1.591 + // are responsible for initiating these two services on the main thread. 1.592 + // Currently this is only nsWyciwygChannel. 1.593 + 1.594 + // XXX: Start the cache service; otherwise DispatchToCacheIOThread will 1.595 + // fail. 1.596 + nsCOMPtr<nsICacheService> service = 1.597 + do_GetService(NS_CACHESERVICE_CONTRACTID, &rv); 1.598 + 1.599 + // Ensure the stream transport service gets initialized on the main thread 1.600 + if (NS_SUCCEEDED(rv) && NS_IsMainThread()) { 1.601 + nsCOMPtr<nsIStreamTransportService> sts = 1.602 + do_GetService(kStreamTransportServiceCID, &rv); 1.603 + } 1.604 + 1.605 + if (NS_SUCCEEDED(rv)) { 1.606 + rv = service->GetCacheIOTarget(getter_AddRefs(mCacheThread)); 1.607 + } 1.608 + 1.609 + if (NS_SUCCEEDED(rv)) { 1.610 + bool onCacheTarget; 1.611 + rv = mCacheThread->IsOnCurrentThread(&onCacheTarget); 1.612 + if (NS_SUCCEEDED(rv) && onCacheTarget) { 1.613 + mSync = true; 1.614 + } 1.615 + } 1.616 + 1.617 + if (NS_SUCCEEDED(rv)) { 1.618 + if (mSync) { 1.619 + rv = Run(); 1.620 + } 1.621 + else { 1.622 + rv = mCacheThread->Dispatch(this, NS_DISPATCH_NORMAL); 1.623 + } 1.624 + } 1.625 + 1.626 + return rv; 1.627 +} 1.628 + 1.629 +NS_IMETHODIMP 1.630 +_OldCacheLoad::Run() 1.631 +{ 1.632 + LOG(("_OldCacheLoad::Run [this=%p, key=%s, cb=%p]", this, mCacheKey.get(), mCallback.get())); 1.633 + 1.634 + nsresult rv; 1.635 + 1.636 + if (mOpening) { 1.637 + mOpening = false; 1.638 + nsCOMPtr<nsICacheSession> session; 1.639 + rv = GetCacheSession(mScheme, mWriteToDisk, mLoadInfo, mAppCache, 1.640 + getter_AddRefs(session)); 1.641 + if (NS_SUCCEEDED(rv)) { 1.642 + // AsyncOpenCacheEntry isn't really async when its called on the 1.643 + // cache service thread. 1.644 + 1.645 + nsCacheAccessMode cacheAccess; 1.646 + if (mFlags & nsICacheStorage::OPEN_TRUNCATE) 1.647 + cacheAccess = nsICache::ACCESS_WRITE; 1.648 + else if ((mFlags & nsICacheStorage::OPEN_READONLY) || mAppCache) 1.649 + cacheAccess = nsICache::ACCESS_READ; 1.650 + else 1.651 + cacheAccess = nsICache::ACCESS_READ_WRITE; 1.652 + 1.653 + LOG((" session->AsyncOpenCacheEntry with access=%d", cacheAccess)); 1.654 + 1.655 + bool bypassBusy = mFlags & nsICacheStorage::OPEN_BYPASS_IF_BUSY; 1.656 + 1.657 + if (mSync && cacheAccess == nsICache::ACCESS_WRITE) { 1.658 + nsCOMPtr<nsICacheEntryDescriptor> entry; 1.659 + rv = session->OpenCacheEntry(mCacheKey, cacheAccess, bypassBusy, 1.660 + getter_AddRefs(entry)); 1.661 + 1.662 + nsCacheAccessMode grantedAccess = 0; 1.663 + if (NS_SUCCEEDED(rv)) { 1.664 + entry->GetAccessGranted(&grantedAccess); 1.665 + } 1.666 + 1.667 + return OnCacheEntryAvailable(entry, grantedAccess, rv); 1.668 + } 1.669 + 1.670 + rv = session->AsyncOpenCacheEntry(mCacheKey, cacheAccess, this, bypassBusy); 1.671 + if (NS_SUCCEEDED(rv)) 1.672 + return NS_OK; 1.673 + } 1.674 + 1.675 + // Opening failed, propagate the error to the consumer 1.676 + LOG((" Opening cache entry failed with rv=0x%08x", rv)); 1.677 + mStatus = rv; 1.678 + mNew = false; 1.679 + NS_DispatchToMainThread(this); 1.680 + } else { 1.681 + if (!mCallback) { 1.682 + LOG((" duplicate call, bypassed")); 1.683 + return NS_OK; 1.684 + } 1.685 + 1.686 + if (NS_SUCCEEDED(mStatus)) { 1.687 + if (mFlags & nsICacheStorage::OPEN_TRUNCATE) { 1.688 + mozilla::Telemetry::AccumulateTimeDelta( 1.689 + mozilla::Telemetry::NETWORK_CACHE_V1_TRUNCATE_TIME_MS, 1.690 + mLoadStart); 1.691 + } 1.692 + else if (mNew) { 1.693 + mozilla::Telemetry::AccumulateTimeDelta( 1.694 + mozilla::Telemetry::NETWORK_CACHE_V1_MISS_TIME_MS, 1.695 + mLoadStart); 1.696 + } 1.697 + else { 1.698 + mozilla::Telemetry::AccumulateTimeDelta( 1.699 + mozilla::Telemetry::NETWORK_CACHE_V1_HIT_TIME_MS, 1.700 + mLoadStart); 1.701 + } 1.702 + } 1.703 + 1.704 + if (!(mFlags & CHECK_MULTITHREADED)) 1.705 + Check(); 1.706 + 1.707 + // break cycles 1.708 + nsCOMPtr<nsICacheEntryOpenCallback> cb = mCallback.forget(); 1.709 + mCacheThread = nullptr; 1.710 + nsCOMPtr<nsICacheEntry> entry = mCacheEntry.forget(); 1.711 + 1.712 + rv = cb->OnCacheEntryAvailable(entry, mNew, mAppCache, mStatus); 1.713 + 1.714 + if (NS_FAILED(rv) && entry) { 1.715 + LOG((" cb->OnCacheEntryAvailable failed with rv=0x%08x", rv)); 1.716 + if (mNew) 1.717 + entry->AsyncDoom(nullptr); 1.718 + else 1.719 + entry->Close(); 1.720 + } 1.721 + } 1.722 + 1.723 + return rv; 1.724 +} 1.725 + 1.726 +NS_IMETHODIMP 1.727 +_OldCacheLoad::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry, 1.728 + nsCacheAccessMode access, 1.729 + nsresult status) 1.730 +{ 1.731 + LOG(("_OldCacheLoad::OnCacheEntryAvailable [this=%p, ent=%p, cb=%p, appcache=%p, access=%x]", 1.732 + this, entry, mCallback.get(), mAppCache.get(), access)); 1.733 + 1.734 + // XXX Bug 759805: Sometimes we will call this method directly from 1.735 + // HttpCacheQuery::Run when AsyncOpenCacheEntry fails, but 1.736 + // AsyncOpenCacheEntry will also call this method. As a workaround, we just 1.737 + // ensure we only execute this code once. 1.738 + NS_ENSURE_TRUE(mRunCount == 0, NS_ERROR_UNEXPECTED); 1.739 + ++mRunCount; 1.740 + 1.741 + mCacheEntry = entry ? new _OldCacheEntryWrapper(entry) : nullptr; 1.742 + mStatus = status; 1.743 + mNew = access == nsICache::ACCESS_WRITE; 1.744 + 1.745 + if (mFlags & CHECK_MULTITHREADED) 1.746 + Check(); 1.747 + 1.748 + if (mSync) 1.749 + return Run(); 1.750 + 1.751 + return NS_DispatchToMainThread(this); 1.752 +} 1.753 + 1.754 +void 1.755 +_OldCacheLoad::Check() 1.756 +{ 1.757 + if (!mCacheEntry) 1.758 + return; 1.759 + 1.760 + if (mNew) 1.761 + return; 1.762 + 1.763 + uint32_t result; 1.764 + nsresult rv = mCallback->OnCacheEntryCheck(mCacheEntry, mAppCache, &result); 1.765 + LOG((" OnCacheEntryCheck result ent=%p, cb=%p, appcache=%p, rv=0x%08x, result=%d", 1.766 + mCacheEntry.get(), mCallback.get(), mAppCache.get(), rv, result)); 1.767 + 1.768 + if (NS_FAILED(rv)) { 1.769 + NS_WARNING("cache check failed"); 1.770 + } 1.771 + 1.772 + if (NS_FAILED(rv) || result == nsICacheEntryOpenCallback::ENTRY_NOT_WANTED) { 1.773 + mCacheEntry->Close(); 1.774 + mCacheEntry = nullptr; 1.775 + mStatus = NS_ERROR_CACHE_KEY_NOT_FOUND; 1.776 + } 1.777 +} 1.778 + 1.779 +NS_IMETHODIMP 1.780 +_OldCacheLoad::OnCacheEntryDoomed(nsresult) 1.781 +{ 1.782 + return NS_ERROR_NOT_IMPLEMENTED; 1.783 +} 1.784 + 1.785 +// nsICacheStorage old cache wrapper 1.786 + 1.787 +NS_IMPL_ISUPPORTS(_OldStorage, nsICacheStorage) 1.788 + 1.789 +_OldStorage::_OldStorage(nsILoadContextInfo* aInfo, 1.790 + bool aAllowDisk, 1.791 + bool aLookupAppCache, 1.792 + bool aOfflineStorage, 1.793 + nsIApplicationCache* aAppCache) 1.794 +: mLoadInfo(GetLoadContextInfo(aInfo)) 1.795 +, mAppCache(aAppCache) 1.796 +, mWriteToDisk(aAllowDisk) 1.797 +, mLookupAppCache(aLookupAppCache) 1.798 +, mOfflineStorage(aOfflineStorage) 1.799 +{ 1.800 + MOZ_COUNT_CTOR(_OldStorage); 1.801 +} 1.802 + 1.803 +_OldStorage::~_OldStorage() 1.804 +{ 1.805 + MOZ_COUNT_DTOR(_OldStorage); 1.806 +} 1.807 + 1.808 +NS_IMETHODIMP _OldStorage::AsyncOpenURI(nsIURI *aURI, 1.809 + const nsACString & aIdExtension, 1.810 + uint32_t aFlags, 1.811 + nsICacheEntryOpenCallback *aCallback) 1.812 +{ 1.813 + NS_ENSURE_ARG(aURI); 1.814 + NS_ENSURE_ARG(aCallback); 1.815 + 1.816 +#ifdef MOZ_LOGGING 1.817 + nsAutoCString uriSpec; 1.818 + aURI->GetAsciiSpec(uriSpec); 1.819 + LOG(("_OldStorage::AsyncOpenURI [this=%p, uri=%s, ide=%s, flags=%x]", 1.820 + this, uriSpec.get(), aIdExtension.BeginReading(), aFlags)); 1.821 +#endif 1.822 + 1.823 + nsresult rv; 1.824 + 1.825 + nsAutoCString cacheKey, scheme; 1.826 + rv = AssembleCacheKey(aURI, aIdExtension, cacheKey, scheme); 1.827 + NS_ENSURE_SUCCESS(rv, rv); 1.828 + 1.829 + if (!mAppCache && (mLookupAppCache || mOfflineStorage)) { 1.830 + rv = ChooseApplicationCache(cacheKey, getter_AddRefs(mAppCache)); 1.831 + NS_ENSURE_SUCCESS(rv, rv); 1.832 + 1.833 + if (mAppCache) { 1.834 + // From a chosen appcache open only as readonly 1.835 + aFlags &= ~nsICacheStorage::OPEN_TRUNCATE; 1.836 + } 1.837 + } 1.838 + 1.839 + nsRefPtr<_OldCacheLoad> cacheLoad = 1.840 + new _OldCacheLoad(scheme, cacheKey, aCallback, mAppCache, 1.841 + mLoadInfo, mWriteToDisk, aFlags); 1.842 + 1.843 + rv = cacheLoad->Start(); 1.844 + NS_ENSURE_SUCCESS(rv, rv); 1.845 + 1.846 + return NS_OK; 1.847 +} 1.848 + 1.849 +NS_IMETHODIMP _OldStorage::AsyncDoomURI(nsIURI *aURI, const nsACString & aIdExtension, 1.850 + nsICacheEntryDoomCallback* aCallback) 1.851 +{ 1.852 + LOG(("_OldStorage::AsyncDoomURI")); 1.853 + 1.854 + nsresult rv; 1.855 + 1.856 + nsAutoCString cacheKey, scheme; 1.857 + rv = AssembleCacheKey(aURI, aIdExtension, cacheKey, scheme); 1.858 + NS_ENSURE_SUCCESS(rv, rv); 1.859 + 1.860 + nsCOMPtr<nsICacheSession> session; 1.861 + rv = GetCacheSession(scheme, mWriteToDisk, mLoadInfo, mAppCache, 1.862 + getter_AddRefs(session)); 1.863 + NS_ENSURE_SUCCESS(rv, rv); 1.864 + 1.865 + nsRefPtr<DoomCallbackWrapper> cb = aCallback 1.866 + ? new DoomCallbackWrapper(aCallback) 1.867 + : nullptr; 1.868 + rv = session->DoomEntry(cacheKey, cb); 1.869 + NS_ENSURE_SUCCESS(rv, rv); 1.870 + 1.871 + return NS_OK; 1.872 +} 1.873 + 1.874 +NS_IMETHODIMP _OldStorage::AsyncEvictStorage(nsICacheEntryDoomCallback* aCallback) 1.875 +{ 1.876 + LOG(("_OldStorage::AsyncEvictStorage")); 1.877 + 1.878 + nsresult rv; 1.879 + 1.880 + if (!mAppCache && mOfflineStorage) { 1.881 + // Special casing for pure offline storage 1.882 + if (mLoadInfo->AppId() == nsILoadContextInfo::NO_APP_ID && 1.883 + !mLoadInfo->IsInBrowserElement()) { 1.884 + 1.885 + // Clear everything. 1.886 + nsCOMPtr<nsICacheService> serv = 1.887 + do_GetService(NS_CACHESERVICE_CONTRACTID, &rv); 1.888 + NS_ENSURE_SUCCESS(rv, rv); 1.889 + 1.890 + rv = serv->EvictEntries(nsICache::STORE_OFFLINE); 1.891 + NS_ENSURE_SUCCESS(rv, rv); 1.892 + } 1.893 + else { 1.894 + // Clear app or inbrowser staff. 1.895 + nsCOMPtr<nsIApplicationCacheService> appCacheService = 1.896 + do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv); 1.897 + NS_ENSURE_SUCCESS(rv, rv); 1.898 + 1.899 + rv = appCacheService->DiscardByAppId(mLoadInfo->AppId(), 1.900 + mLoadInfo->IsInBrowserElement()); 1.901 + NS_ENSURE_SUCCESS(rv, rv); 1.902 + } 1.903 + } 1.904 + else { 1.905 + if (mAppCache) { 1.906 + nsCOMPtr<nsICacheSession> session; 1.907 + rv = GetCacheSession(EmptyCString(), 1.908 + mWriteToDisk, mLoadInfo, mAppCache, 1.909 + getter_AddRefs(session)); 1.910 + NS_ENSURE_SUCCESS(rv, rv); 1.911 + 1.912 + rv = session->EvictEntries(); 1.913 + NS_ENSURE_SUCCESS(rv, rv); 1.914 + } 1.915 + else { 1.916 + // Oh, I'll be so happy when session names are gone... 1.917 + nsCOMPtr<nsICacheSession> session; 1.918 + rv = GetCacheSession(NS_LITERAL_CSTRING("http"), 1.919 + mWriteToDisk, mLoadInfo, mAppCache, 1.920 + getter_AddRefs(session)); 1.921 + NS_ENSURE_SUCCESS(rv, rv); 1.922 + 1.923 + rv = session->EvictEntries(); 1.924 + NS_ENSURE_SUCCESS(rv, rv); 1.925 + 1.926 + rv = GetCacheSession(NS_LITERAL_CSTRING("wyciwyg"), 1.927 + mWriteToDisk, mLoadInfo, mAppCache, 1.928 + getter_AddRefs(session)); 1.929 + NS_ENSURE_SUCCESS(rv, rv); 1.930 + 1.931 + rv = session->EvictEntries(); 1.932 + NS_ENSURE_SUCCESS(rv, rv); 1.933 + 1.934 + // This clears any data from scheme other then http, wyciwyg or ftp 1.935 + rv = GetCacheSession(EmptyCString(), 1.936 + mWriteToDisk, mLoadInfo, mAppCache, 1.937 + getter_AddRefs(session)); 1.938 + NS_ENSURE_SUCCESS(rv, rv); 1.939 + 1.940 + rv = session->EvictEntries(); 1.941 + NS_ENSURE_SUCCESS(rv, rv); 1.942 + } 1.943 + } 1.944 + 1.945 + if (aCallback) { 1.946 + nsRefPtr<DoomCallbackSynchronizer> sync = 1.947 + new DoomCallbackSynchronizer(aCallback); 1.948 + rv = sync->Dispatch(); 1.949 + NS_ENSURE_SUCCESS(rv, rv); 1.950 + } 1.951 + 1.952 + return NS_OK; 1.953 +} 1.954 + 1.955 +NS_IMETHODIMP _OldStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisitor, 1.956 + bool aVisitEntries) 1.957 +{ 1.958 + LOG(("_OldStorage::AsyncVisitStorage")); 1.959 + 1.960 + NS_ENSURE_ARG(aVisitor); 1.961 + 1.962 + if (mLoadInfo->IsAnonymous()) { 1.963 + // There is no concept of 'anonymous' storage in the old cache 1.964 + // since anon cache entries are stored in 'non-anon' storage 1.965 + // with a special prefix. 1.966 + // Just fake we have 0 items with 0 consumption. This at least 1.967 + // prevents displaying double size in the advanced section of 1.968 + // the Options dialog. 1.969 + aVisitor->OnCacheStorageInfo(0, 0); 1.970 + if (aVisitEntries) 1.971 + aVisitor->OnCacheEntryVisitCompleted(); 1.972 + return NS_OK; 1.973 + } 1.974 + 1.975 + nsresult rv; 1.976 + 1.977 + nsCOMPtr<nsICacheService> serv = 1.978 + do_GetService(NS_CACHESERVICE_CONTRACTID, &rv); 1.979 + NS_ENSURE_SUCCESS(rv, rv); 1.980 + 1.981 + char* deviceID; 1.982 + if (mAppCache || mOfflineStorage) { 1.983 + deviceID = const_cast<char*>("offline"); 1.984 + } else if (!mWriteToDisk || mLoadInfo->IsPrivate()) { 1.985 + deviceID = const_cast<char*>("memory"); 1.986 + } else { 1.987 + deviceID = const_cast<char*>("disk"); 1.988 + } 1.989 + 1.990 + nsRefPtr<VisitCallbackWrapper> cb = new VisitCallbackWrapper( 1.991 + deviceID, aVisitor, aVisitEntries); 1.992 + rv = serv->VisitEntries(cb); 1.993 + NS_ENSURE_SUCCESS(rv, rv); 1.994 + 1.995 + return NS_OK; 1.996 +} 1.997 + 1.998 +// Internal 1.999 + 1.1000 +nsresult _OldStorage::AssembleCacheKey(nsIURI *aURI, 1.1001 + nsACString const & aIdExtension, 1.1002 + nsACString & aCacheKey, 1.1003 + nsACString & aScheme) 1.1004 +{ 1.1005 + // Copied from nsHttpChannel::AssembleCacheKey 1.1006 + 1.1007 + aCacheKey.Truncate(); 1.1008 + 1.1009 + nsresult rv; 1.1010 + 1.1011 + rv = aURI->GetScheme(aScheme); 1.1012 + NS_ENSURE_SUCCESS(rv, rv); 1.1013 + 1.1014 + nsAutoCString uriSpec; 1.1015 + if (aScheme.Equals(NS_LITERAL_CSTRING("http")) || 1.1016 + aScheme.Equals(NS_LITERAL_CSTRING("https"))) { 1.1017 + if (mLoadInfo->IsAnonymous()) { 1.1018 + aCacheKey.AssignLiteral("anon&"); 1.1019 + } 1.1020 + 1.1021 + if (!aIdExtension.IsEmpty()) { 1.1022 + aCacheKey.AppendPrintf("id=%s&", aIdExtension.BeginReading()); 1.1023 + } 1.1024 + 1.1025 + nsCOMPtr<nsIURI> noRefURI; 1.1026 + rv = aURI->CloneIgnoringRef(getter_AddRefs(noRefURI)); 1.1027 + NS_ENSURE_SUCCESS(rv, rv); 1.1028 + 1.1029 + rv = noRefURI->GetAsciiSpec(uriSpec); 1.1030 + NS_ENSURE_SUCCESS(rv, rv); 1.1031 + 1.1032 + if (!aCacheKey.IsEmpty()) { 1.1033 + aCacheKey.AppendLiteral("uri="); 1.1034 + } 1.1035 + } 1.1036 + else if (aScheme.Equals(NS_LITERAL_CSTRING("wyciwyg"))) { 1.1037 + rv = aURI->GetSpec(uriSpec); 1.1038 + NS_ENSURE_SUCCESS(rv, rv); 1.1039 + } 1.1040 + else { 1.1041 + rv = aURI->GetAsciiSpec(uriSpec); 1.1042 + NS_ENSURE_SUCCESS(rv, rv); 1.1043 + } 1.1044 + 1.1045 + aCacheKey.Append(uriSpec); 1.1046 + 1.1047 + return NS_OK; 1.1048 +} 1.1049 + 1.1050 +nsresult _OldStorage::ChooseApplicationCache(nsCSubstring const &cacheKey, 1.1051 + nsIApplicationCache** aCache) 1.1052 +{ 1.1053 + nsresult rv; 1.1054 + 1.1055 + nsCOMPtr<nsIApplicationCacheService> appCacheService = 1.1056 + do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv); 1.1057 + NS_ENSURE_SUCCESS(rv, rv); 1.1058 + 1.1059 + rv = appCacheService->ChooseApplicationCache(cacheKey, mLoadInfo, aCache); 1.1060 + NS_ENSURE_SUCCESS(rv, rv); 1.1061 + 1.1062 + return NS_OK; 1.1063 +} 1.1064 + 1.1065 +} // net 1.1066 +} // mozilla