Bug 1947158 - Add url option to ChromeUtils.clearResourceCache. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D238357
This commit is contained in:
Tooru Fujisawa
2025-03-18 09:57:57 +00:00
parent 86db2478c2
commit 8fa3cc1097
12 changed files with 129 additions and 40 deletions

View File

@@ -1612,9 +1612,12 @@ void ChromeUtils::ClearResourceCache(
if (aOptions.mSchemelessSite.WasPassed()) {
filterCount++;
}
if (aOptions.mUrl.WasPassed()) {
filterCount++;
}
if (filterCount > 1) {
aRv.ThrowInvalidStateError(
"target, principal, and schemelessSite properties are mutually "
"target, principal, schemelessSite, and url properties are mutually "
"exclusive");
return;
}
@@ -1676,6 +1679,24 @@ void ChromeUtils::ClearResourceCache(
return;
}
if (aOptions.mUrl.WasPassed()) {
nsCString url(aOptions.mUrl.Value());
if (clearStyleSheet) {
SharedStyleSheetCache::Clear(Nothing(), Nothing(), Nothing(), Nothing(),
Some(url));
}
if (clearScript) {
SharedScriptCache::Clear(Nothing(), Nothing(), Nothing(), Nothing(),
Some(url));
}
if (clearImage) {
imgLoader::ClearCache(Nothing(), Nothing(), Nothing(), Nothing(),
Nothing(), Some(url));
}
return;
}
if (clearStyleSheet) {
SharedStyleSheetCache::Clear();
}

View File

@@ -91,21 +91,26 @@ dictionary ClearResourceCacheOptions {
// If specified, clear only the specified target, either chrome or content.
// If not specified, clears both chrome and content.
//
// Exclusive with principal and schemelessSite.
// Exclusive with principal, schemelessSite, and url.
ResourceCacheTarget target;
// If specified, filters by principal.
//
// Exclusive with target and schemelessSite.
// Exclusive with target, schemelessSite, and url.
Principal principal;
// If specified, filters by site, and needs to provide a pattern.
//
// Exclusive with target and principal.
// Exclusive with target, principal, and url.
UTF8String schemelessSite;
// If specified with schemelessSite, filter by origin attributes.
OriginAttributesPatternDictionary pattern = {};
// If specified, clear the cache for the url
//
// Exclusive with target, principal, and schemelessSite.
UTF8String url;
};
/**

View File

@@ -2093,16 +2093,20 @@ mozilla::ipc::IPCResult ContentChild::RecvRegisterChromeItem(
mozilla::ipc::IPCResult ContentChild::RecvClearStyleSheetCache(
const Maybe<bool>& aChrome, const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern) {
SharedStyleSheetCache::Clear(aChrome, aPrincipal, aSchemelessSite, aPattern);
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL) {
SharedStyleSheetCache::Clear(aChrome, aPrincipal, aSchemelessSite, aPattern,
aURL);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvClearScriptCache(
const Maybe<bool>& aChrome, const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern) {
SharedScriptCache::Clear(aChrome, aPrincipal, aSchemelessSite, aPattern);
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL) {
SharedScriptCache::Clear(aChrome, aPrincipal, aSchemelessSite, aPattern,
aURL);
return IPC_OK();
}
@@ -2110,9 +2114,10 @@ mozilla::ipc::IPCResult ContentChild::RecvClearImageCache(
const Maybe<bool>& aPrivateLoader, const Maybe<bool>& aChrome,
const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern) {
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL) {
imgLoader::ClearCache(aPrincipal, aChrome, aPrincipal, aSchemelessSite,
aPattern);
aPattern, aURL);
return IPC_OK();
}

View File

@@ -249,18 +249,21 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvClearStyleSheetCache(
const Maybe<bool>& aChrome, const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern);
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL);
mozilla::ipc::IPCResult RecvClearScriptCache(
const Maybe<bool>& aChrome, const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern);
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL);
mozilla::ipc::IPCResult RecvClearImageCache(
const Maybe<bool>& aPrivateLoader, const Maybe<bool>& aChrome,
const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern);
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL);
PRemoteSpellcheckEngineChild* AllocPRemoteSpellcheckEngineChild();

View File

@@ -658,17 +658,20 @@ child:
bool? aChrome,
nullable nsIPrincipal? aPrincipal,
nsCString? aSchemelessSite,
OriginAttributesPattern? aPattern);
OriginAttributesPattern? aPattern,
nsCString? aURL);
async ClearStyleSheetCache(bool? aChrome,
nullable nsIPrincipal? aPrincipal,
nsCString? aSchemelessSite,
OriginAttributesPattern? aPattern);
OriginAttributesPattern? aPattern,
nsCString? aURL);
async ClearScriptCache(bool? aChrome,
nullable nsIPrincipal? aPrincipal,
nsCString? aSchemelessSite,
OriginAttributesPattern? aPattern);
OriginAttributesPattern? aPattern,
nsCString? aURL);
async SetOffline(bool offline);
async SetConnectivity(bool connectivity);

View File

@@ -141,18 +141,20 @@ SharedScriptCache::Observe(nsISupports* aSubject, const char* aTopic,
void SharedScriptCache::Clear(const Maybe<bool>& aChrome,
const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern) {
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL) {
using ContentParent = dom::ContentParent;
if (XRE_IsParentProcess()) {
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
Unused << cp->SendClearScriptCache(aChrome, aPrincipal, aSchemelessSite,
aPattern);
aPattern, aURL);
}
}
if (sSingleton) {
sSingleton->ClearInProcess(aChrome, aPrincipal, aSchemelessSite, aPattern);
sSingleton->ClearInProcess(aChrome, aPrincipal, aSchemelessSite, aPattern,
aURL);
}
}

View File

@@ -197,7 +197,8 @@ class SharedScriptCache final
static void Clear(const Maybe<bool>& aChrome = Nothing(),
const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal = Nothing(),
const Maybe<nsCString>& aSchemelessSite = Nothing(),
const Maybe<OriginAttributesPattern>& aPattern = Nothing());
const Maybe<OriginAttributesPattern>& aPattern = Nothing(),
const Maybe<nsCString>& aURL = Nothing());
protected:
~SharedScriptCache();

View File

@@ -1418,11 +1418,12 @@ nsresult imgLoader::ClearCache(
aPrincipal /* = mozilla::Nothing() */,
const mozilla::Maybe<nsCString>& aSchemelessSite /* = mozilla::Nothing() */,
const mozilla::Maybe<mozilla::OriginAttributesPattern>&
aPattern /* = mozilla::Nothing() */) {
aPattern /* = mozilla::Nothing() */,
const mozilla::Maybe<nsCString>& aURL /* = mozilla::Nothing() */) {
if (XRE_IsParentProcess()) {
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
Unused << cp->SendClearImageCache(aPrivateLoader, aChrome, aPrincipal,
aSchemelessSite, aPattern);
aSchemelessSite, aPattern, aURL);
}
}
@@ -1434,19 +1435,36 @@ nsresult imgLoader::ClearCache(
loader = imgLoader::NormalLoader();
}
loader->RemoveEntriesInternal(aPrincipal, Nothing(), Nothing());
loader->RemoveEntriesInternal(aPrincipal, Nothing(), Nothing(), Nothing());
return NS_OK;
}
if (aSchemelessSite) {
if (!aPrivateLoader || !*aPrivateLoader) {
nsresult rv = imgLoader::NormalLoader()->RemoveEntriesInternal(
Nothing(), aSchemelessSite, aPattern);
Nothing(), aSchemelessSite, aPattern, Nothing());
NS_ENSURE_SUCCESS(rv, rv);
}
if (!aPrivateLoader || *aPrivateLoader) {
nsresult rv = imgLoader::PrivateBrowsingLoader()->RemoveEntriesInternal(
Nothing(), aSchemelessSite, aPattern);
Nothing(), aSchemelessSite, aPattern, Nothing());
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
if (aURL) {
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), *aURL);
NS_ENSURE_SUCCESS(rv, rv);
if (!aPrivateLoader || !*aPrivateLoader) {
nsresult rv = imgLoader::NormalLoader()->RemoveEntry(uri, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!aPrivateLoader || *aPrivateLoader) {
nsresult rv =
imgLoader::PrivateBrowsingLoader()->RemoveEntry(uri, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
@@ -1503,9 +1521,12 @@ imgLoader::RemoveEntriesFromSiteInAllProcesses(
nsresult imgLoader::RemoveEntriesInternal(
const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern) {
const Maybe<OriginAttributesPattern>& aPattern,
const mozilla::Maybe<nsCString>& aURL) {
// Can only clear by either principal or site + pattern.
if ((!aPrincipal && !aSchemelessSite) || (aPrincipal && aSchemelessSite) ||
if ((!aPrincipal && !aSchemelessSite && !aURL) ||
(aPrincipal && aSchemelessSite) || (aPrincipal && aURL) ||
(aSchemelessSite && aURL) ||
aSchemelessSite.isSome() != aPattern.isSome()) {
return NS_ERROR_INVALID_ARG;
}
@@ -1518,6 +1539,15 @@ nsresult imgLoader::RemoveEntriesInternal(
// TODO(emilio): Deduplicate this with SharedSubresourceCache.
const bool shouldRemove = [&] {
if (aURL) {
nsAutoCString spec;
nsresult rv = key.URI()->GetSpec(spec);
if (NS_FAILED(rv)) {
return false;
}
return spec == *aURL;
}
if (aPrincipal) {
return key.LoaderPrincipal()->Equals(aPrincipal.ref());
}

View File

@@ -258,17 +258,20 @@ class imgLoader final : public imgILoader,
* 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.
* Has no effect with aPrincipal, aSchemelessSite or aURL.
* @param aPrincipal
* If specified, clear cache from the same origin and the same
* originAttributes of the passed principal.
* Exclusive with aSchemelessSite.
* Exclusive with aSchemelessSite and aURL.
* @param aSchemelessSite
* If specified, clear cache which match the the given site.
* If this is specified, aPattern should also be specified.
* Exclusive with aPrincipal.
* Exclusive with aPrincipal and aURL.
* @param aPattern
* The pattern used with aSchemelessSite.
* @param aURL
* If specified, clear cache for given URL.
* Exclusive with aPrincipal and aschemelesssite.
*/
static nsresult ClearCache(
mozilla::Maybe<bool> aPrivateLoader = mozilla::Nothing(),
@@ -277,7 +280,8 @@ class imgLoader final : public imgILoader,
mozilla::Nothing(),
const mozilla::Maybe<nsCString>& aSchemelessSite = mozilla::Nothing(),
const mozilla::Maybe<mozilla::OriginAttributesPattern>& aPattern =
mozilla::Nothing());
mozilla::Nothing(),
const mozilla::Maybe<nsCString>& aURL = mozilla::Nothing());
bool IsImageAvailable(nsIURI*, nsIPrincipal* aTriggeringPrincipal,
mozilla::CORSMode, mozilla::dom::Document*);
@@ -376,7 +380,8 @@ class imgLoader final : public imgILoader,
nsresult RemoveEntriesInternal(
const mozilla::Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal,
const mozilla::Maybe<nsCString>& aSchemelessSite,
const mozilla::Maybe<mozilla::OriginAttributesPattern>& aPattern);
const mozilla::Maybe<mozilla::OriginAttributesPattern>& aPattern,
const mozilla::Maybe<nsCString>& aURL);
// The image loader maintains a hash table of all imgCacheEntries. However,
// only some of them will be evicted from the cache: those who have no

View File

@@ -207,18 +207,20 @@ SharedStyleSheetCache::CollectReports(nsIHandleReportCallback* aHandleReport,
void SharedStyleSheetCache::Clear(
const Maybe<bool>& aChrome, const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern) {
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL) {
using ContentParent = dom::ContentParent;
if (XRE_IsParentProcess()) {
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
Unused << cp->SendClearStyleSheetCache(aChrome, aPrincipal,
aSchemelessSite, aPattern);
aSchemelessSite, aPattern, aURL);
}
}
if (sSingleton) {
sSingleton->ClearInProcess(aChrome, aPrincipal, aSchemelessSite, aPattern);
sSingleton->ClearInProcess(aChrome, aPrincipal, aSchemelessSite, aPattern,
aURL);
}
}

View File

@@ -69,7 +69,8 @@ class SharedStyleSheetCache final
static void Clear(const Maybe<bool>& aChrome = Nothing(),
const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal = Nothing(),
const Maybe<nsCString>& aSchemelessSite = Nothing(),
const Maybe<OriginAttributesPattern>& aPattern = Nothing());
const Maybe<OriginAttributesPattern>& aPattern = Nothing(),
const Maybe<nsCString>& aURL = Nothing());
protected:
void InsertIfNeeded(css::SheetLoadData&);

View File

@@ -242,7 +242,8 @@ class SharedSubResourceCache {
void ClearInProcess(const Maybe<bool>& aChrome,
const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern);
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL);
protected:
void CancelPendingLoadsForLoader(Loader&);
@@ -272,11 +273,12 @@ template <typename Traits, typename Derived>
void SharedSubResourceCache<Traits, Derived>::ClearInProcess(
const Maybe<bool>& aChrome, const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal,
const Maybe<nsCString>& aSchemelessSite,
const Maybe<OriginAttributesPattern>& aPattern) {
const Maybe<OriginAttributesPattern>& aPattern,
const Maybe<nsCString>& aURL) {
MOZ_ASSERT(aSchemelessSite.isSome() == aPattern.isSome(),
"Must pass both site and OA pattern.");
if (!aChrome && !aPrincipal && !aSchemelessSite) {
if (!aChrome && !aPrincipal && !aSchemelessSite && !aURL) {
mComplete.Clear();
return;
}
@@ -290,11 +292,20 @@ void SharedSubResourceCache<Traits, Derived>::ClearInProcess(
return false;
}
if (!aPrincipal && !aSchemelessSite) {
if (!aPrincipal && !aSchemelessSite && !aURL) {
return true;
}
}
if (aURL) {
nsAutoCString spec;
nsresult rv = iter.Key().URI()->GetSpec(spec);
if (NS_FAILED(rv)) {
return false;
}
return spec == *aURL;
}
if (aPrincipal &&
iter.Key().LoaderPrincipal()->Equals(aPrincipal.ref())) {
return true;