Commits:
-
64132f03
by Fatih Kilic at 2025-09-09T17:36:29+00:00
Bug 1973265 - Put WebCodecs API behind RFP Target. r=tjr,webidl,smaug
Differential Revision: https://phabricator.services.mozilla.com/D254549
17 changed files:
Changes:
dom/base/nsContentUtils.cpp
| ... |
... |
@@ -2844,7 +2844,7 @@ bool nsContentUtils::ShouldResistFingerprinting_dangerous( |
|
2844
|
2844
|
}
|
|
2845
|
2845
|
|
|
2846
|
2846
|
// Web extension principals are also excluded
|
|
2847
|
|
- if (BasePrincipal::Cast(aPrincipal)->AddonPolicy()) {
|
|
|
2847
|
+ if (NS_IsMainThread() && BasePrincipal::Cast(aPrincipal)->AddonPolicy()) {
|
|
2848
|
2848
|
MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,
|
|
2849
|
2849
|
("Inside ShouldResistFingerprinting(nsIPrincipal*)"
|
|
2850
|
2850
|
" and AddonPolicy said false"));
|
dom/media/webcodecs/VideoFrame.cpp
| ... |
... |
@@ -1423,7 +1423,7 @@ JSObject* VideoFrame::WrapObject(JSContext* aCx, |
|
1423
|
1423
|
|
|
1424
|
1424
|
/* static */
|
|
1425
|
1425
|
bool VideoFrame::PrefEnabled(JSContext* aCx, JSObject* aObj) {
|
|
1426
|
|
- return StaticPrefs::dom_media_webcodecs_enabled() ||
|
|
|
1426
|
+ return nsRFPService::ExposeWebCodecsAPI(aCx, aObj) &&
|
|
1427
|
1427
|
StaticPrefs::dom_media_webcodecs_image_decoder_enabled();
|
|
1428
|
1428
|
}
|
|
1429
|
1429
|
|
dom/media/webcodecs/test/mochitest.toml
| ... |
... |
@@ -16,4 +16,13 @@ scheme = "https" |
|
16
|
16
|
["test_imageDecoder_desiredSize.html"]
|
|
17
|
17
|
scheme = "https"
|
|
18
|
18
|
|
|
|
19
|
+["test_rfp_api_disabling_disabled.html"]
|
|
|
20
|
+scheme = "https"
|
|
|
21
|
+
|
|
|
22
|
+["test_rfp_api_disabling_enabled.html"]
|
|
|
23
|
+scheme = "https"
|
|
|
24
|
+
|
|
|
25
|
+["test_rfp_api_disabling_exemption.html"]
|
|
|
26
|
+scheme = "https"
|
|
|
27
|
+
|
|
19
|
28
|
["test_videoFrame_mismatched_codedSize.html"] |
dom/media/webcodecs/test/test_rfp_api_disabling_disabled.html
|
|
1
|
+<!DOCTYPE html>
|
|
|
2
|
+<html>
|
|
|
3
|
+<head>
|
|
|
4
|
+<title></title>
|
|
|
5
|
+<script src="">"/tests/SimpleTest/SimpleTest.js"></script>
|
|
|
6
|
+<link rel="stylesheet" type="text/css" href="">"/tests/SimpleTest/test.css" />
|
|
|
7
|
+</head>
|
|
|
8
|
+<body>
|
|
|
9
|
+<script>
|
|
|
10
|
+const apis = [
|
|
|
11
|
+ "AudioData",
|
|
|
12
|
+ "AudioDecoder",
|
|
|
13
|
+ "AudioEncoder",
|
|
|
14
|
+ "EncodedAudioChunk",
|
|
|
15
|
+ "EncodedVideoChunk",
|
|
|
16
|
+ "ImageDecoder",
|
|
|
17
|
+ "ImageTrack",
|
|
|
18
|
+ "ImageTrackList",
|
|
|
19
|
+ "VideoColorSpace",
|
|
|
20
|
+ "VideoDecoder",
|
|
|
21
|
+ "VideoEncoder",
|
|
|
22
|
+ "VideoFrame",
|
|
|
23
|
+];
|
|
|
24
|
+
|
|
|
25
|
+function enabledAPIs() {
|
|
|
26
|
+ return apis.filter(api => typeof window[api] !== "undefined");
|
|
|
27
|
+}
|
|
|
28
|
+
|
|
|
29
|
+function enabledAPIsWorker() {
|
|
|
30
|
+ const code = `
|
|
|
31
|
+ _onmessage_ = e => {
|
|
|
32
|
+ const apis = ${JSON.stringify(apis)};
|
|
|
33
|
+ postMessage(apis.filter(api => typeof self[api] !== "undefined"));
|
|
|
34
|
+ };`;
|
|
|
35
|
+ const blob = new Blob([code], { type: "application/_javascript_" });
|
|
|
36
|
+ const worker = new Worker(URL.createObjectURL(blob));
|
|
|
37
|
+
|
|
|
38
|
+ return new Promise((resolve) => {
|
|
|
39
|
+ worker.addEventListener("message", async (e) => {
|
|
|
40
|
+ worker.terminate();
|
|
|
41
|
+ resolve(e.data);
|
|
|
42
|
+ });
|
|
|
43
|
+
|
|
|
44
|
+ worker.postMessage({});
|
|
|
45
|
+ });
|
|
|
46
|
+}
|
|
|
47
|
+
|
|
|
48
|
+add_setup(async () => {
|
|
|
49
|
+ await SpecialPowers.pushPrefEnv({
|
|
|
50
|
+ set: [
|
|
|
51
|
+ ["dom.media.webcodecs.enabled", true],
|
|
|
52
|
+ ["dom.media.webcodecs.image-decoder.enabled", true]
|
|
|
53
|
+ ],
|
|
|
54
|
+ });
|
|
|
55
|
+});
|
|
|
56
|
+
|
|
|
57
|
+add_task(async () => {
|
|
|
58
|
+ is(enabledAPIs().length, apis.length, true, "All WebCodecs APIs should be enabled");
|
|
|
59
|
+ is(
|
|
|
60
|
+ (await enabledAPIsWorker()).length,
|
|
|
61
|
+ apis.length,
|
|
|
62
|
+ "All WebCodecs APIs should be enabled in workers too"
|
|
|
63
|
+ );
|
|
|
64
|
+});
|
|
|
65
|
+</script>
|
|
|
66
|
+</body>
|
|
|
67
|
+</html> |
dom/media/webcodecs/test/test_rfp_api_disabling_enabled.html
|
|
1
|
+<!DOCTYPE html>
|
|
|
2
|
+<html>
|
|
|
3
|
+<head>
|
|
|
4
|
+<title></title>
|
|
|
5
|
+<script src="">"/tests/SimpleTest/SimpleTest.js"></script>
|
|
|
6
|
+<link rel="stylesheet" type="text/css" href="">"/tests/SimpleTest/test.css" />
|
|
|
7
|
+</head>
|
|
|
8
|
+<body>
|
|
|
9
|
+<script>
|
|
|
10
|
+const apis = [
|
|
|
11
|
+ "AudioData",
|
|
|
12
|
+ "AudioDecoder",
|
|
|
13
|
+ "AudioEncoder",
|
|
|
14
|
+ "EncodedAudioChunk",
|
|
|
15
|
+ "EncodedVideoChunk",
|
|
|
16
|
+ "ImageDecoder",
|
|
|
17
|
+ "ImageTrack",
|
|
|
18
|
+ "ImageTrackList",
|
|
|
19
|
+ "VideoColorSpace",
|
|
|
20
|
+ "VideoDecoder",
|
|
|
21
|
+ "VideoEncoder",
|
|
|
22
|
+ "VideoFrame",
|
|
|
23
|
+];
|
|
|
24
|
+
|
|
|
25
|
+function enabledAPIs() {
|
|
|
26
|
+ return apis.filter(api => typeof window[api] !== "undefined");
|
|
|
27
|
+}
|
|
|
28
|
+
|
|
|
29
|
+function enabledAPIsWorker() {
|
|
|
30
|
+ const code = `
|
|
|
31
|
+ _onmessage_ = e => {
|
|
|
32
|
+ const apis = ${JSON.stringify(apis)};
|
|
|
33
|
+ postMessage(apis.filter(api => typeof self[api] !== "undefined"));
|
|
|
34
|
+ };`;
|
|
|
35
|
+ const blob = new Blob([code], { type: "application/_javascript_" });
|
|
|
36
|
+ const worker = new Worker(URL.createObjectURL(blob));
|
|
|
37
|
+
|
|
|
38
|
+ return new Promise((resolve) => {
|
|
|
39
|
+ worker.addEventListener("message", async (e) => {
|
|
|
40
|
+ worker.terminate();
|
|
|
41
|
+ resolve(e.data);
|
|
|
42
|
+ });
|
|
|
43
|
+
|
|
|
44
|
+ worker.postMessage({});
|
|
|
45
|
+ });
|
|
|
46
|
+}
|
|
|
47
|
+
|
|
|
48
|
+add_setup(async () => {
|
|
|
49
|
+ await SpecialPowers.pushPrefEnv({
|
|
|
50
|
+ set: [
|
|
|
51
|
+ ["dom.media.webcodecs.enabled", true],
|
|
|
52
|
+ ["dom.media.webcodecs.image-decoder.enabled", true],
|
|
|
53
|
+ ["privacy.fingerprintingProtection", true],
|
|
|
54
|
+ ["privacy.fingerprintingProtection.overrides", "-AllTargets,+WebCodecs"],
|
|
|
55
|
+ ],
|
|
|
56
|
+ });
|
|
|
57
|
+});
|
|
|
58
|
+
|
|
|
59
|
+add_task(async () => {
|
|
|
60
|
+ is(enabledAPIs().length, 0, true, "All WebCodecs APIs should be disabled");
|
|
|
61
|
+ is(
|
|
|
62
|
+ (await enabledAPIsWorker()).length,
|
|
|
63
|
+ 0,
|
|
|
64
|
+ "All WebCodecs APIs should be disabled in workers too"
|
|
|
65
|
+ );
|
|
|
66
|
+});
|
|
|
67
|
+</script>
|
|
|
68
|
+</body>
|
|
|
69
|
+</html> |
dom/media/webcodecs/test/test_rfp_api_disabling_exemption.html
|
|
1
|
+<!DOCTYPE html>
|
|
|
2
|
+<html>
|
|
|
3
|
+<head>
|
|
|
4
|
+<title></title>
|
|
|
5
|
+<script src="">"/tests/SimpleTest/SimpleTest.js"></script>
|
|
|
6
|
+<link rel="stylesheet" type="text/css" href="">"/tests/SimpleTest/test.css" />
|
|
|
7
|
+</head>
|
|
|
8
|
+<body>
|
|
|
9
|
+<script>
|
|
|
10
|
+const apis = [
|
|
|
11
|
+ "AudioData",
|
|
|
12
|
+ "AudioDecoder",
|
|
|
13
|
+ "AudioEncoder",
|
|
|
14
|
+ "EncodedAudioChunk",
|
|
|
15
|
+ "EncodedVideoChunk",
|
|
|
16
|
+ "ImageDecoder",
|
|
|
17
|
+ "ImageTrack",
|
|
|
18
|
+ "ImageTrackList",
|
|
|
19
|
+ "VideoColorSpace",
|
|
|
20
|
+ "VideoDecoder",
|
|
|
21
|
+ "VideoEncoder",
|
|
|
22
|
+ "VideoFrame",
|
|
|
23
|
+];
|
|
|
24
|
+
|
|
|
25
|
+function enabledAPIs() {
|
|
|
26
|
+ return apis.filter(api => typeof window[api] !== "undefined");
|
|
|
27
|
+}
|
|
|
28
|
+
|
|
|
29
|
+function enabledAPIsWorker() {
|
|
|
30
|
+ const code = `
|
|
|
31
|
+ _onmessage_ = e => {
|
|
|
32
|
+ const apis = ${JSON.stringify(apis)};
|
|
|
33
|
+ postMessage(apis.filter(api => typeof self[api] !== "undefined"));
|
|
|
34
|
+ };`;
|
|
|
35
|
+ const blob = new Blob([code], { type: "application/_javascript_" });
|
|
|
36
|
+ const worker = new Worker(URL.createObjectURL(blob));
|
|
|
37
|
+
|
|
|
38
|
+ return new Promise((resolve) => {
|
|
|
39
|
+ worker.addEventListener("message", async (e) => {
|
|
|
40
|
+ worker.terminate();
|
|
|
41
|
+ resolve(e.data);
|
|
|
42
|
+ });
|
|
|
43
|
+
|
|
|
44
|
+ worker.postMessage({});
|
|
|
45
|
+ });
|
|
|
46
|
+}
|
|
|
47
|
+
|
|
|
48
|
+add_setup(async () => {
|
|
|
49
|
+ await SpecialPowers.pushPrefEnv({
|
|
|
50
|
+ set: [
|
|
|
51
|
+ ["dom.media.webcodecs.enabled", true],
|
|
|
52
|
+ ["dom.media.webcodecs.image-decoder.enabled", true],
|
|
|
53
|
+ ["privacy.fingerprintingProtection", true],
|
|
|
54
|
+ ["privacy.fingerprintingProtection.overrides", "-AllTargets,+WebCodecs"],
|
|
|
55
|
+ ["privacy.resistFingerprinting.exemptedDomains", location.hostname]
|
|
|
56
|
+ ],
|
|
|
57
|
+ });
|
|
|
58
|
+});
|
|
|
59
|
+
|
|
|
60
|
+add_task(async () => {
|
|
|
61
|
+ is(enabledAPIs().length, apis.length, true, "All WebCodecs APIs should be disabled");
|
|
|
62
|
+ is(
|
|
|
63
|
+ (await enabledAPIsWorker()).length,
|
|
|
64
|
+ apis.length,
|
|
|
65
|
+ "All WebCodecs APIs should be disabled in workers too"
|
|
|
66
|
+ );
|
|
|
67
|
+});
|
|
|
68
|
+</script>
|
|
|
69
|
+</body>
|
|
|
70
|
+</html> |
dom/webidl/AudioData.webidl
| ... |
... |
@@ -9,7 +9,7 @@ |
|
9
|
9
|
|
|
10
|
10
|
// [Serializable, Transferable] are implemented without adding attributes here,
|
|
11
|
11
|
// but directly with {Read,Write}StructuredClone and Transfer/FromTransfered.
|
|
12
|
|
-[Exposed=(Window,DedicatedWorker), Pref="dom.media.webcodecs.enabled"]
|
|
|
12
|
+[Exposed=(Window,DedicatedWorker), Func="nsRFPService::ExposeWebCodecsAPI"]
|
|
13
|
13
|
interface AudioData {
|
|
14
|
14
|
[Throws]
|
|
15
|
15
|
constructor(AudioDataInit init);
|
dom/webidl/AudioDecoder.webidl
| ... |
... |
@@ -7,7 +7,7 @@ |
|
7
|
7
|
* https://w3c.github.io/webcodecs/#audiodecoder
|
|
8
|
8
|
*/
|
|
9
|
9
|
|
|
10
|
|
-[Exposed=(Window,DedicatedWorker), SecureContext, Pref="dom.media.webcodecs.enabled"]
|
|
|
10
|
+[Exposed=(Window,DedicatedWorker), SecureContext, Func="nsRFPService::ExposeWebCodecsAPI"]
|
|
11
|
11
|
interface AudioDecoder : EventTarget {
|
|
12
|
12
|
[Throws]
|
|
13
|
13
|
constructor(AudioDecoderInit init);
|
dom/webidl/AudioEncoder.webidl
| ... |
... |
@@ -42,7 +42,7 @@ dictionary OpusEncoderConfig { |
|
42
|
42
|
boolean usedtx = false;
|
|
43
|
43
|
};
|
|
44
|
44
|
|
|
45
|
|
-[Exposed=(Window,DedicatedWorker), SecureContext, Pref="dom.media.webcodecs.enabled"]
|
|
|
45
|
+[Exposed=(Window,DedicatedWorker), SecureContext, Func="nsRFPService::ExposeWebCodecsAPI"]
|
|
46
|
46
|
interface AudioEncoder : EventTarget {
|
|
47
|
47
|
[Throws]
|
|
48
|
48
|
constructor(AudioEncoderInit init);
|
dom/webidl/EncodedAudioChunk.webidl
| ... |
... |
@@ -8,7 +8,7 @@ |
|
8
|
8
|
*/
|
|
9
|
9
|
|
|
10
|
10
|
// [Serializable] is implemented without adding attribute here.
|
|
11
|
|
-[Exposed=(Window,DedicatedWorker), Pref="dom.media.webcodecs.enabled"]
|
|
|
11
|
+[Exposed=(Window,DedicatedWorker), Func="nsRFPService::ExposeWebCodecsAPI"]
|
|
12
|
12
|
interface EncodedAudioChunk {
|
|
13
|
13
|
[Throws]
|
|
14
|
14
|
constructor(EncodedAudioChunkInit init);
|
dom/webidl/EncodedVideoChunk.webidl
| ... |
... |
@@ -8,7 +8,7 @@ |
|
8
|
8
|
*/
|
|
9
|
9
|
|
|
10
|
10
|
// [Serializable] is implemented without adding attribute here.
|
|
11
|
|
-[Exposed=(Window,DedicatedWorker), Pref="dom.media.webcodecs.enabled"]
|
|
|
11
|
+[Exposed=(Window,DedicatedWorker), Func="nsRFPService::ExposeWebCodecsAPI"]
|
|
12
|
12
|
interface EncodedVideoChunk {
|
|
13
|
13
|
[Throws]
|
|
14
|
14
|
constructor(EncodedVideoChunkInit init);
|
dom/webidl/ImageDecoder.webidl
| ... |
... |
@@ -30,7 +30,7 @@ dictionary ImageDecodeResult { |
|
30
|
30
|
|
|
31
|
31
|
[Exposed=(Window,DedicatedWorker),
|
|
32
|
32
|
SecureContext,
|
|
33
|
|
- Pref="dom.media.webcodecs.image-decoder.enabled"]
|
|
|
33
|
+ Func="nsRFPService::ExposeWebCodecsAPIImageDecoder"]
|
|
34
|
34
|
interface ImageTrack {
|
|
35
|
35
|
readonly attribute boolean animated;
|
|
36
|
36
|
readonly attribute unsigned long frameCount;
|
| ... |
... |
@@ -40,7 +40,7 @@ interface ImageTrack { |
|
40
|
40
|
|
|
41
|
41
|
[Exposed=(Window,DedicatedWorker),
|
|
42
|
42
|
SecureContext,
|
|
43
|
|
- Pref="dom.media.webcodecs.image-decoder.enabled"]
|
|
|
43
|
+ Func="nsRFPService::ExposeWebCodecsAPIImageDecoder"]
|
|
44
|
44
|
interface ImageTrackList {
|
|
45
|
45
|
getter ImageTrack (unsigned long index);
|
|
46
|
46
|
|
| ... |
... |
@@ -52,7 +52,7 @@ interface ImageTrackList { |
|
52
|
52
|
|
|
53
|
53
|
[Exposed=(Window,DedicatedWorker),
|
|
54
|
54
|
SecureContext,
|
|
55
|
|
- Pref="dom.media.webcodecs.image-decoder.enabled"]
|
|
|
55
|
+ Func="nsRFPService::ExposeWebCodecsAPIImageDecoder"]
|
|
56
|
56
|
interface ImageDecoder {
|
|
57
|
57
|
[Throws]
|
|
58
|
58
|
constructor(ImageDecoderInit init);
|
dom/webidl/VideoDecoder.webidl
| ... |
... |
@@ -7,7 +7,7 @@ |
|
7
|
7
|
* https://w3c.github.io/webcodecs/#videodecoder
|
|
8
|
8
|
*/
|
|
9
|
9
|
|
|
10
|
|
-[Exposed=(Window,DedicatedWorker), SecureContext, Pref="dom.media.webcodecs.enabled"]
|
|
|
10
|
+[Exposed=(Window,DedicatedWorker), SecureContext, Func="nsRFPService::ExposeWebCodecsAPI"]
|
|
11
|
11
|
interface VideoDecoder : EventTarget {
|
|
12
|
12
|
[Throws]
|
|
13
|
13
|
constructor(VideoDecoderInit init);
|
dom/webidl/VideoEncoder.webidl
| ... |
... |
@@ -12,7 +12,7 @@ |
|
12
|
12
|
* commented with a link of the document in which the member is listed.
|
|
13
|
13
|
*/
|
|
14
|
14
|
|
|
15
|
|
-[Exposed=(Window,DedicatedWorker), SecureContext, Pref="dom.media.webcodecs.enabled"]
|
|
|
15
|
+[Exposed=(Window,DedicatedWorker), SecureContext, Func="nsRFPService::ExposeWebCodecsAPI"]
|
|
16
|
16
|
interface VideoEncoder : EventTarget {
|
|
17
|
17
|
[Throws]
|
|
18
|
18
|
constructor(VideoEncoderInit init);
|
toolkit/components/resistfingerprinting/RFPTargets.inc
| ... |
... |
@@ -101,6 +101,7 @@ ITEM_VALUE(JSLocalePrompt, 67) |
|
101
|
101
|
ITEM_VALUE(ScreenAvailToResolution, 68)
|
|
102
|
102
|
ITEM_VALUE(UseHardcodedFontSubstitutes, 69)
|
|
103
|
103
|
ITEM_VALUE(DiskStorageLimit, 70)
|
|
|
104
|
+ITEM_VALUE(WebCodecs, 71)
|
|
104
|
105
|
|
|
105
|
106
|
|
|
106
|
107
|
// !!! Don't forget to update kDefaultFingerprintingProtections in nsRFPService.cpp
|
toolkit/components/resistfingerprinting/nsRFPService.cpp
| ... |
... |
@@ -2697,3 +2697,48 @@ uint64_t nsRFPService::GetSpoofedStorageLimit() { |
|
2697
|
2697
|
|
|
2698
|
2698
|
return limit;
|
|
2699
|
2699
|
}
|
|
|
2700
|
+
|
|
|
2701
|
+/* static */
|
|
|
2702
|
+bool nsRFPService::ExposeWebCodecsAPI(JSContext* aCx, JSObject* aObj) {
|
|
|
2703
|
+ if (!StaticPrefs::dom_media_webcodecs_enabled()) {
|
|
|
2704
|
+ return false;
|
|
|
2705
|
+ }
|
|
|
2706
|
+
|
|
|
2707
|
+ return !IsWebCodecsRFPTargetEnabled(aCx);
|
|
|
2708
|
+}
|
|
|
2709
|
+
|
|
|
2710
|
+/* static */
|
|
|
2711
|
+bool nsRFPService::ExposeWebCodecsAPIImageDecoder(JSContext* aCx,
|
|
|
2712
|
+ JSObject* aObj) {
|
|
|
2713
|
+ if (!StaticPrefs::dom_media_webcodecs_image_decoder_enabled()) {
|
|
|
2714
|
+ return false;
|
|
|
2715
|
+ }
|
|
|
2716
|
+
|
|
|
2717
|
+ return !IsWebCodecsRFPTargetEnabled(aCx);
|
|
|
2718
|
+}
|
|
|
2719
|
+
|
|
|
2720
|
+/* static */
|
|
|
2721
|
+bool nsRFPService::IsWebCodecsRFPTargetEnabled(JSContext* aCx) {
|
|
|
2722
|
+ if (!nsContentUtils::ShouldResistFingerprinting("Efficiency check",
|
|
|
2723
|
+ RFPTarget::WebCodecs)) {
|
|
|
2724
|
+ return false;
|
|
|
2725
|
+ }
|
|
|
2726
|
+
|
|
|
2727
|
+ // We know that the RFPTarget::WebCodecs is enabled, check if principal
|
|
|
2728
|
+ // is exempted.
|
|
|
2729
|
+
|
|
|
2730
|
+ // VideoFrame::PrefEnabled function can be called without a JSContext.
|
|
|
2731
|
+ if (!aCx) {
|
|
|
2732
|
+ return true;
|
|
|
2733
|
+ }
|
|
|
2734
|
+
|
|
|
2735
|
+ // Once bug 1973966 is resolved, we can replace this section with just
|
|
|
2736
|
+ // nsIPrincipal* principal = nsContentUtils::SubjectPrincipal(aCx);
|
|
|
2737
|
+ JS::Realm* realm = js::GetContextRealm(aCx);
|
|
|
2738
|
+ MOZ_ASSERT(realm);
|
|
|
2739
|
+ JSPrincipals* principals = JS::GetRealmPrincipals(realm);
|
|
|
2740
|
+ nsIPrincipal* principal = nsJSPrincipals::get(principals);
|
|
|
2741
|
+
|
|
|
2742
|
+ return nsContentUtils::ShouldResistFingerprinting_dangerous(
|
|
|
2743
|
+ principal, "Principal is the best context we have", RFPTarget::WebCodecs);
|
|
|
2744
|
+} |
toolkit/components/resistfingerprinting/nsRFPService.h
| ... |
... |
@@ -416,6 +416,9 @@ class nsRFPService final : public nsIObserver, public nsIRFPService { |
|
416
|
416
|
|
|
417
|
417
|
static uint64_t GetSpoofedStorageLimit();
|
|
418
|
418
|
|
|
|
419
|
+ static bool ExposeWebCodecsAPI(JSContext* aCx, JSObject* aObj);
|
|
|
420
|
+ static bool ExposeWebCodecsAPIImageDecoder(JSContext* aCx, JSObject* aObj);
|
|
|
421
|
+
|
|
419
|
422
|
private:
|
|
420
|
423
|
nsresult Init();
|
|
421
|
424
|
|
| ... |
... |
@@ -527,6 +530,8 @@ class nsRFPService final : public nsIObserver, public nsIRFPService { |
|
527
|
530
|
static bool IsTargetActiveForMode(RFPTarget aTarget,
|
|
528
|
531
|
FingerprintingProtectionType aMode);
|
|
529
|
532
|
|
|
|
533
|
+ static bool IsWebCodecsRFPTargetEnabled(JSContext* aCx);
|
|
|
534
|
+
|
|
530
|
535
|
static nsCString* sExemptedDomainsLowercase;
|
|
531
|
536
|
};
|
|
532
|
537
|
|
|