Skip to content

Commit 7a92b22

Browse files
FKLCfkilic@mozilla.com
authored andcommitted
Bug 1781277: Implement DiskStorageLimit RFP target. r=tjr,dom-storage-reviewers,asuth
Differential Revision: https://phabricator.services.mozilla.com/D223842
1 parent b834ddb commit 7a92b22

File tree

7 files changed

+103
-4
lines changed

7 files changed

+103
-4
lines changed

dom/quota/ActorsParent.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,12 @@ void GetJarPrefix(bool aInIsolatedMozBrowser, nsACString& aJarPrefix) {
13321332
// This method computes and returns our best guess for the temporary storage
13331333
// limit (in bytes), based on disk capacity.
13341334
Result<uint64_t, nsresult> GetTemporaryStorageLimit(nsIFile& aStorageDir) {
1335+
if (nsContentUtils::ShouldResistFingerprinting(
1336+
"The storage limit is set only once and not webpage specific.",
1337+
RFPTarget::DiskStorageLimit)) {
1338+
return nsRFPService::GetSpoofedStorageLimit();
1339+
}
1340+
13351341
// The fixed limit pref can be used to override temporary storage limit
13361342
// calculation.
13371343
if (StaticPrefs::dom_quotaManager_temporaryStorage_fixedLimit() >= 0) {
@@ -7507,17 +7513,21 @@ void QuotaManager::SetThumbnailPrivateIdentityId(
75077513
}
75087514
}
75097515

7510-
uint64_t QuotaManager::GetGroupLimit() const {
7516+
/* static */
7517+
uint64_t QuotaManager::GetGroupLimitForLimit(uint64_t aLimit) {
75117518
// To avoid one group evicting all the rest, limit the amount any one group
75127519
// can use to 20% resp. a fifth. To prevent individual sites from using
75137520
// exorbitant amounts of storage where there is a lot of free space, cap the
75147521
// group limit to 10GB.
7515-
const auto x = std::min<uint64_t>(mTemporaryStorageLimit / 5, 10 GB);
7522+
const auto x = std::min<uint64_t>(aLimit / 5, 10 GB);
75167523

75177524
// In low-storage situations, make an exception (while not exceeding the total
75187525
// storage limit).
7519-
return std::min<uint64_t>(mTemporaryStorageLimit,
7520-
std::max<uint64_t>(x, 10 MB));
7526+
return std::min<uint64_t>(aLimit, std::max<uint64_t>(x, 10 MB));
7527+
}
7528+
7529+
uint64_t QuotaManager::GetGroupLimit() const {
7530+
return GetGroupLimitForLimit(mTemporaryStorageLimit);
75217531
}
75227532

75237533
Maybe<OriginStateMetadata> QuotaManager::GetOriginStateMetadata(

dom/quota/QuotaManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ class QuotaManager final : public BackgroundThreadObject {
681681
void SetThumbnailPrivateIdentityId(uint32_t aThumbnailPrivateIdentityId);
682682

683683
uint64_t GetGroupLimit() const;
684+
static uint64_t GetGroupLimitForLimit(uint64_t aLimit);
684685

685686
Maybe<OriginStateMetadata> GetOriginStateMetadata(
686687
const OriginMetadata& aOriginMetadata);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Any copyright is dedicated to the Public Domain.
3+
* http://creativecommons.org/publicdomain/zero/1.0/
4+
*/
5+
6+
const { AppConstants } = ChromeUtils.importESModule(
7+
"resource://gre/modules/AppConstants.sys.mjs"
8+
);
9+
10+
async function testSteps() {
11+
const principal = getPrincipal("http://example.com");
12+
const GiB = 1024 * 1024 * 1024;
13+
14+
// Set the limit to some random value that is less than 50 GiB.
15+
const globalLimitBytes = 1 * GiB;
16+
const globalLimitKib = globalLimitBytes / 1024;
17+
18+
setGlobalLimit(globalLimitKib);
19+
20+
let request = init();
21+
await requestFinished(request);
22+
23+
request = initTemporaryStorage();
24+
await requestFinished(request);
25+
26+
request = estimateOrigin(principal);
27+
await requestFinished(request);
28+
29+
const perGroupPercentage = 0.2;
30+
const expectedGroupLimitBytes = Math.floor(
31+
globalLimitBytes * perGroupPercentage
32+
);
33+
is(expectedGroupLimitBytes, request.result.limit);
34+
35+
// Verify the RFP override is applied.
36+
request = reset();
37+
await requestFinished(request);
38+
39+
let spoofedLimitBytes = 50 * GiB;
40+
if (AppConstants.platform == "android") {
41+
spoofedLimitBytes = 32 * GiB;
42+
}
43+
44+
Services.prefs.setBoolPref("privacy.resistFingerprinting", true);
45+
46+
request = init();
47+
await requestFinished(request);
48+
49+
request = initTemporaryStorage();
50+
await requestFinished(request);
51+
52+
request = estimateOrigin(principal);
53+
await requestFinished(request);
54+
55+
const expectedSpoofedGroupLimitBytes = spoofedLimitBytes * perGroupPercentage;
56+
is(
57+
expectedSpoofedGroupLimitBytes,
58+
request.result.limit,
59+
"RFP limit should be applied"
60+
);
61+
62+
Services.prefs.clearUserPref("privacy.resistFingerprinting");
63+
64+
resetGlobalLimit();
65+
66+
request = reset();
67+
await requestFinished(request);
68+
}

dom/quota/test/xpcshell/xpcshell.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,5 @@ run-if = ["!condprof"]
170170
support-files = ["unsetLastAccessTime_profile.zip"]
171171

172172
["test_validOrigins.js"]
173+
174+
["test_temporaryStorageRFP.js"]

toolkit/components/resistfingerprinting/RFPTargets.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ ITEM_VALUE(WebGPUSubgroupSizes, 66)
100100
ITEM_VALUE(JSLocalePrompt, 67)
101101
ITEM_VALUE(ScreenAvailToResolution, 68)
102102
ITEM_VALUE(UseHardcodedFontSubstitutes, 69)
103+
ITEM_VALUE(DiskStorageLimit, 70)
103104

104105

105106
// !!! Don't forget to update kDefaultFingerprintingProtections in nsRFPService.cpp

toolkit/components/resistfingerprinting/nsRFPService.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "mozilla/dom/KeyboardEventBinding.h"
5454
#include "mozilla/dom/WindowGlobalParent.h"
5555
#include "mozilla/dom/MediaDeviceInfoBinding.h"
56+
#include "mozilla/dom/quota/QuotaManager.h"
5657
#include "mozilla/fallible.h"
5758
#include "mozilla/XorShift128PlusRNG.h"
5859
#include "mozilla/dom/CanvasUtils.h"
@@ -2687,3 +2688,17 @@ CSSIntRect nsRFPService::GetSpoofedScreenAvailSize(const nsRect& aRect,
26872688
return CSSIntRect::FromAppUnitsRounded(
26882689
nsRect{0, 0, aRect.width, aRect.height - spoofedHeightOffset});
26892690
}
2691+
2692+
/* static */
2693+
uint64_t nsRFPService::GetSpoofedStorageLimit() {
2694+
uint64_t gib = 1024ULL * 1024ULL * 1024ULL; // 1 GiB
2695+
#ifdef ANDROID
2696+
uint64_t limit = 32ULL * gib; // 32 GiB
2697+
#else
2698+
uint64_t limit = 50ULL * gib; // 50 GiB
2699+
#endif
2700+
MOZ_ASSERT(limit / 5 ==
2701+
dom::quota::QuotaManager::GetGroupLimitForLimit(limit));
2702+
2703+
return limit;
2704+
}

toolkit/components/resistfingerprinting/nsRFPService.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,8 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
414414
static CSSIntRect GetSpoofedScreenAvailSize(const nsRect& aRect, float aScale,
415415
bool aIsFullscreen);
416416

417+
static uint64_t GetSpoofedStorageLimit();
418+
417419
private:
418420
nsresult Init();
419421

0 commit comments

Comments
 (0)