0

Update AlwaysBlock3pcsIncognito extensions logic + fix resulting tests

This CL does a couple of things:
1) Updates extensions logic to throw an error if an extension tries to
allow third-party cookies specifically in incognito when
`AlwaysBlock3pcsIncognito` is enabled. Includes test coverage for this

2) Enables `AlwaysBlock3pcsIncognito` by default in preference_apitest

3) Updates general extension testing that uses thirdPartyCookiesAllowed
to instead use hyperlinkAuditingEnabled for equivalent coverage

Bug: b:370008370
Change-Id: I43afcaa298dcf05b564359392bc8979bc89cf004
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6305649
Reviewed-by: Kevin Graney <kmg@google.com>
Commit-Queue: Devlin Cronin <rdevlin.cronin@chromium.org>
Commit-Queue: Fiona Macintosh <fmacintosh@google.com>
Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org>
Auto-Submit: Fiona Macintosh <fmacintosh@google.com>
Cr-Commit-Position: refs/heads/main@{#1427252}
This commit is contained in:
Fiona Macintosh
2025-03-03 10:57:36 -08:00
committed by Chromium LUCI CQ
parent 50cb5a55f6
commit 62b851db10
11 changed files with 182 additions and 92 deletions
chrome
browser
test
data
extensions
api_test
preference
onchange
onchange_split
onchange_split_regular_only
persistent_incognito
session_only_incognito
third_party_cookies_allowed_incognito
extensions/common

@ -22,7 +22,7 @@ source_set("preference") {
"//chrome/browser/profiles",
"//components/autofill/core/common",
"//components/prefs",
"//components/privacy_sandbox:tracking_protection_prefs",
"//components/privacy_sandbox:features",
"//extensions/browser",
"//extensions/browser/api/content_settings",
"//extensions/common",

@ -12,6 +12,7 @@
#include <utility>
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/lazy_instance.h"
#include "base/values.h"
@ -21,8 +22,9 @@
#include "chrome/browser/extensions/pref_transformer_interface.h"
#include "chrome/browser/extensions/preference/preference_helpers.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/privacy_sandbox/tracking_protection_prefs.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "extensions/browser/api/content_settings/content_settings_service.h"
#include "extensions/browser/extension_function_registry.h"
@ -398,6 +400,16 @@ ExtensionFunction::ResponseAction SetPreferenceFunction::Run() {
if (!extension()->permissions_data()->HasAPIPermission(write_permission))
return RespondNow(Error(kPermissionErrorMessage, pref_key));
// If 3PCs are globally blocked in incognito re-allowing them is not
// supported, so error out.
if (incognito && browser_pref == prefs::kCookieControlsMode &&
value->GetBool() &&
base::FeatureList::IsEnabled(
privacy_sandbox::kAlwaysBlock3pcsIncognito)) {
return RespondNow(
Error(extension_misc::kCookiesAllowedIncognitoErrorMessage));
}
ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context());
const PrefService::Preference* pref =
prefs->pref_service()->FindPreference(browser_pref);

@ -58,7 +58,10 @@ class ExtensionPreferenceApiTest
delete;
protected:
ExtensionPreferenceApiTest() : ExtensionApiTest(GetParam()) {}
ExtensionPreferenceApiTest() : ExtensionApiTest(GetParam()) {
feature_list_.InitAndEnableFeature(
privacy_sandbox::kAlwaysBlock3pcsIncognito);
}
~ExtensionPreferenceApiTest() override = default;
void SetCookieControlsMode(PrefService* prefs, CookieControlsMode mode) {
@ -188,6 +191,7 @@ class ExtensionPreferenceApiTest
raw_ptr<Profile, DanglingUntriaged> profile_ = nullptr;
std::unique_ptr<ScopedKeepAlive> keep_alive_;
base::test::ScopedFeatureList feature_list_;
};
INSTANTIATE_TEST_SUITE_P(BackgroundPage,
@ -273,9 +277,20 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, Standard) {
CheckPreferencesCleared();
}
IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest,
ThirdPartyCookiesAllowedIncognito) {
PrefService* prefs = profile_->GetPrefs();
SetCookieControlsMode(prefs, CookieControlsMode::kBlockThirdParty);
EXPECT_TRUE(
RunExtensionTest("preference/third_party_cookies_allowed_incognito", {},
{.allow_in_incognito = true}))
<< message_;
}
IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, PersistentIncognito) {
PrefService* prefs = profile_->GetPrefs();
SetCookieControlsMode(prefs, CookieControlsMode::kOff);
prefs->SetBoolean(prefs::kEnableHyperlinkAuditing, true);
EXPECT_TRUE(RunExtensionTest("preference/persistent_incognito", {},
{.allow_in_incognito = true}))
@ -286,16 +301,15 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, PersistentIncognito) {
PrefService* otr_prefs =
profile_->GetPrimaryOTRProfile(/*create_if_needed=*/true)->GetPrefs();
auto* otr_pref = otr_prefs->FindPreference(prefs::kCookieControlsMode);
auto* otr_pref = otr_prefs->FindPreference(prefs::kEnableHyperlinkAuditing);
ASSERT_TRUE(otr_pref);
EXPECT_TRUE(otr_pref->IsExtensionControlled());
EXPECT_EQ(CookieControlsMode::kBlockThirdParty,
GetCookieControlsMode(otr_prefs));
EXPECT_FALSE(otr_prefs->GetBoolean(prefs::kEnableHyperlinkAuditing));
auto* pref = prefs->FindPreference(prefs::kCookieControlsMode);
auto* pref = prefs->FindPreference(prefs::kEnableHyperlinkAuditing);
ASSERT_TRUE(pref);
EXPECT_FALSE(pref->IsExtensionControlled());
EXPECT_EQ(CookieControlsMode::kOff, GetCookieControlsMode(prefs));
EXPECT_TRUE(prefs->GetBoolean(prefs::kEnableHyperlinkAuditing));
}
IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, IncognitoDisabled) {
@ -304,7 +318,7 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, IncognitoDisabled) {
IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, SessionOnlyIncognito) {
PrefService* prefs = profile_->GetPrefs();
SetCookieControlsMode(prefs, CookieControlsMode::kOff);
prefs->SetBoolean(prefs::kEnableHyperlinkAuditing, true);
EXPECT_TRUE(RunExtensionTest("preference/session_only_incognito", {},
{.allow_in_incognito = true}))
@ -314,15 +328,15 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, SessionOnlyIncognito) {
PrefService* otr_prefs =
profile_->GetPrimaryOTRProfile(/*create_if_needed=*/true)->GetPrefs();
auto* otr_pref = otr_prefs->FindPreference(prefs::kCookieControlsMode);
auto* otr_pref = otr_prefs->FindPreference(prefs::kEnableHyperlinkAuditing);
ASSERT_TRUE(otr_pref);
EXPECT_TRUE(otr_pref->IsExtensionControlled());
EXPECT_EQ(CookieControlsMode::kOff, GetCookieControlsMode(otr_prefs));
EXPECT_TRUE(otr_prefs->GetBoolean(prefs::kEnableHyperlinkAuditing));
auto* pref = prefs->FindPreference(prefs::kCookieControlsMode);
auto* pref = prefs->FindPreference(prefs::kEnableHyperlinkAuditing);
ASSERT_TRUE(pref);
EXPECT_FALSE(pref->IsExtensionControlled());
EXPECT_EQ(CookieControlsMode::kOff, GetCookieControlsMode(prefs));
EXPECT_TRUE(prefs->GetBoolean(prefs::kEnableHyperlinkAuditing));
}
IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, Clear) {
@ -468,7 +482,7 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, OnChangeSplit) {
IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest,
OnChangeSplitWithNoOTRProfile) {
PrefService* prefs = profile_->GetPrefs();
SetCookieControlsMode(prefs, CookieControlsMode::kBlockThirdParty);
prefs->SetBoolean(prefs::kEnableHyperlinkAuditing, false);
extensions::ResultCatcher catcher;
ExtensionTestMessageListener loaded_incognito_test_listener(
@ -481,7 +495,7 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest,
{.allow_in_incognito = true}));
ASSERT_TRUE(change_pref_listener.WaitUntilSatisfied());
SetCookieControlsMode(prefs, CookieControlsMode::kOff);
prefs->SetBoolean(prefs::kEnableHyperlinkAuditing, true);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
EXPECT_FALSE(loaded_incognito_test_listener.was_satisfied());
@ -491,7 +505,7 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest,
IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest,
OnChangeSplitWithoutIncognitoAccess) {
PrefService* prefs = profile_->GetPrefs();
SetCookieControlsMode(prefs, CookieControlsMode::kBlockThirdParty);
prefs->SetBoolean(prefs::kEnableHyperlinkAuditing, false);
// Open an incognito window.
OpenURLOffTheRecord(profile_, GURL("chrome://newtab/"));
@ -507,7 +521,7 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest,
.AppendASCII("onchange_split_regular_only")));
ASSERT_TRUE(change_pref_listener.WaitUntilSatisfied());
SetCookieControlsMode(prefs, CookieControlsMode::kOff);
prefs->SetBoolean(prefs::kEnableHyperlinkAuditing, true);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
EXPECT_FALSE(loaded_incognito_test_listener.was_satisfied());

@ -25,7 +25,7 @@ chrome.test.runTests([
function changeDefault() {
// Changing the regular settings when no incognito-specific settings are
// defined should fire two events.
listenUntil(pw.thirdPartyCookiesAllowed.onChange, [{
listenUntil(pw.hyperlinkAuditingEnabled.onChange, [{
'value': false,
'levelOfControl': 'controlled_by_this_extension'
},
@ -34,63 +34,63 @@ chrome.test.runTests([
'incognitoSpecific': false,
'levelOfControl': 'controlled_by_this_extension'
}]);
pw.thirdPartyCookiesAllowed.set({
pw.hyperlinkAuditingEnabled.set({
'value':false
}, chrome.test.callbackPass());
},
function changeIncognitoOnly() {
listenUntil(pw.thirdPartyCookiesAllowed.onChange, [{
listenUntil(pw.hyperlinkAuditingEnabled.onChange, [{
'value': true,
'incognitoSpecific': true,
'levelOfControl': 'controlled_by_this_extension'
}]);
pw.thirdPartyCookiesAllowed.set({
pw.hyperlinkAuditingEnabled.set({
'value': true,
'scope': 'incognito_persistent'
}, chrome.test.callbackPass());
},
function changeDefaultOnly() {
listenUntil(pw.thirdPartyCookiesAllowed.onChange, [{
listenUntil(pw.hyperlinkAuditingEnabled.onChange, [{
'value': true,
'levelOfControl': 'controlled_by_this_extension'
}]);
pw.thirdPartyCookiesAllowed.set({
pw.hyperlinkAuditingEnabled.set({
'value': true
}, chrome.test.callbackPass());
},
function changeIncognitoOnlyBack() {
// Change the incognito setting back to false so that we get an event when
// clearing the value.
listenUntil(pw.thirdPartyCookiesAllowed.onChange, [{
listenUntil(pw.hyperlinkAuditingEnabled.onChange, [{
'value': false,
'incognitoSpecific': true,
'levelOfControl': 'controlled_by_this_extension'
}]);
pw.thirdPartyCookiesAllowed.set({
pw.hyperlinkAuditingEnabled.set({
'value': false,
'scope': 'incognito_persistent'
}, chrome.test.callbackPass());
},
function clearIncognito() {
listenUntil(pw.thirdPartyCookiesAllowed.onChange, [{
listenUntil(pw.hyperlinkAuditingEnabled.onChange, [{
'value': true,
'incognitoSpecific': false,
'levelOfControl': 'controlled_by_this_extension'
}]);
pw.thirdPartyCookiesAllowed.clear({
pw.hyperlinkAuditingEnabled.clear({
'scope': 'incognito_persistent'
}, chrome.test.callbackPass());
},
function clearDefault() {
listenUntil(pw.thirdPartyCookiesAllowed.onChange, [{
listenUntil(pw.hyperlinkAuditingEnabled.onChange, [{
'value': true,
'levelOfControl': 'controllable_by_this_extension'
},
{
'value': false,
'value': true,
'incognitoSpecific': false,
'levelOfControl': 'controllable_by_this_extension'
}]);
pw.thirdPartyCookiesAllowed.clear({}, chrome.test.callbackPass());
pw.hyperlinkAuditingEnabled.clear({}, chrome.test.callbackPass());
}
]);

@ -8,7 +8,7 @@
var inIncognitoContext = chrome.extension.inIncognitoContext;
var pass = chrome.test.callbackPass;
var sendMessage = chrome.test.sendMessage;
var allowCookies = chrome.privacy.websites.thirdPartyCookiesAllowed;
var hyperlinkAuditing = chrome.privacy.websites.hyperlinkAuditingEnabled;
// Listen until |event| has fired with all of the values in |expected|.
function listenUntil(event, expected) {
@ -62,13 +62,11 @@ chrome.test.runTests([
});
}
listenUntil(allowCookies.onChange, expected);
listenUntil(hyperlinkAuditing.onChange, expected);
sendMessage(constructMessage("ready"), pass(function() {
if (!inIncognitoContext) {
allowCookies.set({
'value': false
}, pass());
hyperlinkAuditing.set({'value': false}, pass());
}
}));
},
@ -77,10 +75,10 @@ chrome.test.runTests([
// incognito window.
function changeIncognitoOnly() {
if (!inIncognitoContext) {
var done = listenAndFailWhen(allowCookies.onChange);
var done = listenAndFailWhen(hyperlinkAuditing.onChange);
sendMessage(constructMessage("listening"), done);
} else {
listenUntil(allowCookies.onChange, [{
listenUntil(hyperlinkAuditing.onChange, [{
'value': true,
'incognitoSpecific': true,
'levelOfControl': 'controlled_by_this_extension'
@ -89,7 +87,7 @@ chrome.test.runTests([
sendMessage(constructMessage("ready"), pass(function() {
if (inIncognitoContext) {
allowCookies.set({
hyperlinkAuditing.set({
'value': true,
'scope': 'incognito_session_only'
}, pass(function() {
@ -104,18 +102,18 @@ chrome.test.runTests([
// defined should only be visible to the regular window.
function changeDefaultOnly() {
if (!inIncognitoContext) {
listenUntil(allowCookies.onChange, [{
listenUntil(hyperlinkAuditing.onChange, [{
'value': true,
'levelOfControl': 'controlled_by_this_extension'
}]);
} else {
var done = listenAndFailWhen(allowCookies.onChange);
var done = listenAndFailWhen(hyperlinkAuditing.onChange);
sendMessage(constructMessage("listening"), done);
}
sendMessage(constructMessage("ready"), pass(function() {
if (!inIncognitoContext) {
allowCookies.set({
hyperlinkAuditing.set({
'value': true
}, pass(function() {
sendMessage(constructMessage("pref set", "changeDefaultOnly"),
@ -129,10 +127,10 @@ chrome.test.runTests([
// clearing the value. Should not be visible to regular window.
function changeIncognitoOnlyBack() {
if (!inIncognitoContext) {
var done = listenAndFailWhen(allowCookies.onChange);
var done = listenAndFailWhen(hyperlinkAuditing.onChange);
sendMessage(constructMessage("listening"), done);
} else {
listenUntil(allowCookies.onChange, [{
listenUntil(hyperlinkAuditing.onChange, [{
'value': false,
'incognitoSpecific': true,
'levelOfControl': 'controlled_by_this_extension'
@ -141,7 +139,7 @@ chrome.test.runTests([
sendMessage(constructMessage("ready"), pass(function() {
if (inIncognitoContext) {
allowCookies.set({
hyperlinkAuditing.set({
'value': false,
'scope': 'incognito_session_only'
}, pass(function() {
@ -154,10 +152,10 @@ chrome.test.runTests([
function clearIncognito() {
if (!inIncognitoContext) {
var done = listenAndFailWhen(allowCookies.onChange);
var done = listenAndFailWhen(hyperlinkAuditing.onChange);
sendMessage(constructMessage("listening"), done);
} else {
listenUntil(allowCookies.onChange, [{
listenUntil(hyperlinkAuditing.onChange, [{
'value': true,
'incognitoSpecific': false,
'levelOfControl': 'controlled_by_this_extension'
@ -166,7 +164,7 @@ chrome.test.runTests([
sendMessage(constructMessage("ready"), pass(function() {
if (inIncognitoContext) {
allowCookies.clear({
hyperlinkAuditing.clear({
'scope': 'incognito_session_only'
}, pass(function() {
sendMessage(constructMessage("pref cleared", "clearIncognito"),
@ -184,17 +182,17 @@ chrome.test.runTests([
if (inIncognitoContext) {
expected[1] = {
'value': false,
'value': true,
'incognitoSpecific': false,
'levelOfControl': 'controllable_by_this_extension'
};
}
listenUntil(allowCookies.onChange, expected);
listenUntil(hyperlinkAuditing.onChange, expected);
sendMessage(constructMessage("ready"), pass(function() {
if (!inIncognitoContext)
allowCookies.clear({}, pass());
hyperlinkAuditing.clear({}, pass());
}));
}
]);

@ -5,7 +5,7 @@
// Tests preference.onChange API for an incognito split extension in case the
// extension's incognito instance is not expected to be brought up.
var allowCookies = chrome.privacy.websites.thirdPartyCookiesAllowed;
var hyperlinkAuditing = chrome.privacy.websites.hyperlinkAuditingEnabled;
function PreferenceChangeListener() {
this.encounteredEvents = [];
@ -51,7 +51,7 @@ PreferenceChangeListener.prototype.onPrefChanged_ = function(pref) {
callbacks.forEach(callback => callback());
};
var allowCookiesChangeListener = null;
var hyperlinkAuditingChangeListener = null;
// The incognito background is not expected to be run - send a message to the
// test runner, and bail out.
@ -60,14 +60,14 @@ if (chrome.extension.inIncognitoContext) {
} else {
chrome.test.runTests([
function setupPreferenceListener() {
chrome.test.assertFalse(!!allowCookiesChangeListener);
allowCookiesChangeListener = new PreferenceChangeListener();
allowCookiesChangeListener.start(allowCookies.onChange);
chrome.test.assertFalse(!!hyperlinkAuditingChangeListener);
hyperlinkAuditingChangeListener = new PreferenceChangeListener();
hyperlinkAuditingChangeListener.start(hyperlinkAuditing.onChange);
chrome.test.succeed();
},
function getInitialValue() {
allowCookies.get({}, chrome.test.callbackPass(pref => {
hyperlinkAuditing.get({}, chrome.test.callbackPass(pref => {
chrome.test.assertEq(
{levelOfControl: 'controllable_by_this_extension', value: false},
pref);
@ -75,10 +75,10 @@ if (chrome.extension.inIncognitoContext) {
},
function listenForUserChange() {
allowCookiesChangeListener.listenForValue(
hyperlinkAuditingChangeListener.listenForValue(
true, chrome.test.callbackPass(function() {
var events =
allowCookiesChangeListener.getAndClearEncounteredEvents();
hyperlinkAuditingChangeListener.getAndClearEncounteredEvents();
chrome.test.assertEq(events, [
{levelOfControl: 'controllable_by_this_extension', value: true}
]);
@ -88,41 +88,41 @@ if (chrome.extension.inIncognitoContext) {
},
function changeDefault() {
allowCookiesChangeListener.listenForValue(
hyperlinkAuditingChangeListener.listenForValue(
false, chrome.test.callbackPass(function() {
var events =
allowCookiesChangeListener.getAndClearEncounteredEvents();
hyperlinkAuditingChangeListener.getAndClearEncounteredEvents();
chrome.test.assertEq(events, [
{value: false, levelOfControl: 'controlled_by_this_extension'}
]);
}));
allowCookies.set({value: false}, chrome.test.callbackPass());
hyperlinkAuditing.set({value: false}, chrome.test.callbackPass());
},
function changeIncognitoOnly() {
allowCookies.set(
hyperlinkAuditing.set(
{value: true, scope: 'incognito_session_only'},
chrome.test.callbackFail(
'You do not have permission to access incognito preferences.'));
},
function clearControl() {
allowCookiesChangeListener.listenForValue(
hyperlinkAuditingChangeListener.listenForValue(
true, chrome.test.callbackPass(function() {
var events =
allowCookiesChangeListener.getAndClearEncounteredEvents();
hyperlinkAuditingChangeListener.getAndClearEncounteredEvents();
chrome.test.assertEq(events, [
{levelOfControl: 'controllable_by_this_extension', value: true}
]);
}));
allowCookies.clear({}, chrome.test.callbackPass());
hyperlinkAuditing.clear({}, chrome.test.callbackPass());
},
function stopPreferenceListener() {
var listener = allowCookiesChangeListener;
allowCookiesChangeListener = null;
var listener = hyperlinkAuditingChangeListener;
hyperlinkAuditingChangeListener = null;
listener.stop(chrome.test.callbackPass());
}
]);

@ -14,38 +14,38 @@ function expect(expected, message) {
}
chrome.test.runTests([
function getRegular() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{},
expect({ 'value': true,
'levelOfControl': "controllable_by_this_extension" },
"third-party cookies should not be blocked"));
"hyperlink auditing should be enabled"));
},
function getIncognito() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{ 'incognito': true },
expect({ 'value': true,
'incognitoSpecific': false,
'levelOfControl': "controllable_by_this_extension" },
"third-party cookies should not be blocked in incognito mode"));
"hyperlink auditing should be enabled in incognito mode"));
},
function set() {
pw.thirdPartyCookiesAllowed.set(
pw.hyperlinkAuditingEnabled.set(
{ 'scope': 'incognito_persistent', 'value': false },
chrome.test.callbackPass());
},
function getRegular2() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{},
expect({ 'value': true,
'levelOfControl': "controllable_by_this_extension" },
"third-party cookies should not be blocked"));
"hyperlink auditing should be enabled"));
},
function getIncognito2() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{ 'incognito': true },
expect({ 'value': false,
'incognitoSpecific': true,
'levelOfControl': "controlled_by_this_extension" },
"third-party cookies should be blocked in incognito mode"));
"hyperlink auditing should be disabled in incognito mode"));
},
]);

@ -14,44 +14,44 @@ function expect(expected, message) {
}
chrome.test.runTests([
function getRegular() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{},
expect({ 'value': true,
'levelOfControl': "controllable_by_this_extension" },
"third-party cookies should not be blocked"));
"hyperlink auditing should be enabled"));
},
function getIncognito() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{ 'incognito': true },
expect({ 'value': true,
'incognitoSpecific': false,
'levelOfControl': "controllable_by_this_extension" },
"third-party cookies should not be blocked in incognito mode"));
"hyperlink auditing should be enabled in incognito mode"));
},
function set() {
pw.thirdPartyCookiesAllowed.set(
pw.hyperlinkAuditingEnabled.set(
{ 'scope': 'incognito_persistent', 'value': false },
chrome.test.callbackPass());
},
function getRegular2() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{},
expect({ 'value': true,
'levelOfControl': "controllable_by_this_extension" },
"third-party cookies should not be blocked"));
"hyperlink auditing should be enabled"));
},
function getIncognito2() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{ 'incognito': true },
expect({ 'value': false,
'incognitoSpecific': true,
'levelOfControl': "controlled_by_this_extension" },
"third-party cookies should be blocked in incognito mode"));
"hyperlink auditing should be disabled in incognito mode"));
},
// We cannot set session_only_persistent preferences if there is no incognito
// session.
function set2() {
pw.thirdPartyCookiesAllowed.set(
pw.hyperlinkAuditingEnabled.set(
{ 'scope': 'incognito_session_only', 'value': true },
chrome.test.callbackFail("You cannot set a preference with scope " +
"'incognito_session_only' when no incognito " +
@ -62,23 +62,23 @@ chrome.test.runTests([
},
// session_only_persistent overrides incognito_persistent.
function set3() {
pw.thirdPartyCookiesAllowed.set(
pw.hyperlinkAuditingEnabled.set(
{ 'scope': 'incognito_session_only', 'value': true },
chrome.test.callbackPass());
},
function getRegular3() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{},
expect({ 'value': true,
'levelOfControl': "controllable_by_this_extension" },
"third-party cookies should not be blocked"));
"hyperlink auditing should be enabled"));
},
function getIncognito3() {
pw.thirdPartyCookiesAllowed.get(
pw.hyperlinkAuditingEnabled.get(
{ 'incognito': true },
expect({ 'value': true,
'incognitoSpecific': true,
'levelOfControl': "controlled_by_this_extension" },
"third-party cookies should be blocked in incognito mode"));
"hyperlink auditing should be enabled in incognito mode"));
},
]);

@ -0,0 +1,11 @@
{
"name" : "Preferences API Test Extension (thirdPartyCookiesAllowed Incognito)",
"version" : "0.1",
"manifest_version": 2,
"description" : "Preferences API Test Extension (thirdPartyCookiesAllowed Incognito)",
"permissions": [ "privacy" ],
"background": {
"scripts": ["test.js"],
"persistent": false
}
}

@ -0,0 +1,51 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Content settings API test
// Run with browser_tests
// --gtest_filter=ExtensionPreferenceApiTest.ThirdPartyCookiesAllowedIncognito
var pw = chrome.privacy.websites;
const thirdPartyCookiesAllowedIncognitoErrorMessage =
'Third-party cookies are blocked in incognito and cannot be re-allowed.'
function expect(expected, message) {
return chrome.test.callbackPass(function(value) {
chrome.test.assertEq(expected, value, message);
});
}
chrome.test.runTests([
function thirdPartyCookiesAllowedTrueIncognito() {
pw.thirdPartyCookiesAllowed.set(
{'value': true, 'scope': 'incognito_persistent'},
chrome.test.callbackFail(
thirdPartyCookiesAllowedIncognitoErrorMessage, () => {
pw.thirdPartyCookiesAllowed.get(
{'incognito': true},
expect(
{
value: false,
incognitoSpecific: false,
levelOfControl: 'controllable_by_this_extension'
},
'third-party cookies should be blocked in incognito'));
}));
},
function thirdPartyCookiesAllowedFalseIncognito() {
pw.thirdPartyCookiesAllowed.set(
{'value': false, 'scope': 'incognito_persistent'}, function() {
pw.thirdPartyCookiesAllowed.get(
{'incognito': true},
expect(
{
value: false,
incognitoSpecific: true,
levelOfControl: 'controlled_by_this_extension'
},
'third-party cookies should be blocked in incognito'));
});
}
]);

@ -461,6 +461,10 @@ EXTENSIONS_EXPORT bool IsPreinstalledAppId(std::string_view app_id);
inline constexpr char kPolicyBlockedScripting[] =
"This page cannot be scripted due to an ExtensionsSettings policy.";
// Error message when extension tries to allow 3PCs in incognito.
inline constexpr char kCookiesAllowedIncognitoErrorMessage[] =
"Third-party cookies are blocked in incognito and cannot be re-allowed.";
// Error message when access to incognito preferences is denied.
inline constexpr char kIncognitoErrorMessage[] =
"You do not have permission to access incognito preferences.";