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