mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 14:25:49 +00:00
Bug 1705032 - Added CSSCacheCleaner deleteByBaseDomain. r=emilio,timhuang
Differential Revision: https://phabricator.services.mozilla.com/D114518
This commit is contained in:
parent
aeca8bec83
commit
8e5f5e55fc
@ -753,11 +753,20 @@ void ChromeUtils::ClearRecentJSDevError(GlobalObject&) {
|
||||
}
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
void ChromeUtils::ClearStyleSheetCache(GlobalObject&,
|
||||
nsIPrincipal* aForPrincipal) {
|
||||
void ChromeUtils::ClearStyleSheetCacheByPrincipal(GlobalObject&,
|
||||
nsIPrincipal* aForPrincipal) {
|
||||
SharedStyleSheetCache::Clear(aForPrincipal);
|
||||
}
|
||||
|
||||
void ChromeUtils::ClearStyleSheetCacheByBaseDomain(
|
||||
GlobalObject&, const nsACString& aBaseDomain) {
|
||||
SharedStyleSheetCache::Clear(nullptr, &aBaseDomain);
|
||||
}
|
||||
|
||||
void ChromeUtils::ClearStyleSheetCache(GlobalObject&) {
|
||||
SharedStyleSheetCache::Clear();
|
||||
}
|
||||
|
||||
#define PROCTYPE_TO_WEBIDL_CASE(_procType, _webidl) \
|
||||
case mozilla::ProcType::_procType: \
|
||||
return WebIDLProcType::_webidl
|
||||
|
@ -151,7 +151,13 @@ class ChromeUtils {
|
||||
|
||||
static void ClearRecentJSDevError(GlobalObject& aGlobal);
|
||||
|
||||
static void ClearStyleSheetCache(GlobalObject&, nsIPrincipal* aForPrincipal);
|
||||
static void ClearStyleSheetCacheByPrincipal(GlobalObject&,
|
||||
nsIPrincipal* aForPrincipal);
|
||||
|
||||
static void ClearStyleSheetCacheByBaseDomain(GlobalObject& aGlobal,
|
||||
const nsACString& aBaseDomain);
|
||||
|
||||
static void ClearStyleSheetCache(GlobalObject& aGlobal);
|
||||
|
||||
static already_AddRefed<Promise> RequestPerformanceMetrics(
|
||||
GlobalObject& aGlobal, ErrorResult& aRv);
|
||||
|
@ -193,9 +193,20 @@ namespace ChromeUtils {
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
/**
|
||||
* Clears the stylesheet cache.
|
||||
* Clears the stylesheet cache by baseDomain. This includes associated
|
||||
* state-partitioned cache.
|
||||
*/
|
||||
void clearStyleSheetCache(optional Principal? principal = null);
|
||||
void clearStyleSheetCacheByBaseDomain(UTF8String baseDomain);
|
||||
|
||||
/**
|
||||
* Clears the stylesheet cache by principal.
|
||||
*/
|
||||
void clearStyleSheetCacheByPrincipal(Principal principal);
|
||||
|
||||
/**
|
||||
* Clears the entire stylesheet cache.
|
||||
*/
|
||||
void clearStyleSheetCache();
|
||||
|
||||
/**
|
||||
* If the profiler is currently running and recording the current thread,
|
||||
|
@ -2009,11 +2009,13 @@ mozilla::ipc::IPCResult ContentChild::RecvRegisterChromeItem(
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvClearStyleSheetCache(
|
||||
const Maybe<RefPtr<nsIPrincipal>>& aForPrincipal) {
|
||||
nsIPrincipal* prin = aForPrincipal ? aForPrincipal.value().get() : nullptr;
|
||||
SharedStyleSheetCache::Clear(prin);
|
||||
const Maybe<RefPtr<nsIPrincipal>>& aForPrincipal,
|
||||
const Maybe<nsCString>& aBaseDomain) {
|
||||
nsIPrincipal* principal =
|
||||
aForPrincipal ? aForPrincipal.value().get() : nullptr;
|
||||
const nsCString* baseDomain = aBaseDomain ? aBaseDomain.ptr() : nullptr;
|
||||
SharedStyleSheetCache::Clear(principal, baseDomain);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,8 @@ class ContentChild final : public PContentChild,
|
||||
const ChromeRegistryItem& item);
|
||||
|
||||
mozilla::ipc::IPCResult RecvClearStyleSheetCache(
|
||||
const Maybe<RefPtr<nsIPrincipal>>& aForPrincipal);
|
||||
const Maybe<RefPtr<nsIPrincipal>>& aForPrincipal,
|
||||
const Maybe<nsCString>& aBaseDomain);
|
||||
mozilla::ipc::IPCResult RecvClearImageCache(const bool& privateLoader,
|
||||
const bool& chrome);
|
||||
|
||||
|
@ -584,7 +584,8 @@ child:
|
||||
|
||||
async ClearImageCache(bool privateLoader, bool chrome);
|
||||
|
||||
async ClearStyleSheetCache(nsIPrincipal? aForPrincipal);
|
||||
async ClearStyleSheetCache(nsIPrincipal? aForPrincipal,
|
||||
nsCString? aBaseDomain);
|
||||
|
||||
async SetOffline(bool offline);
|
||||
async SetConnectivity(bool connectivity);
|
||||
|
@ -130,6 +130,8 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
|
||||
|
||||
nsIPrincipal* LoaderPrincipal() const { return mLoaderPrincipal; }
|
||||
|
||||
nsIPrincipal* PartitionPrincipal() const { return mPartitionPrincipal; }
|
||||
|
||||
css::SheetParsingMode ParsingMode() const { return mParsingMode; }
|
||||
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "SharedStyleSheetCache.h"
|
||||
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/StoragePrincipalHelper.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/css/SheetLoadData.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
@ -28,13 +29,16 @@ using IsAlternate = css::Loader::IsAlternate;
|
||||
|
||||
SharedStyleSheetCache* SharedStyleSheetCache::sInstance;
|
||||
|
||||
void SharedStyleSheetCache::Clear(nsIPrincipal* aForPrincipal) {
|
||||
void SharedStyleSheetCache::Clear(nsIPrincipal* aForPrincipal,
|
||||
const nsACString* aBaseDomain) {
|
||||
using ContentParent = dom::ContentParent;
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
auto forPrincipal = aForPrincipal ? Some(RefPtr(aForPrincipal)) : Nothing();
|
||||
auto baseDomain = aBaseDomain ? Some(nsCString(*aBaseDomain)) : Nothing();
|
||||
|
||||
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
|
||||
Unused << cp->SendClearStyleSheetCache(forPrincipal);
|
||||
Unused << cp->SendClearStyleSheetCache(forPrincipal, baseDomain);
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,14 +46,43 @@ void SharedStyleSheetCache::Clear(nsIPrincipal* aForPrincipal) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aForPrincipal) {
|
||||
// No filter, clear all.
|
||||
if (!aForPrincipal && !aBaseDomain) {
|
||||
sInstance->mCompleteSheets.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto iter = sInstance->mCompleteSheets.Iter(); !iter.Done();
|
||||
iter.Next()) {
|
||||
if (iter.Key().Principal()->Equals(aForPrincipal)) {
|
||||
const bool shouldRemove = [&] {
|
||||
if (aForPrincipal && iter.Key().Principal()->Equals(aForPrincipal)) {
|
||||
return true;
|
||||
}
|
||||
if (!aBaseDomain) {
|
||||
return false;
|
||||
}
|
||||
// Clear by baseDomain.
|
||||
nsIPrincipal* partitionPrincipal = iter.Key().PartitionPrincipal();
|
||||
|
||||
// Clear entries with matching base domain. This includes entries
|
||||
// which are partitioned under other top level sites (= have a
|
||||
// partitionKey set).
|
||||
nsAutoCString principalBaseDomain;
|
||||
nsresult rv = partitionPrincipal->GetBaseDomain(principalBaseDomain);
|
||||
if (NS_SUCCEEDED(rv) && principalBaseDomain.Equals(*aBaseDomain)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clear entries partitioned under aBaseDomain.
|
||||
nsAutoString partitionKeyBaseDomain;
|
||||
bool ok = StoragePrincipalHelper::GetBaseDomainFromPartitionKey(
|
||||
partitionPrincipal->OriginAttributesRef().mPartitionKey,
|
||||
partitionKeyBaseDomain);
|
||||
return ok &&
|
||||
NS_ConvertUTF16toUTF8(partitionKeyBaseDomain).Equals(*aBaseDomain);
|
||||
}();
|
||||
|
||||
if (shouldRemove) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,8 @@ class SharedStyleSheetCache final : public nsIMemoryReporter {
|
||||
// be called when the document goes away, or when its principal changes.
|
||||
void UnregisterLoader(css::Loader&);
|
||||
|
||||
static void Clear(nsIPrincipal* aForPrincipal = nullptr);
|
||||
static void Clear(nsIPrincipal* aForPrincipal = nullptr,
|
||||
const nsACString* aBaseDomain = nullptr);
|
||||
|
||||
private:
|
||||
static already_AddRefed<SharedStyleSheetCache> Create();
|
||||
|
@ -251,17 +251,16 @@ const CSSCacheCleaner = {
|
||||
aOriginAttributes
|
||||
);
|
||||
|
||||
ChromeUtils.clearStyleSheetCache(httpPrincipal);
|
||||
ChromeUtils.clearStyleSheetCache(httpsPrincipal);
|
||||
ChromeUtils.clearStyleSheetCacheByPrincipal(httpPrincipal);
|
||||
ChromeUtils.clearStyleSheetCacheByPrincipal(httpsPrincipal);
|
||||
},
|
||||
|
||||
async deleteByPrincipal(aPrincipal) {
|
||||
ChromeUtils.clearStyleSheetCache(aPrincipal);
|
||||
ChromeUtils.clearStyleSheetCacheByPrincipal(aPrincipal);
|
||||
},
|
||||
|
||||
deleteByBaseDomain(aBaseDomain) {
|
||||
// TODO: Bug 1705032
|
||||
return this.deleteByHost(aBaseDomain, {});
|
||||
async deleteByBaseDomain(aBaseDomain) {
|
||||
ChromeUtils.clearStyleSheetCacheByBaseDomain(aBaseDomain);
|
||||
},
|
||||
|
||||
async deleteAll() {
|
||||
|
@ -1,3 +1,7 @@
|
||||
[browser_css_cache.js]
|
||||
support-files =
|
||||
file_css_cache.css
|
||||
file_css_cache.html
|
||||
[browser_serviceworkers.js]
|
||||
[browser_quota.js]
|
||||
support-files = worker.js
|
||||
|
129
toolkit/components/cleardata/tests/browser/browser_css_cache.js
Normal file
129
toolkit/components/cleardata/tests/browser/browser_css_cache.js
Normal file
@ -0,0 +1,129 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const BASE_DOMAIN_A = "example.com";
|
||||
const ORIGIN_A = `https://${BASE_DOMAIN_A}`;
|
||||
const ORIGIN_A_HTTP = `http://${BASE_DOMAIN_A}`;
|
||||
const ORIGIN_A_SUB = `https://test1.${BASE_DOMAIN_A}`;
|
||||
|
||||
const BASE_DOMAIN_B = "example.org";
|
||||
const ORIGIN_B = `https://${BASE_DOMAIN_B}`;
|
||||
const ORIGIN_B_HTTP = `http://${BASE_DOMAIN_B}`;
|
||||
const ORIGIN_B_SUB = `https://test1.${BASE_DOMAIN_B}`;
|
||||
|
||||
const TEST_ROOT_DIR = getRootDirectory(gTestPath);
|
||||
|
||||
// Stylesheets are cached per process, so we need to keep tabs open for the
|
||||
// duration of a test.
|
||||
let tabs = {};
|
||||
|
||||
function getTestURLForOrigin(origin) {
|
||||
return (
|
||||
TEST_ROOT_DIR.replace("chrome://mochitests/content", origin) +
|
||||
"file_css_cache.html"
|
||||
);
|
||||
}
|
||||
|
||||
async function testCached(origin, isCached) {
|
||||
let url = getTestURLForOrigin(origin);
|
||||
|
||||
let numParsed;
|
||||
|
||||
let tab = tabs[origin];
|
||||
let loadedPromise;
|
||||
if (!tab) {
|
||||
info("Creating new tab for " + url);
|
||||
tab = BrowserTestUtils.addTab(gBrowser, url);
|
||||
loadedPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
tabs[origin] = tab;
|
||||
} else {
|
||||
loadedPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
tab.linkedBrowser.reload();
|
||||
}
|
||||
await loadedPromise;
|
||||
|
||||
numParsed = await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
|
||||
return SpecialPowers.getDOMWindowUtils(content).parsedStyleSheets;
|
||||
});
|
||||
|
||||
// Stylesheets is cached if numParsed is 0.
|
||||
is(!numParsed, isCached, `${origin} is${isCached ? " " : " not "}cached`);
|
||||
}
|
||||
|
||||
async function addTestTabs() {
|
||||
await testCached(ORIGIN_A, false);
|
||||
await testCached(ORIGIN_A_SUB, false);
|
||||
await testCached(ORIGIN_A_HTTP, false);
|
||||
await testCached(ORIGIN_B, false);
|
||||
await testCached(ORIGIN_B_SUB, false);
|
||||
await testCached(ORIGIN_B_HTTP, false);
|
||||
// Test that the cache has been populated.
|
||||
await testCached(ORIGIN_A, true);
|
||||
await testCached(ORIGIN_A_SUB, true);
|
||||
await testCached(ORIGIN_A_HTTP, true);
|
||||
await testCached(ORIGIN_B, true);
|
||||
await testCached(ORIGIN_B_SUB, true);
|
||||
await testCached(ORIGIN_B_HTTP, true);
|
||||
}
|
||||
|
||||
async function cleanupTestTabs() {
|
||||
Object.values(tabs).forEach(BrowserTestUtils.removeTab);
|
||||
tabs = {};
|
||||
}
|
||||
|
||||
add_task(async function test_deleteByPrincipal() {
|
||||
await addTestTabs();
|
||||
|
||||
// Clear data for content principal of A
|
||||
info("Clearing cache for principal " + ORIGIN_A);
|
||||
await new Promise(resolve => {
|
||||
Services.clearData.deleteDataFromPrincipal(
|
||||
Services.scriptSecurityManager.createContentPrincipalFromOrigin(ORIGIN_A),
|
||||
false,
|
||||
Ci.nsIClearDataService.CLEAR_CSS_CACHE,
|
||||
resolve
|
||||
);
|
||||
});
|
||||
|
||||
// Only the cache entry for ORIGIN_A should have been cleared.
|
||||
await testCached(ORIGIN_A, false);
|
||||
await testCached(ORIGIN_A_SUB, true);
|
||||
await testCached(ORIGIN_A_HTTP, true);
|
||||
await testCached(ORIGIN_B, true);
|
||||
await testCached(ORIGIN_B_SUB, true);
|
||||
await testCached(ORIGIN_B_HTTP, true);
|
||||
|
||||
// Cleanup
|
||||
cleanupTestTabs();
|
||||
ChromeUtils.clearStyleSheetCache();
|
||||
});
|
||||
|
||||
add_task(async function test_deleteByBaseDomain() {
|
||||
await addTestTabs();
|
||||
|
||||
// Clear data for base domain of A.
|
||||
info("Clearing cache for base domain " + BASE_DOMAIN_A);
|
||||
await new Promise(resolve => {
|
||||
Services.clearData.deleteDataFromBaseDomain(
|
||||
BASE_DOMAIN_A,
|
||||
false,
|
||||
Ci.nsIClearDataService.CLEAR_CSS_CACHE,
|
||||
resolve
|
||||
);
|
||||
});
|
||||
|
||||
// All entries for A should have been cleared.
|
||||
await testCached(ORIGIN_A, false);
|
||||
await testCached(ORIGIN_A_SUB, false);
|
||||
await testCached(ORIGIN_A_HTTP, false);
|
||||
// Entries for B should still exist.
|
||||
await testCached(ORIGIN_B, true);
|
||||
await testCached(ORIGIN_B_SUB, true);
|
||||
await testCached(ORIGIN_B_HTTP, true);
|
||||
|
||||
// Cleanup
|
||||
cleanupTestTabs();
|
||||
ChromeUtils.clearStyleSheetCache();
|
||||
});
|
@ -0,0 +1,3 @@
|
||||
:root {
|
||||
background-color: lime;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<head>
|
||||
<link rel="stylesheet" href="file_css_cache.css">
|
||||
</head>
|
||||
<body></body>
|
Loading…
x
Reference in New Issue
Block a user