• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package org.chromium.base.shared_preferences;
6 
7 import com.google.common.collect.Sets;
8 
9 import org.chromium.base.ResettersForTesting;
10 import org.chromium.build.BuildConfig;
11 import org.chromium.build.annotations.CheckDiscard;
12 
13 import java.util.ArrayList;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Set;
17 
18 /**
19  * Ensures that all {@link PreferenceKeyRegistry}s used are known.
20  *
21  * A complement to ChromePreferenceKeysTest, which ensures that preference keys across all known
22  * registries are unique.
23  *
24  * This checking is done in tests in which |initializeKnownRegistries()| is called, which happens
25  * during browser process initialization.
26  */
27 @CheckDiscard("Preference key checking should only happen on build with asserts")
28 public class KnownPreferenceKeyRegistries {
29     private static Set<PreferenceKeyRegistry> sKnownRegistries;
30     private static Set<PreferenceKeyRegistry> sRegistriesUsedBeforeInitialization = new HashSet<>();
31 
onRegistryUsed(PreferenceKeyRegistry registry)32     public static void onRegistryUsed(PreferenceKeyRegistry registry) {
33         if (!BuildConfig.ENABLE_ASSERTS) {
34             return;
35         }
36 
37         if (sKnownRegistries == null) {
38             // Before initialization, keep track of registries used.
39             sRegistriesUsedBeforeInitialization.add(registry);
40         } else {
41             // After initialization, check if registry is known.
42             if (!sKnownRegistries.contains(registry)) {
43                 String message =
44                         "An unknown registry was used, PreferenceKeyRegistries must be declared as "
45                                 + "known in AllPreferenceKeyRegistries: "
46                                 + String.join(",", registry.toDebugString());
47                 assert false : message;
48             }
49         }
50     }
51 
initializeKnownRegistries(Set<PreferenceKeyRegistry> knownRegistries)52     public static void initializeKnownRegistries(Set<PreferenceKeyRegistry> knownRegistries) {
53         if (!BuildConfig.ENABLE_ASSERTS) {
54             return;
55         }
56 
57         if (sKnownRegistries != null) {
58             // Double initialization; make sure new known registries are the same.
59             assert sKnownRegistries.equals(knownRegistries);
60             return;
61         }
62 
63         // Check that each registry already used is known; assert otherwise.
64         Set<PreferenceKeyRegistry> unknownRegistries =
65                 Sets.difference(sRegistriesUsedBeforeInitialization, knownRegistries);
66         if (!unknownRegistries.isEmpty()) {
67             List<String> unknownRegistryNames = new ArrayList<>();
68             for (PreferenceKeyRegistry unknownRegistry : unknownRegistries) {
69                 unknownRegistryNames.add(unknownRegistry.toDebugString());
70             }
71             String message =
72                     "Unknown registries were used, PreferenceKeyRegistries must be declared as "
73                             + "known in AllPreferenceKeyRegistries: "
74                             + String.join(",", unknownRegistryNames);
75             assert false : message;
76         }
77 
78         sKnownRegistries = knownRegistries;
79         sRegistriesUsedBeforeInitialization = null;
80     }
81 
clearForTesting()82     static void clearForTesting() {
83         Set<PreferenceKeyRegistry> previousKnownRegistries = sKnownRegistries;
84         Set<PreferenceKeyRegistry> registriesUsedBeforeInitialization =
85                 sRegistriesUsedBeforeInitialization;
86 
87         ResettersForTesting.register(
88                 () -> {
89                     sKnownRegistries = previousKnownRegistries;
90                     sRegistriesUsedBeforeInitialization = registriesUsedBeforeInitialization;
91                 });
92         sKnownRegistries = null;
93         sRegistriesUsedBeforeInitialization = new HashSet<>();
94     }
95 }
96