netwerk/cache2/OldWrappers.cpp

changeset 2
7e26c7da4463
equal deleted inserted replaced
-1:000000000000 0:0bdf71378d2a
1 // Stuff to link the old imp to the new api - will go away!
2
3 #include "CacheLog.h"
4 #include "OldWrappers.h"
5 #include "CacheStorage.h"
6 #include "CacheStorageService.h"
7 #include "LoadContextInfo.h"
8
9 #include "nsIURI.h"
10 #include "nsICacheService.h"
11 #include "nsICacheSession.h"
12 #include "nsIApplicationCache.h"
13 #include "nsIApplicationCacheService.h"
14 #include "nsIStreamTransportService.h"
15 #include "nsIFile.h"
16 #include "nsICacheEntryDoomCallback.h"
17 #include "nsICacheListener.h"
18 #include "nsICacheStorageVisitor.h"
19
20 #include "nsServiceManagerUtils.h"
21 #include "nsNetCID.h"
22 #include "nsProxyRelease.h"
23 #include "mozilla/Telemetry.h"
24
25 static NS_DEFINE_CID(kStreamTransportServiceCID,
26 NS_STREAMTRANSPORTSERVICE_CID);
27
28 static uint32_t const CHECK_MULTITHREADED = nsICacheStorage::CHECK_MULTITHREADED;
29
30 namespace mozilla {
31 namespace net {
32
33 namespace { // anon
34
35 // Fires the doom callback back on the main thread
36 // after the cache I/O thread is looped.
37
38 class DoomCallbackSynchronizer : public nsRunnable
39 {
40 public:
41 DoomCallbackSynchronizer(nsICacheEntryDoomCallback* cb) : mCB(cb)
42 {
43 MOZ_COUNT_CTOR(DoomCallbackSynchronizer);
44 }
45 nsresult Dispatch();
46
47 private:
48 virtual ~DoomCallbackSynchronizer()
49 {
50 MOZ_COUNT_DTOR(DoomCallbackSynchronizer);
51 }
52
53 NS_DECL_NSIRUNNABLE
54 nsCOMPtr<nsICacheEntryDoomCallback> mCB;
55 };
56
57 nsresult DoomCallbackSynchronizer::Dispatch()
58 {
59 nsresult rv;
60
61 nsCOMPtr<nsICacheService> serv =
62 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
63 NS_ENSURE_SUCCESS(rv, rv);
64
65 nsCOMPtr<nsIEventTarget> eventTarget;
66 rv = serv->GetCacheIOTarget(getter_AddRefs(eventTarget));
67 NS_ENSURE_SUCCESS(rv, rv);
68
69 rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
70 NS_ENSURE_SUCCESS(rv, rv);
71
72 return NS_OK;
73 }
74
75 NS_IMETHODIMP DoomCallbackSynchronizer::Run()
76 {
77 if (!NS_IsMainThread()) {
78 NS_DispatchToMainThread(this);
79 }
80 else {
81 if (mCB)
82 mCB->OnCacheEntryDoomed(NS_OK);
83 }
84 return NS_OK;
85 }
86
87 // Receives doom callback from the old API and forwards to the new API
88
89 class DoomCallbackWrapper : public nsICacheListener
90 {
91 NS_DECL_THREADSAFE_ISUPPORTS
92 NS_DECL_NSICACHELISTENER
93
94 DoomCallbackWrapper(nsICacheEntryDoomCallback* cb) : mCB(cb)
95 {
96 MOZ_COUNT_CTOR(DoomCallbackWrapper);
97 }
98
99 private:
100 virtual ~DoomCallbackWrapper()
101 {
102 MOZ_COUNT_DTOR(DoomCallbackWrapper);
103 }
104
105 nsCOMPtr<nsICacheEntryDoomCallback> mCB;
106 };
107
108 NS_IMPL_ISUPPORTS(DoomCallbackWrapper, nsICacheListener);
109
110 NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryAvailable(nsICacheEntryDescriptor *descriptor,
111 nsCacheAccessMode accessGranted,
112 nsresult status)
113 {
114 return NS_OK;
115 }
116
117 NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryDoomed(nsresult status)
118 {
119 if (!mCB)
120 return NS_ERROR_NULL_POINTER;
121
122 mCB->OnCacheEntryDoomed(status);
123 mCB = nullptr;
124 return NS_OK;
125 }
126
127 // Receives visit callbacks from the old API and forwards it to the new API
128
129 class VisitCallbackWrapper : public nsICacheVisitor
130 {
131 NS_DECL_THREADSAFE_ISUPPORTS
132 NS_DECL_NSICACHEVISITOR
133
134 VisitCallbackWrapper(char* const deviceID,
135 nsICacheStorageVisitor* cb,
136 bool visitEntries)
137 : mCB(cb)
138 , mVisitEntries(visitEntries)
139 , mDeviceID(deviceID)
140 {
141 MOZ_COUNT_CTOR(VisitCallbackWrapper);
142 }
143
144 private:
145 virtual ~VisitCallbackWrapper();
146 nsCOMPtr<nsICacheStorageVisitor> mCB;
147 bool mVisitEntries;
148 char* const mDeviceID;
149 };
150
151 NS_IMPL_ISUPPORTS(VisitCallbackWrapper, nsICacheVisitor)
152
153 VisitCallbackWrapper::~VisitCallbackWrapper()
154 {
155 if (mVisitEntries)
156 mCB->OnCacheEntryVisitCompleted();
157
158 MOZ_COUNT_DTOR(VisitCallbackWrapper);
159 }
160
161 NS_IMETHODIMP VisitCallbackWrapper::VisitDevice(const char * deviceID,
162 nsICacheDeviceInfo *deviceInfo,
163 bool *_retval)
164 {
165 if (!mCB)
166 return NS_ERROR_NULL_POINTER;
167
168 *_retval = false;
169 if (strcmp(deviceID, mDeviceID)) {
170 // Not the device we want to visit
171 return NS_OK;
172 }
173
174 nsresult rv;
175
176 uint32_t entryCount;
177 rv = deviceInfo->GetEntryCount(&entryCount);
178 NS_ENSURE_SUCCESS(rv, rv);
179
180 uint32_t totalSize;
181 rv = deviceInfo->GetTotalSize(&totalSize);
182 NS_ENSURE_SUCCESS(rv, rv);
183
184 mCB->OnCacheStorageInfo(entryCount, totalSize);
185 *_retval = mVisitEntries;
186
187 return NS_OK;
188 }
189
190 NS_IMETHODIMP VisitCallbackWrapper::VisitEntry(const char * deviceID,
191 nsICacheEntryInfo *entryInfo,
192 bool *_retval)
193 {
194 MOZ_ASSERT(!strcmp(deviceID, mDeviceID));
195
196 nsRefPtr<_OldCacheEntryWrapper> wrapper = new _OldCacheEntryWrapper(entryInfo);
197 nsresult rv = mCB->OnCacheEntryInfo(wrapper);
198 *_retval = NS_SUCCEEDED(rv);
199
200 return NS_OK;
201 }
202
203 } // anon
204
205
206 // _OldGetDiskConsumption
207
208 //static
209 nsresult _OldGetDiskConsumption::Get(nsICacheStorageConsumptionObserver* aCallback)
210 {
211 nsresult rv;
212
213 nsCOMPtr<nsICacheService> serv =
214 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
215 NS_ENSURE_SUCCESS(rv, rv);
216
217 nsRefPtr<_OldGetDiskConsumption> cb = new _OldGetDiskConsumption(aCallback);
218
219 // _OldGetDiskConsumption stores the found size value, but until dispatched
220 // to the main thread it doesn't call on the consupmtion observer. See bellow.
221 rv = serv->VisitEntries(cb);
222 NS_ENSURE_SUCCESS(rv, rv);
223
224 // We are called from CacheStorageService::AsyncGetDiskConsumption whose IDL
225 // documentation claims the callback is always delievered asynchronously
226 // back to the main thread. Despite we know the result synchronosusly when
227 // querying the old cache, we need to stand the word and dispatch the result
228 // to the main thread asynchronously. Hence the dispatch here.
229 return NS_DispatchToMainThread(cb);
230 }
231
232 NS_IMPL_ISUPPORTS_INHERITED(_OldGetDiskConsumption,
233 nsRunnable,
234 nsICacheVisitor)
235
236 _OldGetDiskConsumption::_OldGetDiskConsumption(
237 nsICacheStorageConsumptionObserver* aCallback)
238 : mCallback(aCallback)
239 , mSize(0)
240 {
241 }
242
243 NS_IMETHODIMP
244 _OldGetDiskConsumption::Run()
245 {
246 mCallback->OnNetworkCacheDiskConsumption(mSize);
247 return NS_OK;
248 }
249
250 NS_IMETHODIMP
251 _OldGetDiskConsumption::VisitDevice(const char * deviceID,
252 nsICacheDeviceInfo *deviceInfo,
253 bool *_retval)
254 {
255 if (!strcmp(deviceID, "disk")) {
256 uint32_t size;
257 nsresult rv = deviceInfo->GetTotalSize(&size);
258 if (NS_SUCCEEDED(rv))
259 mSize = (int64_t)size;
260 }
261
262 *_retval = false;
263 return NS_OK;
264 }
265
266 NS_IMETHODIMP
267 _OldGetDiskConsumption::VisitEntry(const char * deviceID,
268 nsICacheEntryInfo *entryInfo,
269 bool *_retval)
270 {
271 MOZ_CRASH("Unexpected");
272 return NS_OK;
273 }
274
275
276 // _OldCacheEntryWrapper
277
278 _OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryDescriptor* desc)
279 : mOldDesc(desc), mOldInfo(desc)
280 {
281 MOZ_COUNT_CTOR(_OldCacheEntryWrapper);
282 LOG(("Creating _OldCacheEntryWrapper %p for descriptor %p", this, desc));
283 }
284
285 _OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryInfo* info)
286 : mOldDesc(nullptr), mOldInfo(info)
287 {
288 MOZ_COUNT_CTOR(_OldCacheEntryWrapper);
289 LOG(("Creating _OldCacheEntryWrapper %p for info %p", this, info));
290 }
291
292 _OldCacheEntryWrapper::~_OldCacheEntryWrapper()
293 {
294 MOZ_COUNT_DTOR(_OldCacheEntryWrapper);
295 LOG(("Destroying _OldCacheEntryWrapper %p for descriptor %p", this, mOldInfo.get()));
296 }
297
298 NS_IMPL_ISUPPORTS(_OldCacheEntryWrapper, nsICacheEntry)
299
300 NS_IMETHODIMP _OldCacheEntryWrapper::AsyncDoom(nsICacheEntryDoomCallback* listener)
301 {
302 nsRefPtr<DoomCallbackWrapper> cb = listener
303 ? new DoomCallbackWrapper(listener)
304 : nullptr;
305 return AsyncDoom(cb);
306 }
307
308 NS_IMETHODIMP _OldCacheEntryWrapper::GetDataSize(int64_t *aSize)
309 {
310 uint32_t size;
311 nsresult rv = GetDataSize(&size);
312 if (NS_FAILED(rv))
313 return rv;
314
315 *aSize = size;
316 return NS_OK;
317 }
318
319 NS_IMETHODIMP _OldCacheEntryWrapper::GetPersistent(bool *aPersistToDisk)
320 {
321 if (!mOldDesc) {
322 return NS_ERROR_NULL_POINTER;
323 }
324
325 nsresult rv;
326
327 nsCacheStoragePolicy policy;
328 rv = mOldDesc->GetStoragePolicy(&policy);
329 NS_ENSURE_SUCCESS(rv, rv);
330
331 *aPersistToDisk = policy != nsICache::STORE_IN_MEMORY;
332
333 return NS_OK;
334 }
335
336 NS_IMETHODIMP _OldCacheEntryWrapper::Recreate(bool aMemoryOnly,
337 nsICacheEntry** aResult)
338 {
339 NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NOT_AVAILABLE);
340
341 nsCacheAccessMode mode;
342 nsresult rv = mOldDesc->GetAccessGranted(&mode);
343 NS_ENSURE_SUCCESS(rv, rv);
344
345 if (!(mode & nsICache::ACCESS_WRITE))
346 return NS_ERROR_NOT_AVAILABLE;
347
348 LOG(("_OldCacheEntryWrapper::Recreate [this=%p]", this));
349
350 if (aMemoryOnly)
351 mOldDesc->SetStoragePolicy(nsICache::STORE_IN_MEMORY);
352
353 nsCOMPtr<nsICacheEntry> self(this);
354 self.forget(aResult);
355 return NS_OK;
356 }
357
358 NS_IMETHODIMP _OldCacheEntryWrapper::OpenInputStream(int64_t offset,
359 nsIInputStream * *_retval)
360 {
361 if (offset > PR_UINT32_MAX)
362 return NS_ERROR_INVALID_ARG;
363
364 return OpenInputStream(uint32_t(offset), _retval);
365 }
366 NS_IMETHODIMP _OldCacheEntryWrapper::OpenOutputStream(int64_t offset,
367 nsIOutputStream * *_retval)
368 {
369 if (offset > PR_UINT32_MAX)
370 return NS_ERROR_INVALID_ARG;
371
372 return OpenOutputStream(uint32_t(offset), _retval);
373 }
374
375 NS_IMETHODIMP _OldCacheEntryWrapper::MaybeMarkValid()
376 {
377 LOG(("_OldCacheEntryWrapper::MaybeMarkValid [this=%p]", this));
378
379 NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NULL_POINTER);
380
381 nsCacheAccessMode mode;
382 nsresult rv = mOldDesc->GetAccessGranted(&mode);
383 NS_ENSURE_SUCCESS(rv, rv);
384
385 if (mode & nsICache::ACCESS_WRITE) {
386 LOG(("Marking cache entry valid [entry=%p, descr=%p]", this, mOldDesc));
387 return mOldDesc->MarkValid();
388 }
389
390 LOG(("Not marking read-only cache entry valid [entry=%p, descr=%p]", this, mOldDesc));
391 return NS_OK;
392 }
393
394 NS_IMETHODIMP _OldCacheEntryWrapper::HasWriteAccess(bool aWriteAllowed_unused, bool *aWriteAccess)
395 {
396 NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NULL_POINTER);
397 NS_ENSURE_ARG(aWriteAccess);
398
399 nsCacheAccessMode mode;
400 nsresult rv = mOldDesc->GetAccessGranted(&mode);
401 NS_ENSURE_SUCCESS(rv, rv);
402
403 *aWriteAccess = !!(mode & nsICache::ACCESS_WRITE);
404
405 LOG(("_OldCacheEntryWrapper::HasWriteAccess [this=%p, write-access=%d]", this, *aWriteAccess));
406
407 return NS_OK;
408 }
409
410
411 namespace { // anon
412
413 nsresult
414 GetCacheSessionNameForStoragePolicy(
415 nsCSubstring const &scheme,
416 nsCacheStoragePolicy storagePolicy,
417 bool isPrivate,
418 uint32_t appId,
419 bool inBrowser,
420 nsACString& sessionName)
421 {
422 MOZ_ASSERT(!isPrivate || storagePolicy == nsICache::STORE_IN_MEMORY);
423
424 // HTTP
425 if (scheme.Equals(NS_LITERAL_CSTRING("http")) ||
426 scheme.Equals(NS_LITERAL_CSTRING("https"))) {
427 switch (storagePolicy) {
428 case nsICache::STORE_IN_MEMORY:
429 if (isPrivate)
430 sessionName.Assign(NS_LITERAL_CSTRING("HTTP-memory-only-PB"));
431 else
432 sessionName.Assign(NS_LITERAL_CSTRING("HTTP-memory-only"));
433 break;
434 case nsICache::STORE_OFFLINE:
435 // XXX This is actually never used, only added to prevent
436 // any compatibility damage.
437 sessionName.Assign(NS_LITERAL_CSTRING("HTTP-offline"));
438 break;
439 default:
440 sessionName.Assign(NS_LITERAL_CSTRING("HTTP"));
441 break;
442 }
443 }
444 // WYCIWYG
445 else if (scheme.Equals(NS_LITERAL_CSTRING("wyciwyg"))) {
446 if (isPrivate)
447 sessionName.Assign(NS_LITERAL_CSTRING("wyciwyg-private"));
448 else
449 sessionName.Assign(NS_LITERAL_CSTRING("wyciwyg"));
450 }
451 // FTP
452 else if (scheme.Equals(NS_LITERAL_CSTRING("ftp"))) {
453 if (isPrivate)
454 sessionName.Assign(NS_LITERAL_CSTRING("FTP-private"));
455 else
456 sessionName.Assign(NS_LITERAL_CSTRING("FTP"));
457 }
458 // all remaining URL scheme
459 else {
460 // Since with the new API a consumer cannot specify its own session name
461 // and partitioning of the cache is handled stricly only by the cache
462 // back-end internally, we will use a separate session name to pretend
463 // functionality of the new API wrapping the Darin's cache for all other
464 // URL schemes.
465 // Deliberately omitting |anonymous| since other session types don't
466 // recognize it too.
467 sessionName.Assign(NS_LITERAL_CSTRING("other"));
468 if (isPrivate)
469 sessionName.Append(NS_LITERAL_CSTRING("-private"));
470 }
471
472 if (appId != nsILoadContextInfo::NO_APP_ID || inBrowser) {
473 sessionName.Append('~');
474 sessionName.AppendInt(appId);
475 sessionName.Append('~');
476 sessionName.AppendInt(inBrowser);
477 }
478
479 return NS_OK;
480 }
481
482 nsresult
483 GetCacheSession(nsCSubstring const &aScheme,
484 bool aWriteToDisk,
485 nsILoadContextInfo* aLoadInfo,
486 nsIApplicationCache* aAppCache,
487 nsICacheSession** _result)
488 {
489 nsresult rv;
490
491 nsCacheStoragePolicy storagePolicy;
492 if (aAppCache)
493 storagePolicy = nsICache::STORE_OFFLINE;
494 else if (!aWriteToDisk || aLoadInfo->IsPrivate())
495 storagePolicy = nsICache::STORE_IN_MEMORY;
496 else
497 storagePolicy = nsICache::STORE_ANYWHERE;
498
499 nsAutoCString clientId;
500 if (aAppCache) {
501 aAppCache->GetClientID(clientId);
502 }
503 else {
504 rv = GetCacheSessionNameForStoragePolicy(
505 aScheme,
506 storagePolicy,
507 aLoadInfo->IsPrivate(),
508 aLoadInfo->AppId(),
509 aLoadInfo->IsInBrowserElement(),
510 clientId);
511 NS_ENSURE_SUCCESS(rv, rv);
512 }
513
514 LOG((" GetCacheSession for client=%s, policy=%d", clientId.get(), storagePolicy));
515
516 nsCOMPtr<nsICacheService> serv =
517 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
518 NS_ENSURE_SUCCESS(rv, rv);
519
520 nsCOMPtr<nsICacheSession> session;
521 rv = serv->CreateSession(clientId.get(),
522 storagePolicy,
523 nsICache::STREAM_BASED,
524 getter_AddRefs(session));
525 NS_ENSURE_SUCCESS(rv, rv);
526
527 rv = session->SetIsPrivate(aLoadInfo->IsPrivate());
528 NS_ENSURE_SUCCESS(rv, rv);
529
530 rv = session->SetDoomEntriesIfExpired(false);
531 NS_ENSURE_SUCCESS(rv, rv);
532
533 if (aAppCache) {
534 nsCOMPtr<nsIFile> profileDirectory;
535 aAppCache->GetProfileDirectory(getter_AddRefs(profileDirectory));
536 if (profileDirectory)
537 rv = session->SetProfileDirectory(profileDirectory);
538 NS_ENSURE_SUCCESS(rv, rv);
539 }
540
541 session.forget(_result);
542 return NS_OK;
543 }
544
545 } // anon
546
547
548 NS_IMPL_ISUPPORTS_INHERITED(_OldCacheLoad, nsRunnable, nsICacheListener)
549
550 _OldCacheLoad::_OldCacheLoad(nsCSubstring const& aScheme,
551 nsCSubstring const& aCacheKey,
552 nsICacheEntryOpenCallback* aCallback,
553 nsIApplicationCache* aAppCache,
554 nsILoadContextInfo* aLoadInfo,
555 bool aWriteToDisk,
556 uint32_t aFlags)
557 : mScheme(aScheme)
558 , mCacheKey(aCacheKey)
559 , mCallback(aCallback)
560 , mLoadInfo(GetLoadContextInfo(aLoadInfo))
561 , mFlags(aFlags)
562 , mWriteToDisk(aWriteToDisk)
563 , mNew(true)
564 , mOpening(true)
565 , mSync(false)
566 , mStatus(NS_ERROR_UNEXPECTED)
567 , mRunCount(0)
568 , mAppCache(aAppCache)
569 {
570 MOZ_COUNT_CTOR(_OldCacheLoad);
571 }
572
573 _OldCacheLoad::~_OldCacheLoad()
574 {
575 ProxyReleaseMainThread(mAppCache);
576 MOZ_COUNT_DTOR(_OldCacheLoad);
577 }
578
579 nsresult _OldCacheLoad::Start()
580 {
581 LOG(("_OldCacheLoad::Start [this=%p, key=%s]", this, mCacheKey.get()));
582
583 mLoadStart = mozilla::TimeStamp::Now();
584
585 nsresult rv;
586
587 // Consumers that can invoke this code as first and off the main thread
588 // are responsible for initiating these two services on the main thread.
589 // Currently this is only nsWyciwygChannel.
590
591 // XXX: Start the cache service; otherwise DispatchToCacheIOThread will
592 // fail.
593 nsCOMPtr<nsICacheService> service =
594 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
595
596 // Ensure the stream transport service gets initialized on the main thread
597 if (NS_SUCCEEDED(rv) && NS_IsMainThread()) {
598 nsCOMPtr<nsIStreamTransportService> sts =
599 do_GetService(kStreamTransportServiceCID, &rv);
600 }
601
602 if (NS_SUCCEEDED(rv)) {
603 rv = service->GetCacheIOTarget(getter_AddRefs(mCacheThread));
604 }
605
606 if (NS_SUCCEEDED(rv)) {
607 bool onCacheTarget;
608 rv = mCacheThread->IsOnCurrentThread(&onCacheTarget);
609 if (NS_SUCCEEDED(rv) && onCacheTarget) {
610 mSync = true;
611 }
612 }
613
614 if (NS_SUCCEEDED(rv)) {
615 if (mSync) {
616 rv = Run();
617 }
618 else {
619 rv = mCacheThread->Dispatch(this, NS_DISPATCH_NORMAL);
620 }
621 }
622
623 return rv;
624 }
625
626 NS_IMETHODIMP
627 _OldCacheLoad::Run()
628 {
629 LOG(("_OldCacheLoad::Run [this=%p, key=%s, cb=%p]", this, mCacheKey.get(), mCallback.get()));
630
631 nsresult rv;
632
633 if (mOpening) {
634 mOpening = false;
635 nsCOMPtr<nsICacheSession> session;
636 rv = GetCacheSession(mScheme, mWriteToDisk, mLoadInfo, mAppCache,
637 getter_AddRefs(session));
638 if (NS_SUCCEEDED(rv)) {
639 // AsyncOpenCacheEntry isn't really async when its called on the
640 // cache service thread.
641
642 nsCacheAccessMode cacheAccess;
643 if (mFlags & nsICacheStorage::OPEN_TRUNCATE)
644 cacheAccess = nsICache::ACCESS_WRITE;
645 else if ((mFlags & nsICacheStorage::OPEN_READONLY) || mAppCache)
646 cacheAccess = nsICache::ACCESS_READ;
647 else
648 cacheAccess = nsICache::ACCESS_READ_WRITE;
649
650 LOG((" session->AsyncOpenCacheEntry with access=%d", cacheAccess));
651
652 bool bypassBusy = mFlags & nsICacheStorage::OPEN_BYPASS_IF_BUSY;
653
654 if (mSync && cacheAccess == nsICache::ACCESS_WRITE) {
655 nsCOMPtr<nsICacheEntryDescriptor> entry;
656 rv = session->OpenCacheEntry(mCacheKey, cacheAccess, bypassBusy,
657 getter_AddRefs(entry));
658
659 nsCacheAccessMode grantedAccess = 0;
660 if (NS_SUCCEEDED(rv)) {
661 entry->GetAccessGranted(&grantedAccess);
662 }
663
664 return OnCacheEntryAvailable(entry, grantedAccess, rv);
665 }
666
667 rv = session->AsyncOpenCacheEntry(mCacheKey, cacheAccess, this, bypassBusy);
668 if (NS_SUCCEEDED(rv))
669 return NS_OK;
670 }
671
672 // Opening failed, propagate the error to the consumer
673 LOG((" Opening cache entry failed with rv=0x%08x", rv));
674 mStatus = rv;
675 mNew = false;
676 NS_DispatchToMainThread(this);
677 } else {
678 if (!mCallback) {
679 LOG((" duplicate call, bypassed"));
680 return NS_OK;
681 }
682
683 if (NS_SUCCEEDED(mStatus)) {
684 if (mFlags & nsICacheStorage::OPEN_TRUNCATE) {
685 mozilla::Telemetry::AccumulateTimeDelta(
686 mozilla::Telemetry::NETWORK_CACHE_V1_TRUNCATE_TIME_MS,
687 mLoadStart);
688 }
689 else if (mNew) {
690 mozilla::Telemetry::AccumulateTimeDelta(
691 mozilla::Telemetry::NETWORK_CACHE_V1_MISS_TIME_MS,
692 mLoadStart);
693 }
694 else {
695 mozilla::Telemetry::AccumulateTimeDelta(
696 mozilla::Telemetry::NETWORK_CACHE_V1_HIT_TIME_MS,
697 mLoadStart);
698 }
699 }
700
701 if (!(mFlags & CHECK_MULTITHREADED))
702 Check();
703
704 // break cycles
705 nsCOMPtr<nsICacheEntryOpenCallback> cb = mCallback.forget();
706 mCacheThread = nullptr;
707 nsCOMPtr<nsICacheEntry> entry = mCacheEntry.forget();
708
709 rv = cb->OnCacheEntryAvailable(entry, mNew, mAppCache, mStatus);
710
711 if (NS_FAILED(rv) && entry) {
712 LOG((" cb->OnCacheEntryAvailable failed with rv=0x%08x", rv));
713 if (mNew)
714 entry->AsyncDoom(nullptr);
715 else
716 entry->Close();
717 }
718 }
719
720 return rv;
721 }
722
723 NS_IMETHODIMP
724 _OldCacheLoad::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
725 nsCacheAccessMode access,
726 nsresult status)
727 {
728 LOG(("_OldCacheLoad::OnCacheEntryAvailable [this=%p, ent=%p, cb=%p, appcache=%p, access=%x]",
729 this, entry, mCallback.get(), mAppCache.get(), access));
730
731 // XXX Bug 759805: Sometimes we will call this method directly from
732 // HttpCacheQuery::Run when AsyncOpenCacheEntry fails, but
733 // AsyncOpenCacheEntry will also call this method. As a workaround, we just
734 // ensure we only execute this code once.
735 NS_ENSURE_TRUE(mRunCount == 0, NS_ERROR_UNEXPECTED);
736 ++mRunCount;
737
738 mCacheEntry = entry ? new _OldCacheEntryWrapper(entry) : nullptr;
739 mStatus = status;
740 mNew = access == nsICache::ACCESS_WRITE;
741
742 if (mFlags & CHECK_MULTITHREADED)
743 Check();
744
745 if (mSync)
746 return Run();
747
748 return NS_DispatchToMainThread(this);
749 }
750
751 void
752 _OldCacheLoad::Check()
753 {
754 if (!mCacheEntry)
755 return;
756
757 if (mNew)
758 return;
759
760 uint32_t result;
761 nsresult rv = mCallback->OnCacheEntryCheck(mCacheEntry, mAppCache, &result);
762 LOG((" OnCacheEntryCheck result ent=%p, cb=%p, appcache=%p, rv=0x%08x, result=%d",
763 mCacheEntry.get(), mCallback.get(), mAppCache.get(), rv, result));
764
765 if (NS_FAILED(rv)) {
766 NS_WARNING("cache check failed");
767 }
768
769 if (NS_FAILED(rv) || result == nsICacheEntryOpenCallback::ENTRY_NOT_WANTED) {
770 mCacheEntry->Close();
771 mCacheEntry = nullptr;
772 mStatus = NS_ERROR_CACHE_KEY_NOT_FOUND;
773 }
774 }
775
776 NS_IMETHODIMP
777 _OldCacheLoad::OnCacheEntryDoomed(nsresult)
778 {
779 return NS_ERROR_NOT_IMPLEMENTED;
780 }
781
782 // nsICacheStorage old cache wrapper
783
784 NS_IMPL_ISUPPORTS(_OldStorage, nsICacheStorage)
785
786 _OldStorage::_OldStorage(nsILoadContextInfo* aInfo,
787 bool aAllowDisk,
788 bool aLookupAppCache,
789 bool aOfflineStorage,
790 nsIApplicationCache* aAppCache)
791 : mLoadInfo(GetLoadContextInfo(aInfo))
792 , mAppCache(aAppCache)
793 , mWriteToDisk(aAllowDisk)
794 , mLookupAppCache(aLookupAppCache)
795 , mOfflineStorage(aOfflineStorage)
796 {
797 MOZ_COUNT_CTOR(_OldStorage);
798 }
799
800 _OldStorage::~_OldStorage()
801 {
802 MOZ_COUNT_DTOR(_OldStorage);
803 }
804
805 NS_IMETHODIMP _OldStorage::AsyncOpenURI(nsIURI *aURI,
806 const nsACString & aIdExtension,
807 uint32_t aFlags,
808 nsICacheEntryOpenCallback *aCallback)
809 {
810 NS_ENSURE_ARG(aURI);
811 NS_ENSURE_ARG(aCallback);
812
813 #ifdef MOZ_LOGGING
814 nsAutoCString uriSpec;
815 aURI->GetAsciiSpec(uriSpec);
816 LOG(("_OldStorage::AsyncOpenURI [this=%p, uri=%s, ide=%s, flags=%x]",
817 this, uriSpec.get(), aIdExtension.BeginReading(), aFlags));
818 #endif
819
820 nsresult rv;
821
822 nsAutoCString cacheKey, scheme;
823 rv = AssembleCacheKey(aURI, aIdExtension, cacheKey, scheme);
824 NS_ENSURE_SUCCESS(rv, rv);
825
826 if (!mAppCache && (mLookupAppCache || mOfflineStorage)) {
827 rv = ChooseApplicationCache(cacheKey, getter_AddRefs(mAppCache));
828 NS_ENSURE_SUCCESS(rv, rv);
829
830 if (mAppCache) {
831 // From a chosen appcache open only as readonly
832 aFlags &= ~nsICacheStorage::OPEN_TRUNCATE;
833 }
834 }
835
836 nsRefPtr<_OldCacheLoad> cacheLoad =
837 new _OldCacheLoad(scheme, cacheKey, aCallback, mAppCache,
838 mLoadInfo, mWriteToDisk, aFlags);
839
840 rv = cacheLoad->Start();
841 NS_ENSURE_SUCCESS(rv, rv);
842
843 return NS_OK;
844 }
845
846 NS_IMETHODIMP _OldStorage::AsyncDoomURI(nsIURI *aURI, const nsACString & aIdExtension,
847 nsICacheEntryDoomCallback* aCallback)
848 {
849 LOG(("_OldStorage::AsyncDoomURI"));
850
851 nsresult rv;
852
853 nsAutoCString cacheKey, scheme;
854 rv = AssembleCacheKey(aURI, aIdExtension, cacheKey, scheme);
855 NS_ENSURE_SUCCESS(rv, rv);
856
857 nsCOMPtr<nsICacheSession> session;
858 rv = GetCacheSession(scheme, mWriteToDisk, mLoadInfo, mAppCache,
859 getter_AddRefs(session));
860 NS_ENSURE_SUCCESS(rv, rv);
861
862 nsRefPtr<DoomCallbackWrapper> cb = aCallback
863 ? new DoomCallbackWrapper(aCallback)
864 : nullptr;
865 rv = session->DoomEntry(cacheKey, cb);
866 NS_ENSURE_SUCCESS(rv, rv);
867
868 return NS_OK;
869 }
870
871 NS_IMETHODIMP _OldStorage::AsyncEvictStorage(nsICacheEntryDoomCallback* aCallback)
872 {
873 LOG(("_OldStorage::AsyncEvictStorage"));
874
875 nsresult rv;
876
877 if (!mAppCache && mOfflineStorage) {
878 // Special casing for pure offline storage
879 if (mLoadInfo->AppId() == nsILoadContextInfo::NO_APP_ID &&
880 !mLoadInfo->IsInBrowserElement()) {
881
882 // Clear everything.
883 nsCOMPtr<nsICacheService> serv =
884 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
885 NS_ENSURE_SUCCESS(rv, rv);
886
887 rv = serv->EvictEntries(nsICache::STORE_OFFLINE);
888 NS_ENSURE_SUCCESS(rv, rv);
889 }
890 else {
891 // Clear app or inbrowser staff.
892 nsCOMPtr<nsIApplicationCacheService> appCacheService =
893 do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
894 NS_ENSURE_SUCCESS(rv, rv);
895
896 rv = appCacheService->DiscardByAppId(mLoadInfo->AppId(),
897 mLoadInfo->IsInBrowserElement());
898 NS_ENSURE_SUCCESS(rv, rv);
899 }
900 }
901 else {
902 if (mAppCache) {
903 nsCOMPtr<nsICacheSession> session;
904 rv = GetCacheSession(EmptyCString(),
905 mWriteToDisk, mLoadInfo, mAppCache,
906 getter_AddRefs(session));
907 NS_ENSURE_SUCCESS(rv, rv);
908
909 rv = session->EvictEntries();
910 NS_ENSURE_SUCCESS(rv, rv);
911 }
912 else {
913 // Oh, I'll be so happy when session names are gone...
914 nsCOMPtr<nsICacheSession> session;
915 rv = GetCacheSession(NS_LITERAL_CSTRING("http"),
916 mWriteToDisk, mLoadInfo, mAppCache,
917 getter_AddRefs(session));
918 NS_ENSURE_SUCCESS(rv, rv);
919
920 rv = session->EvictEntries();
921 NS_ENSURE_SUCCESS(rv, rv);
922
923 rv = GetCacheSession(NS_LITERAL_CSTRING("wyciwyg"),
924 mWriteToDisk, mLoadInfo, mAppCache,
925 getter_AddRefs(session));
926 NS_ENSURE_SUCCESS(rv, rv);
927
928 rv = session->EvictEntries();
929 NS_ENSURE_SUCCESS(rv, rv);
930
931 // This clears any data from scheme other then http, wyciwyg or ftp
932 rv = GetCacheSession(EmptyCString(),
933 mWriteToDisk, mLoadInfo, mAppCache,
934 getter_AddRefs(session));
935 NS_ENSURE_SUCCESS(rv, rv);
936
937 rv = session->EvictEntries();
938 NS_ENSURE_SUCCESS(rv, rv);
939 }
940 }
941
942 if (aCallback) {
943 nsRefPtr<DoomCallbackSynchronizer> sync =
944 new DoomCallbackSynchronizer(aCallback);
945 rv = sync->Dispatch();
946 NS_ENSURE_SUCCESS(rv, rv);
947 }
948
949 return NS_OK;
950 }
951
952 NS_IMETHODIMP _OldStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisitor,
953 bool aVisitEntries)
954 {
955 LOG(("_OldStorage::AsyncVisitStorage"));
956
957 NS_ENSURE_ARG(aVisitor);
958
959 if (mLoadInfo->IsAnonymous()) {
960 // There is no concept of 'anonymous' storage in the old cache
961 // since anon cache entries are stored in 'non-anon' storage
962 // with a special prefix.
963 // Just fake we have 0 items with 0 consumption. This at least
964 // prevents displaying double size in the advanced section of
965 // the Options dialog.
966 aVisitor->OnCacheStorageInfo(0, 0);
967 if (aVisitEntries)
968 aVisitor->OnCacheEntryVisitCompleted();
969 return NS_OK;
970 }
971
972 nsresult rv;
973
974 nsCOMPtr<nsICacheService> serv =
975 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
976 NS_ENSURE_SUCCESS(rv, rv);
977
978 char* deviceID;
979 if (mAppCache || mOfflineStorage) {
980 deviceID = const_cast<char*>("offline");
981 } else if (!mWriteToDisk || mLoadInfo->IsPrivate()) {
982 deviceID = const_cast<char*>("memory");
983 } else {
984 deviceID = const_cast<char*>("disk");
985 }
986
987 nsRefPtr<VisitCallbackWrapper> cb = new VisitCallbackWrapper(
988 deviceID, aVisitor, aVisitEntries);
989 rv = serv->VisitEntries(cb);
990 NS_ENSURE_SUCCESS(rv, rv);
991
992 return NS_OK;
993 }
994
995 // Internal
996
997 nsresult _OldStorage::AssembleCacheKey(nsIURI *aURI,
998 nsACString const & aIdExtension,
999 nsACString & aCacheKey,
1000 nsACString & aScheme)
1001 {
1002 // Copied from nsHttpChannel::AssembleCacheKey
1003
1004 aCacheKey.Truncate();
1005
1006 nsresult rv;
1007
1008 rv = aURI->GetScheme(aScheme);
1009 NS_ENSURE_SUCCESS(rv, rv);
1010
1011 nsAutoCString uriSpec;
1012 if (aScheme.Equals(NS_LITERAL_CSTRING("http")) ||
1013 aScheme.Equals(NS_LITERAL_CSTRING("https"))) {
1014 if (mLoadInfo->IsAnonymous()) {
1015 aCacheKey.AssignLiteral("anon&");
1016 }
1017
1018 if (!aIdExtension.IsEmpty()) {
1019 aCacheKey.AppendPrintf("id=%s&", aIdExtension.BeginReading());
1020 }
1021
1022 nsCOMPtr<nsIURI> noRefURI;
1023 rv = aURI->CloneIgnoringRef(getter_AddRefs(noRefURI));
1024 NS_ENSURE_SUCCESS(rv, rv);
1025
1026 rv = noRefURI->GetAsciiSpec(uriSpec);
1027 NS_ENSURE_SUCCESS(rv, rv);
1028
1029 if (!aCacheKey.IsEmpty()) {
1030 aCacheKey.AppendLiteral("uri=");
1031 }
1032 }
1033 else if (aScheme.Equals(NS_LITERAL_CSTRING("wyciwyg"))) {
1034 rv = aURI->GetSpec(uriSpec);
1035 NS_ENSURE_SUCCESS(rv, rv);
1036 }
1037 else {
1038 rv = aURI->GetAsciiSpec(uriSpec);
1039 NS_ENSURE_SUCCESS(rv, rv);
1040 }
1041
1042 aCacheKey.Append(uriSpec);
1043
1044 return NS_OK;
1045 }
1046
1047 nsresult _OldStorage::ChooseApplicationCache(nsCSubstring const &cacheKey,
1048 nsIApplicationCache** aCache)
1049 {
1050 nsresult rv;
1051
1052 nsCOMPtr<nsIApplicationCacheService> appCacheService =
1053 do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
1054 NS_ENSURE_SUCCESS(rv, rv);
1055
1056 rv = appCacheService->ChooseApplicationCache(cacheKey, mLoadInfo, aCache);
1057 NS_ENSURE_SUCCESS(rv, rv);
1058
1059 return NS_OK;
1060 }
1061
1062 } // net
1063 } // mozilla

mercurial