Bug 1895742 - Return HandledByContent for touches prevented by touch-action. r=botond...
[gecko.git] / netwerk / cache2 / CacheFileContextEvictor.cpp
blob1f0792759afbc92b1bbd1310b366396c67406e10
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "CacheLog.h"
6 #include "CacheFileContextEvictor.h"
7 #include "CacheFileIOManager.h"
8 #include "CacheFileMetadata.h"
9 #include "CacheIndex.h"
10 #include "CacheIndexIterator.h"
11 #include "CacheFileUtils.h"
12 #include "CacheObserver.h"
13 #include "nsIFile.h"
14 #include "LoadContextInfo.h"
15 #include "nsThreadUtils.h"
16 #include "nsString.h"
17 #include "nsIDirectoryEnumerator.h"
18 #include "mozilla/Base64.h"
19 #include "mozilla/IntegerPrintfMacros.h"
20 #include "nsContentUtils.h"
21 #include "nsNetUtil.h"
23 namespace mozilla::net {
25 #define CONTEXT_EVICTION_PREFIX "ce_"
26 const uint32_t kContextEvictionPrefixLength =
27 sizeof(CONTEXT_EVICTION_PREFIX) - 1;
29 bool CacheFileContextEvictor::sDiskAlreadySearched = false;
31 CacheFileContextEvictor::CacheFileContextEvictor() {
32 LOG(("CacheFileContextEvictor::CacheFileContextEvictor() [this=%p]", this));
35 CacheFileContextEvictor::~CacheFileContextEvictor() {
36 LOG(("CacheFileContextEvictor::~CacheFileContextEvictor() [this=%p]", this));
39 nsresult CacheFileContextEvictor::Init(nsIFile* aCacheDirectory) {
40 LOG(("CacheFileContextEvictor::Init()"));
42 nsresult rv;
44 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
46 CacheIndex::IsUpToDate(&mIndexIsUpToDate);
48 mCacheDirectory = aCacheDirectory;
50 rv = aCacheDirectory->Clone(getter_AddRefs(mEntriesDir));
51 if (NS_WARN_IF(NS_FAILED(rv))) {
52 return rv;
55 rv = mEntriesDir->AppendNative(nsLiteralCString(ENTRIES_DIR));
56 if (NS_WARN_IF(NS_FAILED(rv))) {
57 return rv;
60 if (!sDiskAlreadySearched) {
61 LoadEvictInfoFromDisk();
62 if ((mEntries.Length() != 0) && mIndexIsUpToDate) {
63 CreateIterators();
64 StartEvicting();
68 return NS_OK;
71 void CacheFileContextEvictor::Shutdown() {
72 LOG(("CacheFileContextEvictor::Shutdown()"));
74 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
76 CloseIterators();
79 uint32_t CacheFileContextEvictor::ContextsCount() {
80 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
82 return mEntries.Length();
85 nsresult CacheFileContextEvictor::AddContext(
86 nsILoadContextInfo* aLoadContextInfo, bool aPinned,
87 const nsAString& aOrigin) {
88 LOG(
89 ("CacheFileContextEvictor::AddContext() [this=%p, loadContextInfo=%p, "
90 "pinned=%d]",
91 this, aLoadContextInfo, aPinned));
93 nsresult rv;
95 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
97 CacheFileContextEvictorEntry* entry = nullptr;
98 if (aLoadContextInfo) {
99 for (uint32_t i = 0; i < mEntries.Length(); ++i) {
100 if (mEntries[i]->mInfo && mEntries[i]->mInfo->Equals(aLoadContextInfo) &&
101 mEntries[i]->mPinned == aPinned &&
102 mEntries[i]->mOrigin.Equals(aOrigin)) {
103 entry = mEntries[i].get();
104 break;
107 } else {
108 // Not providing load context info means we want to delete everything,
109 // so let's not bother with any currently running context cleanups
110 // for the same pinning state.
111 for (uint32_t i = mEntries.Length(); i > 0;) {
112 --i;
113 if (mEntries[i]->mInfo && mEntries[i]->mPinned == aPinned) {
114 RemoveEvictInfoFromDisk(mEntries[i]->mInfo, mEntries[i]->mPinned,
115 mEntries[i]->mOrigin);
116 mEntries.RemoveElementAt(i);
121 if (!entry) {
122 entry = new CacheFileContextEvictorEntry();
123 entry->mInfo = aLoadContextInfo;
124 entry->mPinned = aPinned;
125 entry->mOrigin = aOrigin;
126 mEntries.AppendElement(WrapUnique(entry));
129 entry->mTimeStamp = PR_Now() / PR_USEC_PER_MSEC;
131 PersistEvictionInfoToDisk(aLoadContextInfo, aPinned, aOrigin);
133 if (mIndexIsUpToDate) {
134 // Already existing context could be added again, in this case the iterator
135 // would be recreated. Close the old iterator explicitely.
136 if (entry->mIterator) {
137 entry->mIterator->Close();
138 entry->mIterator = nullptr;
141 rv = CacheIndex::GetIterator(aLoadContextInfo, false,
142 getter_AddRefs(entry->mIterator));
143 if (NS_FAILED(rv)) {
144 // This could probably happen during shutdown. Remove the entry from
145 // the array, but leave the info on the disk. No entry can be opened
146 // during shutdown and we'll load the eviction info on next start.
147 LOG(
148 ("CacheFileContextEvictor::AddContext() - Cannot get an iterator. "
149 "[rv=0x%08" PRIx32 "]",
150 static_cast<uint32_t>(rv)));
151 mEntries.RemoveElement(entry);
152 return rv;
155 StartEvicting();
158 return NS_OK;
161 void CacheFileContextEvictor::CacheIndexStateChanged() {
162 LOG(("CacheFileContextEvictor::CacheIndexStateChanged() [this=%p]", this));
164 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
166 bool isUpToDate = false;
167 CacheIndex::IsUpToDate(&isUpToDate);
168 if (mEntries.Length() == 0) {
169 // Just save the state and exit, since there is nothing to do
170 mIndexIsUpToDate = isUpToDate;
171 return;
174 if (!isUpToDate && !mIndexIsUpToDate) {
175 // Index is outdated and status has not changed, nothing to do.
176 return;
179 if (isUpToDate && mIndexIsUpToDate) {
180 // Status has not changed, but make sure the eviction is running.
181 if (mEvicting) {
182 return;
185 // We're not evicting, but we should be evicting?!
186 LOG(
187 ("CacheFileContextEvictor::CacheIndexStateChanged() - Index is up to "
188 "date, we have some context to evict but eviction is not running! "
189 "Starting now."));
192 mIndexIsUpToDate = isUpToDate;
194 if (mIndexIsUpToDate) {
195 CreateIterators();
196 StartEvicting();
197 } else {
198 CloseIterators();
202 void CacheFileContextEvictor::WasEvicted(const nsACString& aKey, nsIFile* aFile,
203 bool* aEvictedAsPinned,
204 bool* aEvictedAsNonPinned) {
205 LOG(("CacheFileContextEvictor::WasEvicted() [key=%s]",
206 PromiseFlatCString(aKey).get()));
208 *aEvictedAsPinned = false;
209 *aEvictedAsNonPinned = false;
211 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
213 nsCOMPtr<nsILoadContextInfo> info = CacheFileUtils::ParseKey(aKey);
214 MOZ_ASSERT(info);
215 if (!info) {
216 LOG(("CacheFileContextEvictor::WasEvicted() - Cannot parse key!"));
217 return;
220 for (uint32_t i = 0; i < mEntries.Length(); ++i) {
221 const auto& entry = mEntries[i];
223 if (entry->mInfo && !info->Equals(entry->mInfo)) {
224 continue;
227 PRTime lastModifiedTime;
228 if (NS_FAILED(aFile->GetLastModifiedTime(&lastModifiedTime))) {
229 LOG(
230 ("CacheFileContextEvictor::WasEvicted() - Cannot get last modified "
231 "time, returning."));
232 return;
235 if (lastModifiedTime > entry->mTimeStamp) {
236 // File has been modified since context eviction.
237 continue;
240 LOG(
241 ("CacheFileContextEvictor::WasEvicted() - evicted [pinning=%d, "
242 "mTimeStamp=%" PRId64 ", lastModifiedTime=%" PRId64 "]",
243 entry->mPinned, entry->mTimeStamp, lastModifiedTime));
245 if (entry->mPinned) {
246 *aEvictedAsPinned = true;
247 } else {
248 *aEvictedAsNonPinned = true;
253 nsresult CacheFileContextEvictor::PersistEvictionInfoToDisk(
254 nsILoadContextInfo* aLoadContextInfo, bool aPinned,
255 const nsAString& aOrigin) {
256 LOG(
257 ("CacheFileContextEvictor::PersistEvictionInfoToDisk() [this=%p, "
258 "loadContextInfo=%p]",
259 this, aLoadContextInfo));
261 nsresult rv;
263 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
265 nsCOMPtr<nsIFile> file;
266 rv = GetContextFile(aLoadContextInfo, aPinned, aOrigin, getter_AddRefs(file));
267 if (NS_WARN_IF(NS_FAILED(rv))) {
268 return rv;
271 nsCString path = file->HumanReadablePath();
273 PRFileDesc* fd;
274 rv =
275 file->OpenNSPRFileDesc(PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
276 if (NS_WARN_IF(NS_FAILED(rv))) {
277 LOG(
278 ("CacheFileContextEvictor::PersistEvictionInfoToDisk() - Creating file "
279 "failed! [path=%s, rv=0x%08" PRIx32 "]",
280 path.get(), static_cast<uint32_t>(rv)));
281 return rv;
284 PR_Close(fd);
286 LOG(
287 ("CacheFileContextEvictor::PersistEvictionInfoToDisk() - Successfully "
288 "created file. [path=%s]",
289 path.get()));
291 return NS_OK;
294 nsresult CacheFileContextEvictor::RemoveEvictInfoFromDisk(
295 nsILoadContextInfo* aLoadContextInfo, bool aPinned,
296 const nsAString& aOrigin) {
297 LOG(
298 ("CacheFileContextEvictor::RemoveEvictInfoFromDisk() [this=%p, "
299 "loadContextInfo=%p]",
300 this, aLoadContextInfo));
302 nsresult rv;
304 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
306 nsCOMPtr<nsIFile> file;
307 rv = GetContextFile(aLoadContextInfo, aPinned, aOrigin, getter_AddRefs(file));
308 if (NS_WARN_IF(NS_FAILED(rv))) {
309 return rv;
312 nsCString path = file->HumanReadablePath();
314 rv = file->Remove(false);
315 if (NS_WARN_IF(NS_FAILED(rv))) {
316 LOG(
317 ("CacheFileContextEvictor::RemoveEvictionInfoFromDisk() - Removing file"
318 " failed! [path=%s, rv=0x%08" PRIx32 "]",
319 path.get(), static_cast<uint32_t>(rv)));
320 return rv;
323 LOG(
324 ("CacheFileContextEvictor::RemoveEvictionInfoFromDisk() - Successfully "
325 "removed file. [path=%s]",
326 path.get()));
328 return NS_OK;
331 nsresult CacheFileContextEvictor::LoadEvictInfoFromDisk() {
332 LOG(("CacheFileContextEvictor::LoadEvictInfoFromDisk() [this=%p]", this));
334 nsresult rv;
336 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
338 sDiskAlreadySearched = true;
340 nsCOMPtr<nsIDirectoryEnumerator> dirEnum;
341 rv = mCacheDirectory->GetDirectoryEntries(getter_AddRefs(dirEnum));
342 if (NS_WARN_IF(NS_FAILED(rv))) {
343 return rv;
346 while (true) {
347 nsCOMPtr<nsIFile> file;
348 rv = dirEnum->GetNextFile(getter_AddRefs(file));
349 if (!file) {
350 break;
353 bool isDir = false;
354 file->IsDirectory(&isDir);
355 if (isDir) {
356 continue;
359 nsAutoCString leaf;
360 rv = file->GetNativeLeafName(leaf);
361 if (NS_FAILED(rv)) {
362 LOG(
363 ("CacheFileContextEvictor::LoadEvictInfoFromDisk() - "
364 "GetNativeLeafName() failed! Skipping file."));
365 continue;
368 if (leaf.Length() < kContextEvictionPrefixLength) {
369 continue;
372 if (!StringBeginsWith(leaf, nsLiteralCString(CONTEXT_EVICTION_PREFIX))) {
373 continue;
376 nsAutoCString encoded;
377 encoded = Substring(leaf, kContextEvictionPrefixLength);
378 encoded.ReplaceChar('-', '/');
380 nsAutoCString decoded;
381 rv = Base64Decode(encoded, decoded);
382 if (NS_FAILED(rv)) {
383 LOG(
384 ("CacheFileContextEvictor::LoadEvictInfoFromDisk() - Base64 decoding "
385 "failed. Removing the file. [file=%s]",
386 leaf.get()));
387 file->Remove(false);
388 continue;
391 bool pinned = decoded[0] == '\t';
392 if (pinned) {
393 decoded = Substring(decoded, 1);
396 // Let's see if we have an origin.
397 nsAutoCString origin;
398 if (decoded.Contains('\t')) {
399 auto split = decoded.Split('\t');
400 MOZ_ASSERT(decoded.CountChar('\t') == 1);
402 auto splitIt = split.begin();
403 origin = *splitIt;
404 ++splitIt;
405 decoded = *splitIt;
408 nsCOMPtr<nsILoadContextInfo> info;
409 if (!"*"_ns.Equals(decoded)) {
410 // "*" is indication of 'delete all', info left null will pass
411 // to CacheFileContextEvictor::AddContext and clear all the cache data.
412 info = CacheFileUtils::ParseKey(decoded);
413 if (!info) {
414 LOG(
415 ("CacheFileContextEvictor::LoadEvictInfoFromDisk() - Cannot parse "
416 "context key, removing file. [contextKey=%s, file=%s]",
417 decoded.get(), leaf.get()));
418 file->Remove(false);
419 continue;
423 PRTime lastModifiedTime;
424 rv = file->GetLastModifiedTime(&lastModifiedTime);
425 if (NS_FAILED(rv)) {
426 continue;
429 CacheFileContextEvictorEntry* entry = new CacheFileContextEvictorEntry();
430 entry->mInfo = info;
431 entry->mPinned = pinned;
432 CopyUTF8toUTF16(origin, entry->mOrigin);
433 entry->mTimeStamp = lastModifiedTime;
434 mEntries.AppendElement(entry);
437 return NS_OK;
440 nsresult CacheFileContextEvictor::GetContextFile(
441 nsILoadContextInfo* aLoadContextInfo, bool aPinned,
442 const nsAString& aOrigin, nsIFile** _retval) {
443 nsresult rv;
445 nsAutoCString keyPrefix;
446 if (aPinned) {
447 // Mark pinned context files with a tab char at the start.
448 // Tab is chosen because it can never be used as a context key tag.
449 keyPrefix.Append('\t');
451 if (aLoadContextInfo) {
452 CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, keyPrefix);
453 } else {
454 keyPrefix.Append('*');
456 if (!aOrigin.IsEmpty()) {
457 keyPrefix.Append('\t');
458 keyPrefix.Append(NS_ConvertUTF16toUTF8(aOrigin));
461 nsAutoCString leafName;
462 leafName.AssignLiteral(CONTEXT_EVICTION_PREFIX);
464 rv = Base64EncodeAppend(keyPrefix, leafName);
465 if (NS_WARN_IF(NS_FAILED(rv))) {
466 return rv;
469 // Replace '/' with '-' since '/' cannot be part of the filename.
470 leafName.ReplaceChar('/', '-');
472 nsCOMPtr<nsIFile> file;
473 rv = mCacheDirectory->Clone(getter_AddRefs(file));
474 if (NS_WARN_IF(NS_FAILED(rv))) {
475 return rv;
478 rv = file->AppendNative(leafName);
479 if (NS_WARN_IF(NS_FAILED(rv))) {
480 return rv;
483 file.swap(*_retval);
484 return NS_OK;
487 void CacheFileContextEvictor::CreateIterators() {
488 LOG(("CacheFileContextEvictor::CreateIterators() [this=%p]", this));
490 CloseIterators();
492 nsresult rv;
494 for (uint32_t i = 0; i < mEntries.Length();) {
495 rv = CacheIndex::GetIterator(mEntries[i]->mInfo, false,
496 getter_AddRefs(mEntries[i]->mIterator));
497 if (NS_FAILED(rv)) {
498 LOG(
499 ("CacheFileContextEvictor::CreateIterators() - Cannot get an iterator"
500 ". [rv=0x%08" PRIx32 "]",
501 static_cast<uint32_t>(rv)));
502 mEntries.RemoveElementAt(i);
503 continue;
506 ++i;
510 void CacheFileContextEvictor::CloseIterators() {
511 LOG(("CacheFileContextEvictor::CloseIterators() [this=%p]", this));
513 for (uint32_t i = 0; i < mEntries.Length(); ++i) {
514 if (mEntries[i]->mIterator) {
515 mEntries[i]->mIterator->Close();
516 mEntries[i]->mIterator = nullptr;
521 void CacheFileContextEvictor::StartEvicting() {
522 LOG(("CacheFileContextEvictor::StartEvicting() [this=%p]", this));
524 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
526 if (mEvicting) {
527 LOG(("CacheFileContextEvictor::StartEvicting() - already evicting."));
528 return;
531 if (mEntries.Length() == 0) {
532 LOG(("CacheFileContextEvictor::StartEvicting() - no context to evict."));
533 return;
536 nsCOMPtr<nsIRunnable> ev =
537 NewRunnableMethod("net::CacheFileContextEvictor::EvictEntries", this,
538 &CacheFileContextEvictor::EvictEntries);
540 RefPtr<CacheIOThread> ioThread = CacheFileIOManager::IOThread();
542 nsresult rv = ioThread->Dispatch(ev, CacheIOThread::EVICT);
543 if (NS_FAILED(rv)) {
544 LOG(
545 ("CacheFileContextEvictor::StartEvicting() - Cannot dispatch event to "
546 "IO thread. [rv=0x%08" PRIx32 "]",
547 static_cast<uint32_t>(rv)));
550 mEvicting = true;
553 void CacheFileContextEvictor::EvictEntries() {
554 LOG(("CacheFileContextEvictor::EvictEntries()"));
556 nsresult rv;
558 MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
560 mEvicting = false;
562 if (!mIndexIsUpToDate) {
563 LOG(
564 ("CacheFileContextEvictor::EvictEntries() - Stopping evicting due to "
565 "outdated index."));
566 return;
569 while (true) {
570 if (CacheObserver::ShuttingDown()) {
571 LOG(
572 ("CacheFileContextEvictor::EvictEntries() - Stopping evicting due to "
573 "shutdown."));
574 mEvicting =
575 true; // We don't want to start eviction again during shutdown
576 // process. Setting this flag to true ensures it.
577 return;
580 if (CacheIOThread::YieldAndRerun()) {
581 LOG(
582 ("CacheFileContextEvictor::EvictEntries() - Breaking loop for higher "
583 "level events."));
584 mEvicting = true;
585 return;
588 if (mEntries.Length() == 0) {
589 LOG(
590 ("CacheFileContextEvictor::EvictEntries() - Stopping evicting, there "
591 "is no context to evict."));
593 // Allow index to notify AsyncGetDiskConsumption callbacks. The size is
594 // actual again.
595 CacheIndex::OnAsyncEviction(false);
596 return;
599 SHA1Sum::Hash hash;
600 rv = mEntries[0]->mIterator->GetNextHash(&hash);
601 if (rv == NS_ERROR_NOT_AVAILABLE) {
602 LOG(
603 ("CacheFileContextEvictor::EvictEntries() - No more entries left in "
604 "iterator. [iterator=%p, info=%p]",
605 mEntries[0]->mIterator.get(), mEntries[0]->mInfo.get()));
606 RemoveEvictInfoFromDisk(mEntries[0]->mInfo, mEntries[0]->mPinned,
607 mEntries[0]->mOrigin);
608 mEntries.RemoveElementAt(0);
609 continue;
611 if (NS_FAILED(rv)) {
612 LOG(
613 ("CacheFileContextEvictor::EvictEntries() - Iterator failed to "
614 "provide next hash (shutdown?), keeping eviction info on disk."
615 " [iterator=%p, info=%p]",
616 mEntries[0]->mIterator.get(), mEntries[0]->mInfo.get()));
617 mEntries.RemoveElementAt(0);
618 continue;
621 LOG(
622 ("CacheFileContextEvictor::EvictEntries() - Processing hash. "
623 "[hash=%08x%08x%08x%08x%08x, iterator=%p, info=%p]",
624 LOGSHA1(&hash), mEntries[0]->mIterator.get(),
625 mEntries[0]->mInfo.get()));
627 RefPtr<CacheFileHandle> handle;
628 CacheFileIOManager::gInstance->mHandles.GetHandle(&hash,
629 getter_AddRefs(handle));
630 if (handle) {
631 // We doom any active handle in CacheFileIOManager::EvictByContext(), so
632 // this must be a new one. Skip it.
633 LOG(
634 ("CacheFileContextEvictor::EvictEntries() - Skipping entry since we "
635 "found an active handle. [handle=%p]",
636 handle.get()));
637 continue;
640 CacheIndex::EntryStatus status;
641 bool pinned = false;
642 auto callback = [&pinned](const CacheIndexEntry* aEntry) {
643 pinned = aEntry->IsPinned();
645 rv = CacheIndex::HasEntry(hash, &status, callback);
646 // This must never fail, since eviction (this code) happens only when the
647 // index is up-to-date and thus the informatin is known.
648 MOZ_ASSERT(NS_SUCCEEDED(rv));
650 if (pinned != mEntries[0]->mPinned) {
651 LOG(
652 ("CacheFileContextEvictor::EvictEntries() - Skipping entry since "
653 "pinning "
654 "doesn't match [evicting pinned=%d, entry pinned=%d]",
655 mEntries[0]->mPinned, pinned));
656 continue;
659 if (!mEntries[0]->mOrigin.IsEmpty()) {
660 nsCOMPtr<nsIFile> file;
661 CacheFileIOManager::gInstance->GetFile(&hash, getter_AddRefs(file));
663 // Read metadata from the file synchronously
664 RefPtr<CacheFileMetadata> metadata = new CacheFileMetadata();
665 rv = metadata->SyncReadMetadata(file);
666 if (NS_WARN_IF(NS_FAILED(rv))) {
667 continue;
670 // Now get the context + enhance id + URL from the key.
671 nsAutoCString uriSpec;
672 RefPtr<nsILoadContextInfo> info =
673 CacheFileUtils::ParseKey(metadata->GetKey(), nullptr, &uriSpec);
674 MOZ_ASSERT(info);
675 if (!info) {
676 continue;
679 nsCOMPtr<nsIURI> uri;
680 rv = NS_NewURI(getter_AddRefs(uri), uriSpec);
681 if (NS_FAILED(rv)) {
682 LOG(
683 ("CacheFileContextEvictor::EvictEntries() - Skipping entry since "
684 "NS_NewURI failed to parse the uriSpec"));
685 continue;
688 nsAutoString urlOrigin;
689 rv = nsContentUtils::GetWebExposedOriginSerialization(uri, urlOrigin);
690 if (NS_FAILED(rv)) {
691 LOG(
692 ("CacheFileContextEvictor::EvictEntries() - Skipping entry since "
693 "We failed to extract an origin"));
694 continue;
697 if (!urlOrigin.Equals(mEntries[0]->mOrigin)) {
698 LOG(
699 ("CacheFileContextEvictor::EvictEntries() - Skipping entry since "
700 "origin "
701 "doesn't match"));
702 continue;
706 nsAutoCString leafName;
707 CacheFileIOManager::HashToStr(&hash, leafName);
709 PRTime lastModifiedTime;
710 nsCOMPtr<nsIFile> file;
711 rv = mEntriesDir->Clone(getter_AddRefs(file));
712 if (NS_SUCCEEDED(rv)) {
713 rv = file->AppendNative(leafName);
715 if (NS_SUCCEEDED(rv)) {
716 rv = file->GetLastModifiedTime(&lastModifiedTime);
718 if (NS_FAILED(rv)) {
719 LOG(
720 ("CacheFileContextEvictor::EvictEntries() - Cannot get last modified "
721 "time, skipping entry."));
722 continue;
725 if (lastModifiedTime > mEntries[0]->mTimeStamp) {
726 LOG(
727 ("CacheFileContextEvictor::EvictEntries() - Skipping newer entry. "
728 "[mTimeStamp=%" PRId64 ", lastModifiedTime=%" PRId64 "]",
729 mEntries[0]->mTimeStamp, lastModifiedTime));
730 continue;
733 LOG(("CacheFileContextEvictor::EvictEntries - Removing entry."));
734 file->Remove(false);
735 CacheIndex::RemoveEntry(&hash);
738 MOZ_ASSERT_UNREACHABLE("We should never get here");
741 } // namespace mozilla::net