Bug 1948875 - Part 1: Add static imgLoader::ClearCache and refactor IPC. r=tnikkel

In order to clear cache from ChromeUtils.clearResourceCache with variuos
filtering, imgLoader needs a method that are adaptive to the current process,
where in the parent process, clear all processes' cache,
and in the content process, clear the cache in the process.

Refactored the cache methods based on single static method and single IPC
method, this is also necessary to extend the ChromeUtils.clearResourceCache in
bug 1947158.

Differential Revision: https://phabricator.services.mozilla.com/D239138
This commit is contained in:
Tooru Fujisawa
2025-03-18 02:03:31 +00:00
parent 6788fd328e
commit 893c87646e
6 changed files with 140 additions and 68 deletions

View File

@@ -1617,8 +1617,7 @@ void ChromeUtils::ClearResourceCache(GlobalObject&,
Maybe<bool> chrome = aChrome.WasPassed() ? Some(aChrome.Value()) : Nothing(); Maybe<bool> chrome = aChrome.WasPassed() ? Some(aChrome.Value()) : Nothing();
SharedStyleSheetCache::Clear(chrome); SharedStyleSheetCache::Clear(chrome);
SharedScriptCache::Clear(chrome); SharedScriptCache::Clear(chrome);
imgLoader::PrivateBrowsingLoader()->ClearCache(chrome); imgLoader::ClearCache(Nothing(), chrome);
imgLoader::NormalLoader()->ClearCache(chrome);
} }
#define PROCTYPE_TO_WEBIDL_CASE(_procType, _webidl) \ #define PROCTYPE_TO_WEBIDL_CASE(_procType, _webidl) \

View File

@@ -2106,35 +2106,13 @@ mozilla::ipc::IPCResult ContentChild::RecvClearScriptCache(
return IPC_OK(); return IPC_OK();
} }
mozilla::ipc::IPCResult ContentChild::RecvClearImageCacheFromPrincipal(
nsIPrincipal* aPrincipal) {
imgLoader* loader;
if (aPrincipal->OriginAttributesRef().IsPrivateBrowsing()) {
loader = imgLoader::PrivateBrowsingLoader();
} else {
loader = imgLoader::NormalLoader();
}
loader->RemoveEntriesInternal(Some(aPrincipal), Nothing(), Nothing());
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvClearImageCacheFromSite(
const nsCString& aSchemelessSite, const OriginAttributesPattern& aPattern) {
imgLoader::NormalLoader()->RemoveEntriesInternal(
Nothing(), Some(aSchemelessSite), Some(aPattern));
imgLoader::PrivateBrowsingLoader()->RemoveEntriesInternal(
Nothing(), Some(aSchemelessSite), Some(aPattern));
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvClearImageCache( mozilla::ipc::IPCResult ContentChild::RecvClearImageCache(
const bool& privateLoader, const mozilla::Maybe<bool>& chrome) { const Maybe<bool>& aPrivateLoader, const Maybe<bool>& aChrome,
imgLoader* loader = privateLoader ? imgLoader::PrivateBrowsingLoader() const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
: imgLoader::NormalLoader(); const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern) {
loader->ClearCache(chrome); imgLoader::ClearCache(aPrincipal, aChrome, aPrincipal, aSchemelessSite,
aPattern);
return IPC_OK(); return IPC_OK();
} }

View File

@@ -256,13 +256,11 @@ class ContentChild final : public PContentChild,
const Maybe<nsCString>& aSchemelessSite, const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern); const Maybe<OriginAttributesPattern>& aPattern);
mozilla::ipc::IPCResult RecvClearImageCacheFromPrincipal( mozilla::ipc::IPCResult RecvClearImageCache(
nsIPrincipal* aPrincipal); const Maybe<bool>& aPrivateLoader, const Maybe<bool>& aChrome,
mozilla::ipc::IPCResult RecvClearImageCacheFromSite( const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
const nsCString& aSchemelessSite, const Maybe<nsCString>& aSchemelessSite,
const OriginAttributesPattern& aPattern); const Maybe<OriginAttributesPattern>& aPattern);
mozilla::ipc::IPCResult RecvClearImageCache(const bool& privateLoader,
const Maybe<bool>& chrome);
PRemoteSpellcheckEngineChild* AllocPRemoteSpellcheckEngineChild(); PRemoteSpellcheckEngineChild* AllocPRemoteSpellcheckEngineChild();

View File

@@ -654,11 +654,11 @@ child:
OverrideMapping[] overrides, nsCString locale, bool reset); OverrideMapping[] overrides, nsCString locale, bool reset);
async RegisterChromeItem(ChromeRegistryItem item); async RegisterChromeItem(ChromeRegistryItem item);
async ClearImageCacheFromPrincipal(nullable nsIPrincipal aPrincipal); async ClearImageCache(bool? privateLoader,
bool? aChrome,
async ClearImageCacheFromSite(nsCString aSchemelessSite, OriginAttributesPattern aPattern); nullable nsIPrincipal? aPrincipal,
nsCString? aSchemelessSite,
async ClearImageCache(bool privateLoader, bool? chrome); OriginAttributesPattern? aPattern);
async ClearStyleSheetCache(bool? aChrome, async ClearStyleSheetCache(bool? aChrome,
nullable nsIPrincipal? aPrincipal, nullable nsIPrincipal? aPrincipal,

View File

@@ -1372,17 +1372,28 @@ imgLoader::Observe(nsISupports* aSubject, const char* aTopic,
} }
NS_IMETHODIMP NS_IMETHODIMP
imgLoader::ClearCache(JS::Handle<JS::Value> chrome) { imgLoader::ClearCache(JS::Handle<JS::Value> aChrome) {
return ClearCache(chrome.isBoolean() ? Some(chrome.toBoolean()) : Nothing()); nsresult rv = NS_OK;
}
nsresult imgLoader::ClearCache(mozilla::Maybe<bool> chrome) { Maybe<bool> chrome =
aChrome.isBoolean() ? Some(aChrome.toBoolean()) : Nothing();
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
bool privateLoader = this == gPrivateBrowsingLoader; bool privateLoader = this == gPrivateBrowsingLoader;
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) { rv = ClearCache(Some(privateLoader), chrome, Nothing(), Nothing(),
Unused << cp->SendClearImageCache(privateLoader, chrome); Nothing());
if (this == gNormalLoader || this == gPrivateBrowsingLoader) {
return rv;
} }
// NOTE: There can be other loaders created with
// Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader).
// If ClearCache is called on them, the above static ClearCache
// doesn't handle it, and ClearImageCache needs to be called on
// the current instance.
// The favicon handling and some tests can create such loaders.
} }
ClearOptions options; ClearOptions options;
if (chrome) { if (chrome) {
if (*chrome) { if (*chrome) {
@@ -1391,7 +1402,74 @@ nsresult imgLoader::ClearCache(mozilla::Maybe<bool> chrome) {
options += ClearOption::ContentOnly; options += ClearOption::ContentOnly;
} }
} }
return ClearImageCache(options); nsresult rv2 = ClearImageCache(options);
if (NS_FAILED(rv)) {
return rv;
}
return rv2;
}
/*static */
nsresult imgLoader::ClearCache(
mozilla::Maybe<bool> aPrivateLoader /* = mozilla::Nothing() */,
mozilla::Maybe<bool> aChrome /* = mozilla::Nothing() */,
const mozilla::Maybe<nsCOMPtr<nsIPrincipal>>&
aPrincipal /* = mozilla::Nothing() */,
const mozilla::Maybe<nsCString>& aSchemelessSite /* = mozilla::Nothing() */,
const mozilla::Maybe<mozilla::OriginAttributesPattern>&
aPattern /* = mozilla::Nothing() */) {
if (XRE_IsParentProcess()) {
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
Unused << cp->SendClearImageCache(aPrivateLoader, aChrome, aPrincipal,
aSchemelessSite, aPattern);
}
}
if (aPrincipal) {
imgLoader* loader;
if ((*aPrincipal)->OriginAttributesRef().IsPrivateBrowsing()) {
loader = imgLoader::PrivateBrowsingLoader();
} else {
loader = imgLoader::NormalLoader();
}
loader->RemoveEntriesInternal(aPrincipal, Nothing(), Nothing());
return NS_OK;
}
if (aSchemelessSite) {
if (!aPrivateLoader || !*aPrivateLoader) {
nsresult rv = imgLoader::NormalLoader()->RemoveEntriesInternal(
Nothing(), aSchemelessSite, aPattern);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!aPrivateLoader || *aPrivateLoader) {
nsresult rv = imgLoader::PrivateBrowsingLoader()->RemoveEntriesInternal(
Nothing(), aSchemelessSite, aPattern);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
ClearOptions options;
if (aChrome) {
if (*aChrome) {
options += ClearOption::ChromeOnly;
} else {
options += ClearOption::ContentOnly;
}
}
if (!aPrivateLoader || !*aPrivateLoader) {
nsresult rv = imgLoader::NormalLoader()->ClearImageCache(options);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!aPrivateLoader || *aPrivateLoader) {
nsresult rv = imgLoader::PrivateBrowsingLoader()->ClearImageCache(options);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@@ -1400,18 +1478,8 @@ imgLoader::RemoveEntriesFromPrincipalInAllProcesses(nsIPrincipal* aPrincipal) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) { nsCOMPtr<nsIPrincipal> principal = aPrincipal;
Unused << cp->SendClearImageCacheFromPrincipal(aPrincipal); return ClearCache(Nothing(), Nothing(), Some(principal));
}
imgLoader* loader;
if (aPrincipal->OriginAttributesRef().IsPrivateBrowsing()) {
loader = imgLoader::PrivateBrowsingLoader();
} else {
loader = imgLoader::NormalLoader();
}
return loader->RemoveEntriesInternal(Some(aPrincipal), Nothing(), Nothing());
} }
NS_IMETHODIMP NS_IMETHODIMP
@@ -1428,12 +1496,8 @@ imgLoader::RemoveEntriesFromSiteInAllProcesses(
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
} }
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) { return ClearCache(Nothing(), Nothing(), Nothing(),
Unused << cp->SendClearImageCacheFromSite(aSchemelessSite, pattern); Some(nsCString(aSchemelessSite)), Some(pattern));
}
return RemoveEntriesInternal(Nothing(), Some(nsCString(aSchemelessSite)),
Some(pattern));
} }
nsresult imgLoader::RemoveEntriesInternal( nsresult imgLoader::RemoveEntriesInternal(

View File

@@ -244,7 +244,40 @@ class imgLoader final : public imgILoader,
imgLoader(); imgLoader();
nsresult Init(); nsresult Init();
nsresult ClearCache(mozilla::Maybe<bool> chrome); /**
* Clear cache that matches the specified filters.
* If called on the parent process, clear cache from all processes.
* If called in the content process, clear cache within the process.
*
* @param aPrivateLoader
* If specified and true, clear private loader.
* If specified and false, clear normal loader.
* If not specified, clear both loaders.
* Has no effect with aPrincipal.
* @param aChrome
* If specified and true, clear chrome cache.
* If specified and false, clear content cache.
* If not specified, clear both.
* Has no effect with aPrincipal or aSchemelessSite.
* @param aPrincipal
* If specified, clear cache from the same origin and the same
* originAttributes of the passed principal.
* Exclusive with aSchemelessSite.
* @param aSchemelessSite
* If specified, clear cache which match the the given site.
* If this is specified, aPattern should also be specified.
* Exclusive with aPrincipal.
* @param aPattern
* The pattern used with aSchemelessSite.
*/
static nsresult ClearCache(
mozilla::Maybe<bool> aPrivateLoader = mozilla::Nothing(),
mozilla::Maybe<bool> aChrome = mozilla::Nothing(),
const mozilla::Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal =
mozilla::Nothing(),
const mozilla::Maybe<nsCString>& aSchemelessSite = mozilla::Nothing(),
const mozilla::Maybe<mozilla::OriginAttributesPattern>& aPattern =
mozilla::Nothing());
bool IsImageAvailable(nsIURI*, nsIPrincipal* aTriggeringPrincipal, bool IsImageAvailable(nsIURI*, nsIPrincipal* aTriggeringPrincipal,
mozilla::CORSMode, mozilla::dom::Document*); mozilla::CORSMode, mozilla::dom::Document*);