tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit e8c4e2674d333f0393f9cc033c595729817f2857
parent 8b3064548eb10178858bb8b4df7b86a2041e0692
Author: Randell Jesup <rjesup@mozilla.com>
Date:   Mon,  3 Nov 2025 18:26:15 +0000

Bug 1997497: Rework DictionaryOrigin clearing code r=necko-reviewers,sunil

Differential Revision: https://phabricator.services.mozilla.com/D270792

Diffstat:
Mnetwerk/cache2/Dictionary.cpp | 64++++++++++++++++++++++++++++++++++++++--------------------------
Mnetwerk/cache2/Dictionary.h | 6++++--
2 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/netwerk/cache2/Dictionary.cpp b/netwerk/cache2/Dictionary.cpp @@ -946,12 +946,12 @@ void DictionaryCache::RemoveOriginFor(const nsACString& aKey) { DICTIONARY_LOG( ("Removing dictionary origin %s", PromiseFlatCString(aKey).get())); NS_DispatchToMainThread(NewRunnableMethod<const nsCString>( - "DictionaryCache::RemoveOriginFor", cache, &DictionaryCache::RemoveOrigin, - aKey)); + "DictionaryCache::RemoveOriginFor", cache, + &DictionaryCache::RemoveOriginForInternal, aKey)); } // Remove a dictionary if it exists for the key given, if it's empty -void DictionaryCache::RemoveOrigin(const nsACString& aKey) { +void DictionaryCache::RemoveOriginForInternal(const nsACString& aKey) { nsCOMPtr<nsIURI> uri; if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), aKey))) { return; @@ -962,7 +962,8 @@ void DictionaryCache::RemoveOrigin(const nsACString& aKey) { if (MOZ_UNLIKELY(origin.Data()->IsEmpty())) { DICTIONARY_LOG( ("Removing origin for %s", PromiseFlatCString(aKey).get())); - mDictionaryCache.Remove(prepath); + // This removes it from the global list and also dooms the entry + origin.Data()->Clear(); } else { DICTIONARY_LOG( ("Origin not empty: %s", PromiseFlatCString(aKey).get())); @@ -971,8 +972,13 @@ void DictionaryCache::RemoveOrigin(const nsACString& aKey) { } } +// Remove a dictionary if it exists for the key given (key should be prepath) +void DictionaryCache::RemoveOrigin(const nsACString& aOrigin) { + mDictionaryCache.Remove(aOrigin); +} + // Remove a dictionary if it exists for the key given. Mainthread only. -// Note: due to cookie samesite rules, we need to clean for all ports +// Note: due to cookie samesite rules, we need to clean for all ports! // static void DictionaryCache::RemoveDictionariesForOrigin(nsIURI* aURI) { // There's no PrePathNoPort() @@ -988,9 +994,12 @@ void DictionaryCache::RemoveDictionariesForOrigin(nsIURI* aURI) { PromiseFlatCString(origin).get(), origin.Length())); RefPtr<DictionaryCache> cache = GetInstance(); // We can't just use Remove here; the ClearSiteData service strips the - // port. In that case, We need to clear all that match the host with any - // port or none. - cache->mDictionaryCache.RemoveIf([&origin](auto& entry) { + // port. We need to clear all that match the host with any port or none. + + // Keep an array of origins to clear since tht will want to modify the + // hash table we're iterating + AutoTArray<RefPtr<DictionaryOrigin>, 1> toClear; + for (auto& entry : cache->mDictionaryCache) { // We need to drop any port from entry (and origin). Assuming they're // the same up to the / or : in mOrigin, we want to limit the host // there. We also know that entry is https://. @@ -1001,27 +1010,29 @@ void DictionaryCache::RemoveDictionariesForOrigin(nsIURI* aURI) { // https://foo.barsoom.com:666/ DICTIONARY_LOG( ("Possibly removing dictionary origin for %s (vs %s), %zu vs %zu", - entry.Data()->mOrigin.get(), PromiseFlatCString(origin).get(), - entry.Data()->mOrigin.Length(), origin.Length())); - if (entry.Data()->mOrigin.Length() > origin.Length() && - (entry.Data()->mOrigin[origin.Length()] == '/' || // no port - entry.Data()->mOrigin[origin.Length()] == ':')) { // port + entry.GetData()->mOrigin.get(), PromiseFlatCString(origin).get(), + entry.GetData()->mOrigin.Length(), origin.Length())); + if (entry.GetData()->mOrigin.Length() > origin.Length() && + (entry.GetData()->mOrigin[origin.Length()] == '/' || // no port + entry.GetData()->mOrigin[origin.Length()] == ':')) { // port // no strncmp() for nsCStrings... nsDependentCSubstring host = - Substring(entry.Data()->mOrigin, 0, + Substring(entry.GetData()->mOrigin, 0, origin.Length()); // not including '/' or ':' - DICTIONARY_LOG(("Compare %s vs %s", entry.Data()->mOrigin.get(), + DICTIONARY_LOG(("Compare %s vs %s", entry.GetData()->mOrigin.get(), PromiseFlatCString(host).get())); if (origin.Equals(host)) { DICTIONARY_LOG( ("RemoveDictionaries: Removing dictionary origin %p for %s", - entry.Data().get(), entry.Data()->mOrigin.get())); - entry.Data()->Clear(); - return true; + entry.GetData().get(), entry.GetData()->mOrigin.get())); + toClear.AppendElement(entry.GetData()); } } - return false; - }); + } + // Now clear and doom all the entries + for (auto& entry : toClear) { + entry->Clear(); + } } // Remove a dictionary if it exists for the key given. Mainthread only @@ -1294,10 +1305,7 @@ nsresult DictionaryOrigin::RemoveEntry(const nsACString& aKey) { } // If this origin has no entries, remove it and doom the entry if (IsEmpty()) { - if (mEntry) { - mEntry->AsyncDoom(nullptr); - } - gDictionaryCache->RemoveOrigin(mOrigin); + Clear(); } return hold ? NS_OK : NS_ERROR_FAILURE; } @@ -1351,6 +1359,7 @@ void DictionaryOrigin::DumpEntries() { } void DictionaryOrigin::Clear() { + DICTIONARY_LOG(("*** Clearing origin %s", mOrigin.get())); mEntries.Clear(); mPendingEntries.Clear(); mPendingRemove.Clear(); @@ -1359,9 +1368,12 @@ void DictionaryOrigin::Clear() { // This will attempt to delete the DictionaryOrigin, but we'll do // that more directly NS_DispatchBackgroundTask(NS_NewRunnableFunction( - "DictionaryOrigin::Clear", - [entry = mEntry]() { entry->AsyncDoom(nullptr); })); + "DictionaryOrigin::Clear", [entry = mEntry, origin(mOrigin)]() { + DICTIONARY_LOG(("*** Dooming origin %s", origin.get())); + entry->AsyncDoom(nullptr); + })); } + gDictionaryCache->RemoveOrigin(mOrigin); } // caller will throw this into a RefPtr diff --git a/netwerk/cache2/Dictionary.h b/netwerk/cache2/Dictionary.h @@ -339,8 +339,8 @@ class DictionaryCache final { // Remove a dictionary if it exists for the key given void RemoveDictionary(const nsACString& aKey); - // Remove an origin for the key given - void RemoveOrigin(const nsACString& aKey); + // Remove an origin for the origin given + void RemoveOrigin(const nsACString& aOrigin); nsresult RemoveEntry(nsIURI* aURI, const nsACString& aKey); @@ -362,6 +362,8 @@ class DictionaryCache final { } private: + void RemoveOriginForInternal(const nsACString& aKey); + static StaticRefPtr<nsICacheStorage> sCacheStorage; // In-memory cache of dictionary entries. HashMap, keyed by origin, of