1 // Copyright 2022 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.
5 #if !defined(BUILD_CHROME)
6 #include <span> // std::size.
9 #include "base/containers/contains.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/browser/extensions/pref_mapping.h"
12 #include "chrome/browser/extensions/pref_transformer_interface.h"
13 #include "chrome/browser/prefetch/pref_names.h"
14 #include "chrome/browser/preloading/preloading_prefs.h"
15 #include "components/autofill/core/common/autofill_prefs.h"
16 #include "components/content_settings/core/common/pref_names.h"
17 #include "components/embedder_support/pref_names.h"
18 #include "components/password_manager/core/common/password_manager_pref_names.h"
19 #include "components/privacy_sandbox/privacy_sandbox_prefs.h"
20 #include "components/privacy_sandbox/tracking_protection_prefs.h"
21 #include "components/proxy_config/proxy_config_pref_names.h"
22 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
23 #include "components/spellcheck/browser/pref_names.h"
24 #include "components/translate/core/browser/translate_pref_names.h"
25 #include "third_party/abseil-cpp/absl/types/optional.h"
27 #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
28 #include "chrome/browser/chromeos/extensions/controlled_pref_mapping.h"
31 #if BUILDFLAG(IS_CHROMEOS_LACROS)
32 #include "base/containers/fixed_flat_map.h"
35 using extensions::mojom::APIPermissionID;
37 namespace extensions {
41 constexpr char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange";
43 const PrefMappingEntry kMappings[] = {
44 {"alternateErrorPagesEnabled",
45 embedder_support::kAlternateErrorPagesEnabled, APIPermissionID::kPrivacy,
46 APIPermissionID::kPrivacy},
47 {"autofillEnabled", autofill::prefs::kAutofillEnabledDeprecated,
48 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
49 {"autofillAddressEnabled", autofill::prefs::kAutofillProfileEnabled,
50 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
51 {"autofillCreditCardEnabled", autofill::prefs::kAutofillCreditCardEnabled,
52 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
53 {"hyperlinkAuditingEnabled", prefs::kEnableHyperlinkAuditing,
54 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
55 {"networkPredictionEnabled", prefetch::prefs::kNetworkPredictionOptions,
56 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
57 {"passwordSavingEnabled",
58 password_manager::prefs::kCredentialsEnableService,
59 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
61 // Note in Lacros this is Ash-controlled.
62 {"protectedContentEnabled", prefs::kProtectedContentDefault,
63 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
65 {"proxy", proxy_config::prefs::kProxy, APIPermissionID::kProxy,
66 APIPermissionID::kProxy},
67 {"referrersEnabled", prefs::kEnableReferrers, APIPermissionID::kPrivacy,
68 APIPermissionID::kPrivacy},
69 {"doNotTrackEnabled", prefs::kEnableDoNotTrack, APIPermissionID::kPrivacy,
70 APIPermissionID::kPrivacy},
71 {"safeBrowsingEnabled", prefs::kSafeBrowsingEnabled,
72 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
73 {"safeBrowsingExtendedReportingEnabled",
74 prefs::kSafeBrowsingScoutReportingEnabled, APIPermissionID::kPrivacy,
75 APIPermissionID::kPrivacy},
76 {"searchSuggestEnabled", prefs::kSearchSuggestEnabled,
77 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
78 {"spellingServiceEnabled", spellcheck::prefs::kSpellCheckUseSpellingService,
79 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
80 {"thirdPartyCookiesAllowed", prefs::kCookieControlsMode,
81 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
82 {"topicsEnabled", prefs::kPrivacySandboxM1TopicsEnabled,
83 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
84 {"fledgeEnabled", prefs::kPrivacySandboxM1FledgeEnabled,
85 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
86 {"adMeasurementEnabled", prefs::kPrivacySandboxM1AdMeasurementEnabled,
87 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
88 {"translationServiceEnabled", translate::prefs::kOfferTranslateEnabled,
89 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
90 {"webRTCIPHandlingPolicy", prefs::kWebRTCIPHandlingPolicy,
91 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
92 {"webRTCUDPPortRange", prefs::kWebRTCUDPPortRange,
93 APIPermissionID::kPrivacy, APIPermissionID::kPrivacy},
94 // accessibilityFeatures.animationPolicy is available for
95 // all platforms but the others from accessibilityFeatures
96 // is only available for OS_CHROMEOS.
97 {"animationPolicy", prefs::kAnimationPolicy,
98 APIPermissionID::kAccessibilityFeaturesRead,
99 APIPermissionID::kAccessibilityFeaturesModify},
100 // Below is the list of extension-controlled preferences where the underlying
101 // feature being controlled exists in ash. They should be kept in sync/in order.
102 // If a new extension-controlled pref of this type is added, it should be added
104 #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
105 {"autoclick", chromeos::prefs::kAccessibilityAutoclickEnabled,
106 APIPermissionID::kAccessibilityFeaturesRead,
107 APIPermissionID::kAccessibilityFeaturesModify},
108 {"caretHighlight", chromeos::prefs::kAccessibilityCaretHighlightEnabled,
109 APIPermissionID::kAccessibilityFeaturesRead,
110 APIPermissionID::kAccessibilityFeaturesModify},
111 {"cursorColor", chromeos::prefs::kAccessibilityCursorColorEnabled,
112 APIPermissionID::kAccessibilityFeaturesRead,
113 APIPermissionID::kAccessibilityFeaturesModify},
114 {"cursorHighlight", chromeos::prefs::kAccessibilityCursorHighlightEnabled,
115 APIPermissionID::kAccessibilityFeaturesRead,
116 APIPermissionID::kAccessibilityFeaturesModify},
117 {"dictation", chromeos::prefs::kAccessibilityDictationEnabled,
118 APIPermissionID::kAccessibilityFeaturesRead,
119 APIPermissionID::kAccessibilityFeaturesModify},
120 {"dockedMagnifier", chromeos::prefs::kDockedMagnifierEnabled,
121 APIPermissionID::kAccessibilityFeaturesRead,
122 APIPermissionID::kAccessibilityFeaturesModify},
123 {"focusHighlight", chromeos::prefs::kAccessibilityFocusHighlightEnabled,
124 APIPermissionID::kAccessibilityFeaturesRead,
125 APIPermissionID::kAccessibilityFeaturesModify},
126 {"highContrast", chromeos::prefs::kAccessibilityHighContrastEnabled,
127 APIPermissionID::kAccessibilityFeaturesRead,
128 APIPermissionID::kAccessibilityFeaturesModify},
129 {"largeCursor", chromeos::prefs::kAccessibilityLargeCursorEnabled,
130 APIPermissionID::kAccessibilityFeaturesRead,
131 APIPermissionID::kAccessibilityFeaturesModify},
132 {"screenMagnifier", chromeos::prefs::kAccessibilityScreenMagnifierEnabled,
133 APIPermissionID::kAccessibilityFeaturesRead,
134 APIPermissionID::kAccessibilityFeaturesModify},
135 {"selectToSpeak", chromeos::prefs::kAccessibilitySelectToSpeakEnabled,
136 APIPermissionID::kAccessibilityFeaturesRead,
137 APIPermissionID::kAccessibilityFeaturesModify},
138 {"spokenFeedback", chromeos::prefs::kAccessibilitySpokenFeedbackEnabled,
139 APIPermissionID::kAccessibilityFeaturesRead,
140 APIPermissionID::kAccessibilityFeaturesModify},
141 {"stickyKeys", chromeos::prefs::kAccessibilityStickyKeysEnabled,
142 APIPermissionID::kAccessibilityFeaturesRead,
143 APIPermissionID::kAccessibilityFeaturesModify},
144 {"switchAccess", chromeos::prefs::kAccessibilitySwitchAccessEnabled,
145 APIPermissionID::kAccessibilityFeaturesRead,
146 APIPermissionID::kAccessibilityFeaturesModify},
147 {"virtualKeyboard", chromeos::prefs::kAccessibilityVirtualKeyboardEnabled,
148 APIPermissionID::kAccessibilityFeaturesRead,
149 APIPermissionID::kAccessibilityFeaturesModify},
153 class IdentityPrefTransformer : public PrefTransformerInterface {
155 absl::optional<base::Value> ExtensionToBrowserPref(
156 const base::Value& extension_pref,
158 bool& bad_message) override {
159 return extension_pref.Clone();
162 absl::optional<base::Value> BrowserToExtensionPref(
163 const base::Value& browser_pref,
164 bool is_incognito_profile) override {
165 return browser_pref.Clone();
172 PrefMapping* PrefMapping::GetInstance() {
173 return base::Singleton<PrefMapping>::get();
177 base::span<const PrefMappingEntry> PrefMapping::GetMappings() {
181 bool PrefMapping::FindBrowserPrefForExtensionPref(
182 const std::string& extension_pref,
183 std::string* browser_pref,
184 APIPermissionID* read_permission,
185 APIPermissionID* write_permission) const {
186 auto it = mapping_.find(extension_pref);
187 if (it == mapping_.end())
189 *browser_pref = it->second.pref_name;
190 *read_permission = it->second.read_permission;
191 *write_permission = it->second.write_permission;
195 bool PrefMapping::FindEventForBrowserPref(const std::string& browser_pref,
196 std::string* event_name,
197 APIPermissionID* permission) const {
198 auto it = event_mapping_.find(browser_pref);
199 if (it == event_mapping_.end())
201 *event_name = it->second.pref_name;
202 *permission = it->second.read_permission;
206 PrefTransformerInterface* PrefMapping::FindTransformerForBrowserPref(
207 const std::string& browser_pref) const {
208 auto it = transformers_.find(browser_pref);
209 if (it != transformers_.end())
210 return it->second.get();
211 return identity_transformer_.get();
214 #if BUILDFLAG(IS_CHROMEOS_LACROS)
215 // Given a pref name for an extension-controlled pref where the underlying
216 // pref is controlled by ash, returns the PrefPath used by the crosapi to set
217 // the pref in ash, or nullptr if no pref exists.
218 crosapi::mojom::PrefPath PrefMapping::GetPrefPathForPrefName(
219 const std::string& pref_name) const {
220 static const auto name_to_extension_prefpath = base::MakeFixedFlatMap<
221 base::StringPiece, crosapi::mojom::PrefPath>(
222 {{chromeos::prefs::kDockedMagnifierEnabled,
223 crosapi::mojom::PrefPath::kDockedMagnifierEnabled},
224 {chromeos::prefs::kAccessibilityAutoclickEnabled,
225 crosapi::mojom::PrefPath::kAccessibilityAutoclickEnabled},
226 {chromeos::prefs::kAccessibilityCaretHighlightEnabled,
227 crosapi::mojom::PrefPath::kAccessibilityCaretHighlightEnabled},
228 {chromeos::prefs::kAccessibilityCursorColorEnabled,
229 crosapi::mojom::PrefPath::kAccessibilityCursorColorEnabled},
230 {chromeos::prefs::kAccessibilityCursorHighlightEnabled,
231 crosapi::mojom::PrefPath::kAccessibilityCursorHighlightEnabled},
232 {chromeos::prefs::kAccessibilityDictationEnabled,
233 crosapi::mojom::PrefPath::kAccessibilityDictationEnabled},
234 {chromeos::prefs::kAccessibilityFocusHighlightEnabled,
235 crosapi::mojom::PrefPath::kAccessibilityFocusHighlightEnabled},
236 {chromeos::prefs::kAccessibilityHighContrastEnabled,
237 crosapi::mojom::PrefPath::kAccessibilityHighContrastEnabled},
238 {chromeos::prefs::kAccessibilityLargeCursorEnabled,
239 crosapi::mojom::PrefPath::kAccessibilityLargeCursorEnabled},
240 {chromeos::prefs::kAccessibilityScreenMagnifierEnabled,
241 crosapi::mojom::PrefPath::kAccessibilityScreenMagnifierEnabled},
242 {chromeos::prefs::kAccessibilitySelectToSpeakEnabled,
243 crosapi::mojom::PrefPath::kAccessibilitySelectToSpeakEnabled},
244 {chromeos::prefs::kAccessibilitySpokenFeedbackEnabled,
245 crosapi::mojom::PrefPath::kExtensionAccessibilitySpokenFeedbackEnabled},
246 {chromeos::prefs::kAccessibilityStickyKeysEnabled,
247 crosapi::mojom::PrefPath::kAccessibilityStickyKeysEnabled},
248 {chromeos::prefs::kAccessibilitySwitchAccessEnabled,
249 crosapi::mojom::PrefPath::kAccessibilitySwitchAccessEnabled},
250 {chromeos::prefs::kAccessibilityVirtualKeyboardEnabled,
251 crosapi::mojom::PrefPath::kAccessibilityVirtualKeyboardEnabled},
252 {prefs::kProtectedContentDefault,
253 crosapi::mojom::PrefPath::kProtectedContentDefault},
254 {proxy_config::prefs::kProxy, crosapi::mojom::PrefPath::kProxy}});
255 auto* pref_iter = name_to_extension_prefpath.find(pref_name);
256 return pref_iter == name_to_extension_prefpath.end()
257 ? crosapi::mojom::PrefPath::kUnknown
260 #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
262 PrefMapping::PrefMapping() {
263 identity_transformer_ = std::make_unique<IdentityPrefTransformer>();
264 for (const auto& pref : kMappings) {
265 mapping_[pref.extension_pref] = PrefMapData(
266 pref.browser_pref, pref.read_permission, pref.write_permission);
267 std::string event_name =
268 base::StringPrintf(kOnPrefChangeFormat, pref.extension_pref);
269 event_mapping_[pref.browser_pref] =
270 PrefMapData(event_name, pref.read_permission, pref.write_permission);
272 DCHECK_EQ(std::size(kMappings), mapping_.size());
273 DCHECK_EQ(std::size(kMappings), event_mapping_.size());
276 PrefMapping::~PrefMapping() = default;
278 void PrefMapping::RegisterPrefTransformer(
279 const std::string& browser_pref,
280 std::unique_ptr<PrefTransformerInterface> transformer) {
281 DCHECK(!base::Contains(transformers_, browser_pref))
282 << "Trying to register pref transformer for " << browser_pref << " twice";
283 transformers_[browser_pref] = std::move(transformer);
286 } // namespace extensions