Bug 1851802 - Make mixed content upgrade for audio/video/image individually togglable. r=freddyb

Differential Revision: https://phabricator.services.mozilla.com/D187782
This commit is contained in:
Tom Schuster 2023-09-13 11:27:12 +00:00
Родитель 098b0c4de6
Коммит f2c9b9e900
10 изменённых файлов: 219 добавлений и 58 удалений

Просмотреть файл

@ -914,9 +914,16 @@ nsCSPDirective* nsCSPParser::directiveName() {
// special case handling for block-all-mixed-content
if (directive == nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT) {
// If mixed content upgrade is enabled block-all-mixed content is obsolete
// If mixed content upgrade is enabled for all types block-all-mixed-content
// is obsolete
if (mozilla::StaticPrefs::
security_mixed_content_upgrade_display_content()) {
security_mixed_content_upgrade_display_content() &&
mozilla::StaticPrefs::
security_mixed_content_upgrade_display_content_image() &&
mozilla::StaticPrefs::
security_mixed_content_upgrade_display_content_audio() &&
mozilla::StaticPrefs::
security_mixed_content_upgrade_display_content_video()) {
// log to the console that if mixed content display upgrading is enabled
// block-all-mixed-content is obsolete.
AutoTArray<nsString, 1> params = {mCurToken};

Просмотреть файл

@ -371,12 +371,32 @@ bool nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(nsIURI* aURI) {
}
/* static */
bool nsMixedContentBlocker::IsUpgradableContentType(nsContentPolicyType aType) {
bool nsMixedContentBlocker::IsUpgradableContentType(nsContentPolicyType aType,
bool aConsiderPrefs) {
MOZ_ASSERT(NS_IsMainThread());
return (aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE ||
aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_AUDIO ||
aType == nsIContentPolicy::TYPE_INTERNAL_VIDEO);
if (aConsiderPrefs &&
!StaticPrefs::security_mixed_content_upgrade_display_content()) {
return false;
}
switch (aType) {
case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
return !aConsiderPrefs ||
StaticPrefs::
security_mixed_content_upgrade_display_content_image();
case nsIContentPolicy::TYPE_INTERNAL_AUDIO:
return !aConsiderPrefs ||
StaticPrefs::
security_mixed_content_upgrade_display_content_audio();
case nsIContentPolicy::TYPE_INTERNAL_VIDEO:
return !aConsiderPrefs ||
StaticPrefs::
security_mixed_content_upgrade_display_content_video();
default:
return false;
}
}
/*
@ -766,8 +786,7 @@ nsresult nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
// be upgraded to https before fetching any data from the netwerk.
if (isHttpScheme) {
bool isUpgradableContentType =
IsUpgradableContentType(internalContentType) &&
StaticPrefs::security_mixed_content_upgrade_display_content();
IsUpgradableContentType(internalContentType, /* aConsiderPrefs */ true);
if (isUpgradableContentType) {
*aDecision = ACCEPT;
return NS_OK;

Просмотреть файл

@ -61,8 +61,13 @@ class nsMixedContentBlocker : public nsIContentPolicy,
/**
* Returns true if the provided content policy type is subject to the
* mixed content level 2 upgrading mechanism (audio, video, image).
*
* @param aConsiderPrefs A boolean that indicates whether the result of this
* functions takes the `security.mixed_content.upgrade_display_content`
* preferences into account.
*/
static bool IsUpgradableContentType(nsContentPolicyType aType);
static bool IsUpgradableContentType(nsContentPolicyType aType,
bool aConsiderPrefs);
/* Static version of ShouldLoad() that contains all the Mixed Content Blocker
* logic. Called from non-static ShouldLoad().

Просмотреть файл

@ -9,7 +9,10 @@ const TEST_TOPLEVEL_URI = TEST_PATH + "auto_upgrading_identity.html";
// auto upgrading mixed content should not indicate passive mixed content loaded
add_task(async () => {
await SpecialPowers.pushPrefEnv({
set: [["security.mixed_content.upgrade_display_content", true]],
set: [
["security.mixed_content.upgrade_display_content", true],
["security.mixed_content.upgrade_display_content.image", true],
],
});
await BrowserTestUtils.withNewTab(
TEST_TOPLEVEL_URI,

Просмотреть файл

@ -9,70 +9,163 @@ const PRE_PATH = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"https://example.com"
);
var gTestBrowser = null;
let expectedMessages = 3;
function on_new_message(msgObj) {
const message = msgObj.message;
let gExpectedMessages = 0;
let gExpectBlockAllMsg = false;
function onConsoleMessage({ message }) {
// Check if csp warns about block-all-mixed content being obsolete
if (message.includes("Content-Security-Policy")) {
ok(
message.includes("block-all-mixed-content obsolete"),
"CSP warns about block-all-mixed content being obsolete"
);
if (gExpectBlockAllMsg) {
ok(
message.includes("block-all-mixed-content obsolete"),
"CSP warns about block-all-mixed content being obsolete"
);
} else {
ok(
message.includes("Blocking insecure request"),
"CSP error about blocking insecure request"
);
}
}
if (message.includes("Mixed Content:")) {
ok(
message.includes("Upgrading insecure display request"),
"msg included a mixed content upgrade"
);
expectedMessages--;
gExpectedMessages--;
}
}
add_task(async function () {
await SpecialPowers.pushPrefEnv({
set: [["security.mixed_content.upgrade_display_content", true]],
});
Services.console.registerListener(on_new_message);
// Starting the test
var url =
async function checkLoadedElements() {
let url =
PRE_PATH +
"file_csp_block_all_mixedcontent_and_mixed_content_display_upgrade.html";
await BrowserTestUtils.withNewTab(
return BrowserTestUtils.withNewTab(
{
gBrowser,
url,
waitForLoad: true,
},
async function (browser) {
let loadedElements = await ContentTask.spawn(
browser,
[],
async function () {
// Check image loaded
let image = content.document.getElementById("some-img");
let imageLoaded =
image && image.complete && image.naturalHeight !== 0;
// Check audio loaded
let audio = content.document.getElementById("some-audio");
let audioLoaded = audio && audio.readyState >= 2;
// Check video loaded
let video = content.document.getElementById("some-video");
//let videoPlayable = await once(video, "loadeddata").then(_ => true);
let videoLoaded = video && video.readyState === 4;
return { audio: audioLoaded, img: imageLoaded, video: videoLoaded };
}
);
is(true, loadedElements.img, "Image loaded and was upgraded " + url);
is(true, loadedElements.video, "Video loaded and was upgraded " + url);
is(true, loadedElements.audio, "Audio loaded and was upgraded " + url);
return ContentTask.spawn(browser, [], async function () {
console.log(content.document.innerHTML);
// Check image loaded
let image = content.document.getElementById("some-img");
let imageLoaded = image && image.complete && image.naturalHeight !== 0;
// Check audio loaded
let audio = content.document.getElementById("some-audio");
let audioLoaded = audio && audio.readyState >= 2;
// Check video loaded
let video = content.document.getElementById("some-video");
//let videoPlayable = await once(video, "loadeddata").then(_ => true);
let videoLoaded = video && video.readyState === 4;
return { audio: audioLoaded, img: imageLoaded, video: videoLoaded };
});
}
);
}
await BrowserTestUtils.waitForCondition(() => expectedMessages === 0);
add_task(async function test_upgrade_all() {
await SpecialPowers.pushPrefEnv({
set: [
["security.mixed_content.upgrade_display_content", true],
// Not enabled by default outside Nightly.
["security.mixed_content.upgrade_display_content.image", true],
],
});
Services.console.registerListener(onConsoleMessage);
// Starting the test
gExpectedMessages = 3;
gExpectBlockAllMsg = true;
let loadedElements = await checkLoadedElements();
is(loadedElements.img, true, "Image loaded and was upgraded");
is(loadedElements.video, true, "Video loaded and was upgraded");
is(loadedElements.audio, true, "Audio loaded and was upgraded");
await BrowserTestUtils.waitForCondition(() => gExpectedMessages === 0);
// Clean up
Services.console.unregisterListener(on_new_message);
Services.console.unregisterListener(onConsoleMessage);
SpecialPowers.popPrefEnv();
});
add_task(async function test_dont_upgrade_image() {
await SpecialPowers.pushPrefEnv({
set: [
["security.mixed_content.upgrade_display_content", true],
["security.mixed_content.upgrade_display_content.image", false],
],
});
Services.console.registerListener(onConsoleMessage);
// Starting the test
gExpectedMessages = 2;
gExpectBlockAllMsg = false;
let loadedElements = await checkLoadedElements();
is(loadedElements.img, false, "Image was not loaded");
is(loadedElements.video, true, "Video loaded and was upgraded");
is(loadedElements.audio, true, "Audio loaded and was upgraded");
await BrowserTestUtils.waitForCondition(() => gExpectedMessages === 0);
// Clean up
Services.console.unregisterListener(onConsoleMessage);
SpecialPowers.popPrefEnv();
});
add_task(async function test_dont_upgrade_audio() {
await SpecialPowers.pushPrefEnv({
set: [
["security.mixed_content.upgrade_display_content", true],
["security.mixed_content.upgrade_display_content.image", true],
["security.mixed_content.upgrade_display_content.audio", false],
],
});
Services.console.registerListener(onConsoleMessage);
// Starting the test
gExpectedMessages = 2;
gExpectBlockAllMsg = false;
let loadedElements = await checkLoadedElements();
is(loadedElements.img, true, "Image loaded and was upgraded");
is(loadedElements.video, true, "Video loaded and was upgraded");
is(loadedElements.audio, false, "Audio was not loaded");
await BrowserTestUtils.waitForCondition(() => gExpectedMessages === 0);
// Clean up
Services.console.unregisterListener(onConsoleMessage);
SpecialPowers.popPrefEnv();
});
add_task(async function test_dont_upgrade_video() {
await SpecialPowers.pushPrefEnv({
set: [
["security.mixed_content.upgrade_display_content", true],
["security.mixed_content.upgrade_display_content.image", true],
["security.mixed_content.upgrade_display_content.video", false],
],
});
Services.console.registerListener(onConsoleMessage);
// Starting the test
gExpectedMessages = 2;
gExpectBlockAllMsg = false;
let loadedElements = await checkLoadedElements();
is(loadedElements.img, true, "Image loaded and was upgraded");
is(loadedElements.video, false, "Video was not loaded");
is(loadedElements.audio, true, "Audio loaded and was upgraded");
await BrowserTestUtils.waitForCondition(() => gExpectedMessages === 0);
// Clean up
Services.console.unregisterListener(onConsoleMessage);
SpecialPowers.popPrefEnv();
});

Просмотреть файл

@ -18,7 +18,10 @@ add_task(async function () {
// Enable HTTPS-Only Mode and register console-listener
await SpecialPowers.pushPrefEnv({
set: [["security.mixed_content.upgrade_display_content", true]],
set: [
["security.mixed_content.upgrade_display_content", true],
["security.mixed_content.upgrade_display_content.image", true],
],
});
Services.console.registerListener(on_auto_upgrade_message);

Просмотреть файл

@ -13545,12 +13545,30 @@
value: false
mirror: always
# Pref for mixed display content upgrading (images, audio, video).
# Prerequisite pref for mixed display content upgrading (images, audio, video).
- name: security.mixed_content.upgrade_display_content
type: bool
value: @IS_NIGHTLY_BUILD@
mirror: always
# Upgrade images when the upgrading is enabled.
- name: security.mixed_content.upgrade_display_content.image
type: bool
value: @IS_NIGHTLY_BUILD@
mirror: always
# Upgrade audio when the upgrading is enabled.
- name: security.mixed_content.upgrade_display_content.audio
type: bool
value: true
mirror: always
# Upgrade videos when the upgrading is enabled.
- name: security.mixed_content.upgrade_display_content.video
type: bool
value: true
mirror: always
# Whether strict file origin policy is in effect. "False" is traditional.
- name: security.fileuri.strict_origin_policy
type: RelaxedAtomicBool

Просмотреть файл

@ -266,11 +266,12 @@ LoadInfo::LoadInfo(
}
if (nsMixedContentBlocker::IsUpgradableContentType(
mInternalContentPolicyType)) {
mInternalContentPolicyType, /* aConsiderPrefs */ false)) {
// Check the load is within a secure context but ignore loopback URLs
if (mLoadingPrincipal->GetIsOriginPotentiallyTrustworthy() &&
!mLoadingPrincipal->GetIsLoopbackHost()) {
if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
if (nsMixedContentBlocker::IsUpgradableContentType(
mInternalContentPolicyType, /* aConsiderPrefs */ true)) {
mBrowserUpgradeInsecureRequests = true;
} else {
mBrowserWouldUpgradeInsecureRequests = true;

Просмотреть файл

@ -1 +1 @@
prefs: [security.mixed_content.upgrade_display_content:true]
prefs: [security.mixed_content.upgrade_display_content:true,security.mixed_content.upgrade_display_content.image:true]

Просмотреть файл

@ -1524,10 +1524,22 @@ mixedContentUpgrading:
owner: fbraun@mozilla.com
hasExposure: false
variables:
boolean:
enabled:
description: True if the mixed content upgrading pref is enabled
type: boolean
setPref: security.mixed_content.upgrade_display_content
image:
description: True if the mixed content upgrading is enabled for images
type: boolean
setPref: security.mixed_content.upgrade_display_content.image
audio:
description: True if the mixed content upgrading is enabled for audio
type: boolean
setPref: security.mixed_content.upgrade_display_content.audio
video:
description: True if the mixed content upgrading is enabled for videos
type: boolean
setPref: security.mixed_content.upgrade_display_content.video
jsParallelParsing:
description: Pref to toggle JS parallel parsing.