Skip to content

Commit cfa336a

Browse files
Filipa SenraChromium LUCI CQ
Filipa Senra
authored and
Chromium LUCI CQ
committed
[M111][Privacy Sandbox] Support compatibility privacySandboxEnabled API
The existing privacySandboxEnabled Chrome Extension API is being depreciated in favour of three new k-APIs - topicsEnabled, fledgeEnabled and adMeasurementEnabled in M111. This CL enables the existing privacySandboxEnabled API to be respected and compatible with the new k-APIs during the migration period. If an extension has disabled the privacySandboxEnabled API, then the new k-APIs must also be disabled. If an extension clears the privacySandboxEnabled API, then the new k-APIs are also cleared. See a screen recording of an extension disabling the privacySandbox API: http://dr/file/d/1MoLhOVmmh4bqW18lkdDctQRmsTo-Hjdy/view Test extension for Privacy Sandbox Extension APIs used: http://dr/file/d/1Wlk3TzECpU7j_23H9UUZxUdSY2UDTMQc/view Experiment #privacy-sandbox-settings-4 was enabled. (cherry picked from commit 5fc51e7) Bug: 1378703, b/254414152 Change-Id: Id5e711149e85ceb84217e2b59d6b2ebaffef8997 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4133664 Commit-Queue: Filipa Senra <fsenra@google.com> Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org> Cr-Original-Commit-Position: refs/heads/main@{#1097899} Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4202368 Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Cr-Commit-Position: refs/branch-heads/5563@{#44} Cr-Branched-From: 3ac59a6-refs/heads/main@{#1097615}
1 parent e8eea85 commit cfa336a

File tree

6 files changed

+330
-9
lines changed

6 files changed

+330
-9
lines changed

chrome/browser/extensions/api/preference/preference_api.cc

+40
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,33 @@ ExtensionFunction::ResponseAction SetPreferenceFunction::Run() {
866866
BuildPrivacySandboxDeprecationInspectorIssueInfo(source_url()));
867867
}
868868

869+
// Clear the new Privacy Sandbox APIs if an extension sets to true the
870+
// deprecated pref |kPrivacySandboxApisEnabled| and set to false the new
871+
// Privacy Sandbox APIs if an extension sets to false the deprecated pref
872+
// |kPrivacySandboxApisEnabled| in order to maintain backward compatibility
873+
// during the migration period.
874+
// TODO(b/263568309): Remove this once the deprecated API is retired.
875+
if (prefs::kPrivacySandboxApisEnabled == browser_pref) {
876+
if (browser_pref_value->GetBool()) {
877+
prefs_helper->RemoveExtensionControlledPref(
878+
extension_id(), prefs::kPrivacySandboxM1TopicsEnabled, scope);
879+
prefs_helper->RemoveExtensionControlledPref(
880+
extension_id(), prefs::kPrivacySandboxM1FledgeEnabled, scope);
881+
prefs_helper->RemoveExtensionControlledPref(
882+
extension_id(), prefs::kPrivacySandboxM1AdMeasurementEnabled, scope);
883+
} else {
884+
prefs_helper->SetExtensionControlledPref(
885+
extension_id(), prefs::kPrivacySandboxM1TopicsEnabled, scope,
886+
base::Value(false));
887+
prefs_helper->SetExtensionControlledPref(
888+
extension_id(), prefs::kPrivacySandboxM1FledgeEnabled, scope,
889+
base::Value(false));
890+
prefs_helper->SetExtensionControlledPref(
891+
extension_id(), prefs::kPrivacySandboxM1AdMeasurementEnabled, scope,
892+
base::Value(false));
893+
}
894+
}
895+
869896
prefs_helper->SetExtensionControlledPref(extension_id(), browser_pref, scope,
870897
browser_pref_value->Clone());
871898
#if BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -961,6 +988,19 @@ ExtensionFunction::ResponseAction ClearPreferenceFunction::Run() {
961988
BuildPrivacySandboxDeprecationInspectorIssueInfo(source_url()));
962989
}
963990

991+
// Clear the new Privacy Sandbox APIs if an extension clears the deprecated
992+
// pref |kPrivacySandboxApisEnabled| in order to maintain backward
993+
// compatibility during the migration period.
994+
// TODO(b/263568309): Remove this once the deprecated API is retired.
995+
if (prefs::kPrivacySandboxApisEnabled == browser_pref) {
996+
prefs_helper->RemoveExtensionControlledPref(
997+
extension_id(), prefs::kPrivacySandboxM1TopicsEnabled, scope);
998+
prefs_helper->RemoveExtensionControlledPref(
999+
extension_id(), prefs::kPrivacySandboxM1FledgeEnabled, scope);
1000+
prefs_helper->RemoveExtensionControlledPref(
1001+
extension_id(), prefs::kPrivacySandboxM1AdMeasurementEnabled, scope);
1002+
}
1003+
9641004
// Whenever an extension clears the |kSafeBrowsingEnabled| preference,
9651005
// it must also clear |kSafeBrowsingEnhanced|. See crbug.com/1064722 for
9661006
// more background.

chrome/browser/extensions/api/preference/preference_apitest.cc

+160
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,51 @@ class ExtensionPreferenceApiTest
136136
/* expected_controlled */ false);
137137
}
138138

139+
void CheckPrivacySandboxPreferencesDisabled() {
140+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxApisEnabled,
141+
base::Value(false),
142+
/* expected_controlled */ true);
143+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxM1TopicsEnabled,
144+
base::Value(false),
145+
/* expected_controlled */ true);
146+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxM1FledgeEnabled,
147+
base::Value(false),
148+
/* expected_controlled */ true);
149+
VerifyPrefValueAndControlledState(
150+
prefs::kPrivacySandboxM1AdMeasurementEnabled, base::Value(false),
151+
/* expected_controlled */ true);
152+
}
153+
154+
void CheckPrivacySandboxPreferencesEnabled() {
155+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxApisEnabled,
156+
base::Value(true),
157+
/* expected_controlled */ true);
158+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxM1TopicsEnabled,
159+
base::Value(true),
160+
/* expected_controlled */ false);
161+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxM1FledgeEnabled,
162+
base::Value(true),
163+
/* expected_controlled */ false);
164+
VerifyPrefValueAndControlledState(
165+
prefs::kPrivacySandboxM1AdMeasurementEnabled, base::Value(true),
166+
/* expected_controlled */ false);
167+
}
168+
169+
void CheckPrivacySandboxPreferencesCleared() {
170+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxApisEnabled,
171+
base::Value(true),
172+
/* expected_controlled */ false);
173+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxM1TopicsEnabled,
174+
base::Value(true),
175+
/* expected_controlled */ false);
176+
VerifyPrefValueAndControlledState(prefs::kPrivacySandboxM1FledgeEnabled,
177+
base::Value(true),
178+
/* expected_controlled */ false);
179+
VerifyPrefValueAndControlledState(
180+
prefs::kPrivacySandboxM1AdMeasurementEnabled, base::Value(true),
181+
/* expected_controlled */ false);
182+
}
183+
139184
// Verifies whether the boolean |preference| has the |expected_value| and is
140185
// |expected_controlled| by an extension.
141186

@@ -630,6 +675,121 @@ IN_PROC_BROWSER_TEST_P(ExtensionPreferenceApiTest, ThirdPartyCookiesAllowed) {
630675
/* expected_controlled */ false);
631676
}
632677

678+
// Tests the behavior of the PrivacySandboxEnabled API during the migration
679+
// period.
680+
// The preferences |kPrivacySandboxM1Topics|, |kPrivacySandboxM1Fledge| and
681+
// |kPrivacySandboxM1AdMeasurement| should be enforced to kOff if
682+
// |kPrivacySandboxApisEnabled| is set to false by an extension.
683+
// They should also be cleared if |kPrivacySandboxApisEnabled| is cleared.
684+
// This check is not done in the Standard test so we can test if the granular
685+
// Privacy Sandbox APIs are turned off, when |kPrivacySandboxApisEnabled| is
686+
// turned off, in isolation of controlling them directly.
687+
// Disabled due to flakes on multiple platforms; see https://crbug.com/1410736.
688+
IN_PROC_BROWSER_TEST_F(ExtensionPreferenceApiTest,
689+
DISABLED_PrivacySandboxMigration) {
690+
PrefService* prefs = profile_->GetPrefs();
691+
prefs->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, true);
692+
prefs->SetBoolean(prefs::kPrivacySandboxM1FledgeEnabled, true);
693+
prefs->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, true);
694+
695+
base::FilePath extension_path =
696+
test_data_dir_.AppendASCII("preference/privacy_sandbox_migration");
697+
698+
// STEP 1. Install extension and set the pref |kPrivacySandboxApisEnabled| to
699+
// false.
700+
// The preferences for PrivacySandbox, Topics, Fledge and AdMeasurement should
701+
// all be disabled.
702+
{
703+
extensions::ResultCatcher catcher;
704+
ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply);
705+
EXPECT_TRUE(LoadExtension(extension_path)) << message_;
706+
EXPECT_TRUE(listener.WaitUntilSatisfied());
707+
// Run the tests.
708+
listener.Reply("run set to false test");
709+
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
710+
}
711+
CheckPrivacySandboxPreferencesDisabled();
712+
713+
// STEP 2. Reload extension.
714+
// The preferences should not be reset when the extension is reloaded.
715+
{
716+
ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply);
717+
ReloadExtension(last_loaded_extension_id());
718+
EXPECT_TRUE(listener.WaitUntilSatisfied());
719+
listener.Reply("");
720+
}
721+
CheckPrivacySandboxPreferencesDisabled();
722+
723+
// STEP 4. Enable the pref |kPrivacySandboxApisEnabled|.
724+
// The preference PrivacySandbox should be enabled but the preferences Topics,
725+
// Fledge and AdMeasurement should all be cleared and on their default values.
726+
{
727+
extensions::ResultCatcher catcher;
728+
ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply);
729+
ReloadExtension(last_loaded_extension_id());
730+
EXPECT_TRUE(listener.WaitUntilSatisfied());
731+
// Run the tests.
732+
listener.Reply("run set to true test");
733+
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
734+
}
735+
CheckPrivacySandboxPreferencesEnabled();
736+
737+
// STEP 5. Redo Step 1.
738+
// So we can see a meaningful change on Step 6.
739+
{
740+
extensions::ResultCatcher catcher;
741+
ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply);
742+
ReloadExtension(last_loaded_extension_id());
743+
EXPECT_TRUE(listener.WaitUntilSatisfied());
744+
listener.Reply("run set to false test");
745+
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
746+
}
747+
CheckPrivacySandboxPreferencesDisabled();
748+
749+
// STEP 6. Clear the pref |kPrivacySandboxApisEnabled|.
750+
// The preferences for PrivacySandbox, Topics, Fledge and AdMeasurement should
751+
// all be cleared and on their default values.
752+
{
753+
extensions::ResultCatcher catcher;
754+
ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply);
755+
ReloadExtension(last_loaded_extension_id());
756+
EXPECT_TRUE(listener.WaitUntilSatisfied());
757+
// Run the tests.
758+
listener.Reply("run clear test");
759+
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
760+
}
761+
CheckPrivacySandboxPreferencesCleared();
762+
763+
// STEP 7. Redo Step 1.
764+
// So we can see a meaningful change on Step 8.
765+
{
766+
extensions::ResultCatcher catcher;
767+
ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply);
768+
ReloadExtension(last_loaded_extension_id());
769+
EXPECT_TRUE(listener.WaitUntilSatisfied());
770+
listener.Reply("run set to false test");
771+
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
772+
}
773+
CheckPrivacySandboxPreferencesDisabled();
774+
775+
// STEP 8. Uninstall and install the extension (without running the test
776+
// that calls the extension API)
777+
// Uninstalling and installing should clear the preferences.
778+
extensions::TestExtensionRegistryObserver observer(
779+
extensions::ExtensionRegistry::Get(profile_), last_loaded_extension_id());
780+
UninstallExtension(last_loaded_extension_id());
781+
observer.WaitForExtensionUninstalled();
782+
CheckPrivacySandboxPreferencesCleared();
783+
784+
{
785+
ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply);
786+
EXPECT_TRUE(LoadExtension(extension_path));
787+
EXPECT_TRUE(listener.WaitUntilSatisfied());
788+
listener.Reply("");
789+
}
790+
CheckPrivacySandboxPreferencesCleared();
791+
}
792+
633793
namespace extensions {
634794

635795
class ExtensionPrefDevToolsIssueTest

chrome/common/extensions/api/privacy.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
"$ref": "types.ChromeSetting",
105105
"value": ["privacySandboxEnabled", {"type": "boolean"}],
106106
"deprecated": "We’re deprecating the API <code><a href='#property-websites-privacySandboxEnabled'>chrome.privacy.websites.privacySandboxEnabled</a></code>, though it will remain active for backward compatibility until release M113. Instead, please use <code><a href='#property-websites-topicsEnabled'>chrome.privacy.websites.topicsEnabled</a></code>, <code><a href='#property-websites-fledgeEnabled'>chrome.privacy.websites.fledgeEnabled</a></code> and <code><a href='#property-websites-adMeasurementEnabled'>chrome.privacy.websites.adMeasurementEnabled</a></code>.",
107-
"description": "If enabled, the experimental <a href=https://www.chromium.org/Home/chromium-privacy/privacy-sandbox>Privacy Sandbox</a> features are active. The value of this preference is of type boolean, and the default value is <code>true</code>. PLEASE NOTE: The schema of this API may change in the future as the Privacy Sandbox features crystallize. In that case, we will provide prior notice."
107+
"description": "If enabled, the experimental <a href='https://www.chromium.org/Home/chromium-privacy/privacy-sandbox'>Privacy Sandbox</a> features are active. The value of this preference is of type boolean, and the default value is <code>true</code>."
108108
},
109109
"topicsEnabled": {
110110
"$ref": "types.ChromeSetting",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name" : "Preferences API Test Extension for Privacy Sandbox Migration",
3+
"version" : "0.1",
4+
"manifest_version": 2,
5+
"description" : "Preferences API Test Extension for Privacy Sandbox Migration",
6+
"permissions": [ "privacy" ],
7+
"background": {
8+
"scripts": ["test.js"],
9+
"persistent": false
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2023 The Chromium Authors
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// Privacy Sandbox Migration API test
6+
// Run with browser_tests
7+
// --gtest_filter=ExtensionPreferenceApiTest.PrivacySandboxMigration
8+
9+
var privacyWebsitesNamespace = chrome.privacy.websites;
10+
11+
function expect(expected, message) {
12+
return chrome.test.callbackPass(function(value) {
13+
chrome.test.assertEq(expected, value, message);
14+
});
15+
}
16+
17+
// Verifies that the preference has the expected default value.
18+
function expectDefault(prefName, defaultValue) {
19+
return expect(
20+
{value: defaultValue, levelOfControl: 'controllable_by_this_extension'},
21+
'`' + prefName + '` is expected to be the default, which is ' +
22+
defaultValue);
23+
}
24+
25+
// Verifies that the preference is properly controlled by the extension.
26+
function expectControlled(prefName, newValue) {
27+
return expect(
28+
{
29+
value: newValue,
30+
levelOfControl: 'controlled_by_this_extension',
31+
},
32+
'`' + prefName + '` is expected to be controlled by this extension');
33+
}
34+
35+
function setToFalsePref() {
36+
chrome.test.getConfig(function(config) {
37+
chrome.test.runTests([
38+
// Setting the deprecated pref to false |kPrivacySandboxApisEnabled|
39+
// should also set to false the new Privacy Sandbox APIs in order to
40+
// maintain backward compatibility during the migration period.
41+
function testSetToFalsePrivacyGuideEnabled() {
42+
privacyWebsitesNamespace.privacySandboxEnabled.set(
43+
{value: false}, function() {
44+
privacyWebsitesNamespace.topicsEnabled.get(
45+
{}, expectControlled('topicsEnabled', false));
46+
privacyWebsitesNamespace.fledgeEnabled.get(
47+
{}, expectControlled('fledgeEnabled', false));
48+
privacyWebsitesNamespace.adMeasurementEnabled.get(
49+
{}, expectControlled('adMeasurementEnabled', false));
50+
});
51+
},
52+
])
53+
})
54+
}
55+
56+
function setToTruePref() {
57+
chrome.test.getConfig(function(config) {
58+
chrome.test.runTests([
59+
// Setting the deprecated pref to true |kPrivacySandboxApisEnabled|
60+
// should clear the new Privacy Sandbox APIs in order to
61+
// maintain backward compatibility during the migration period.
62+
function testSetToTruePrivacyGuideEnabled() {
63+
privacyWebsitesNamespace.privacySandboxEnabled.set(
64+
{value: true}, function() {
65+
privacyWebsitesNamespace.topicsEnabled.get(
66+
{}, expectDefault('topicsEnabled', true));
67+
privacyWebsitesNamespace.fledgeEnabled.get(
68+
{}, expectDefault('fledgeEnabled', true));
69+
privacyWebsitesNamespace.adMeasurementEnabled.get(
70+
{}, expectDefault('adMeasurementEnabled', true));
71+
});
72+
},
73+
])
74+
})
75+
}
76+
77+
function clearPref() {
78+
chrome.test.getConfig(function(config) {
79+
chrome.test.runTests([
80+
// Clearing the deprecated pref|kPrivacySandboxApisEnabled|
81+
// should also clear the new k-APIs in order to maintain backward
82+
// compatibility during the migration period.
83+
function testClearPrivacyGuideEnabled() {
84+
privacyWebsitesNamespace.privacySandboxEnabled.clear({}, function() {
85+
privacyWebsitesNamespace.topicsEnabled.get(
86+
{}, expectDefault('topicsEnabled', true));
87+
privacyWebsitesNamespace.fledgeEnabled.get(
88+
{}, expectDefault('fledgeEnabled', true));
89+
privacyWebsitesNamespace.adMeasurementEnabled.get(
90+
{}, expectDefault('adMeasurementEnabled', true));
91+
});
92+
},
93+
])
94+
})
95+
}
96+
97+
chrome.test.sendMessage('ready', function(message) {
98+
if (message == 'run set to false test') {
99+
setToFalsePref();
100+
} else if (message == 'run set to true test') {
101+
setToTruePref();
102+
} else if (message == 'run clear test') {
103+
clearPref();
104+
}
105+
});

chrome/test/data/extensions/api_test/preference/standard/test.js

+13-8
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,6 @@ chrome.test.sendMessage('ready', function(message) {
158158
}
159159
}
160160
},
161-
function setGlobals() {
162-
for (let preferenceSet of preferences_to_test) {
163-
for (let key in preferenceSet.preferences) {
164-
prefSetterOppositeOfDefault.call(
165-
preferenceSet.root, key, preferenceSet.preferences[key]);
166-
}
167-
}
168-
},
169161
// For Privacy Sandbox APIs unable to enable a pref.
170162
function setToEnableExpectErrorDefault() {
171163
for (let preferenceSet of
@@ -196,6 +188,19 @@ chrome.test.sendMessage('ready', function(message) {
196188
}
197189
}
198190
},
191+
// setGlobals() after setToEnableExpectErrorAndControlled(), so disabling
192+
// privacySandboxEnabled doesn't trigger topicsEnabled, fledgeEnabled and
193+
// adsMeasurementEnabled to false
194+
// TODO(b/263568309): Move this method after getPreferences() after the
195+
// deprecated API privacySandboxEnabled is retired.
196+
function setGlobals() {
197+
for (let preferenceSet of preferences_to_test) {
198+
for (let key in preferenceSet.preferences) {
199+
prefSetterOppositeOfDefault.call(
200+
preferenceSet.root, key, preferenceSet.preferences[key]);
201+
}
202+
}
203+
},
199204
// Set the WebRTCIPHhandlingPolicy and verify it in the get function.
200205
function testWebRTCIPHandlingPolicy() {
201206
if (pn.webRTCIPHandlingPolicy == undefined) {

0 commit comments

Comments
 (0)