File: theme_service.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (395 lines) | stat: -rw-r--r-- 15,067 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_THEMES_THEME_SERVICE_H_
#define CHROME_BROWSER_THEMES_THEME_SERVICE_H_

#include <memory>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/themes/theme_helper.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension_id.h"
#include "ui/base/mojom/themes.mojom.h"
#include "ui/base/theme_provider.h"
#include "ui/color/system_theme.h"

class BrowserThemePack;
class CustomThemeSupplier;
class Profile;
class ThemeServiceObserver;
class ThemeSyncableService;

namespace extensions {
class Extension;
}  // namespace extensions

namespace theme_service_internal {
class ThemeServiceTest;
}  // namespace theme_service_internal

namespace ui {
class ColorProvider;
}  // namespace ui

class BrowserThemeProviderDelegate {
 public:
  virtual CustomThemeSupplier* GetThemeSupplier() const = 0;
  virtual bool ShouldUseCustomFrame() const = 0;
};

// A theme consists of a set of colors and images, including the NTP background
// image. See CustomThemeSupplier for details. There are multiple sources for
// themes, including extensions, NTP, the system theme, and policy.
// TODO(https://crbug.com/341787825): When the NTP generates a custom background
// image, the color is stored in ThemeService but the background image is stored
// in NtpCustomBackgroundService. This divergence from other theme sources
// introduces complexity and fragility.
class ThemeService : public KeyedService, public BrowserThemeProviderDelegate {
 public:
  // This is stored as an integer in the profile prefs, so entries should not be
  // renumbered and numeric values should never be reused.
  enum class BrowserColorScheme {
    kSystem = 0,
    kLight = 1,
    kDark = 2,
  };

  // This class keeps track of the number of existing |ThemeReinstaller|
  // objects. When that number reaches 0 then unused themes will be deleted.
  class ThemeReinstaller {
   public:
    ThemeReinstaller(Profile* profile, base::OnceClosure installer);
    ThemeReinstaller(const ThemeReinstaller&) = delete;
    ThemeReinstaller& operator=(const ThemeReinstaller&) = delete;
    ~ThemeReinstaller();

    void Reinstall();

   private:
    base::OnceClosure installer_;
    const raw_ptr<ThemeService> theme_service_;
  };

  // Constant ID to use for all autogenerated themes.
  static const char kAutogeneratedThemeID[];
  // Constant ID to use for all user color themes.
  static const char kUserColorThemeID[];

  // Creates a ThemeProvider with a custom theme supplier specified via
  // |delegate|. The return value must not outlive |profile|'s ThemeService.
  static std::unique_ptr<ui::ThemeProvider> CreateBoundThemeProvider(
      Profile* profile,
      BrowserThemeProviderDelegate* delegate);

  ThemeService(Profile* profile, const ThemeHelper& theme_helper);
  ThemeService(const ThemeService&) = delete;
  ThemeService& operator=(const ThemeService&) = delete;
  ~ThemeService() override;

  void Init();

  // KeyedService:
  void Shutdown() override;

  // Overridden from BrowserThemeProviderDelegate:
  CustomThemeSupplier* GetThemeSupplier() const override;
  bool ShouldUseCustomFrame() const override;

  // Set the current theme to the theme defined in |extension|.
  // |extension| must already be added to this profile's
  // ExtensionService.
  void SetTheme(const extensions::Extension* extension);

  // Similar to SetTheme, but doesn't show an undo infobar.
  void RevertToExtensionTheme(const std::string& extension_id);

  // Sets the platform theme based on `system_theme`.
  virtual void UseTheme(ui::SystemTheme system_theme);

  // Reset the theme to default.
  virtual void UseDefaultTheme();

  // Toggle whether the browser follows its own theme or from the OS. For now,
  // this is distinct from the ui::SystemTheme.
  virtual void UseDeviceTheme(bool follow);

  // Returns true if the browser should follow the OS theme.
  virtual bool UsingDeviceTheme() const;

  // Set the current theme to the system theme. On some platforms, the system
  // theme is the default theme.
  virtual void UseSystemTheme();

  // Returns true if the default theme and system theme are not the same on
  // this platform.
  virtual bool IsSystemThemeDistinctFromDefaultTheme() const;

  // Forwards to ThemeProviderBase::IsDefaultTheme().
  // Virtual for testing.
  virtual bool UsingDefaultTheme() const;

  // Whether we are using the system theme. On Linux, the system theme is the
  // GTK or QT themes, not the "Classic" theme.
  virtual bool UsingSystemTheme() const;

  // Forwards to ThemeProviderBase::IsExtensionTheme().
  // Virtual for testing.
  virtual bool UsingExtensionTheme() const;

  // Forwards to ThemeProviderBase::IsAutogeneratedTheme().
  // Virtual for testing.
  virtual bool UsingAutogeneratedTheme() const;

  // Whether current theme colors are enforced through a policy.
  // Virtual for testing.
  virtual bool UsingPolicyTheme() const;

  // Gets the id of the last installed theme. (The theme may have been further
  // locally customized.)
  virtual std::string GetThemeID() const;

  // Uninstall theme extensions which are no longer in use.
  void RemoveUnusedThemes();

  // Returns the syncable service for syncing theme. The returned service is
  // owned by |this| object.
  virtual ThemeSyncableService* GetThemeSyncableService() const;

  // Gets the ThemeProvider for |profile|. This will be different for an
  // incognito profile and its original profile, even though both profiles use
  // the same ThemeService.
  //
  // Before using this function, consider if the caller is in a rooted UI tree.
  // If it is, strongly favor referring to the conceptual roots for a
  // ThemeProvider. For Views, this is the Widget. For Cocoa, this is the
  // AppControl.
  static const ui::ThemeProvider& GetThemeProviderForProfile(Profile* profile);
  static CustomThemeSupplier* GetThemeSupplierForProfile(Profile* profile);

  // Gets the ColorProvider for this ThemeService.
  //
  // Before using this function, consider if the caller is in a rooted UI tree.
  // If it is, strongly favor referring to the conceptual roots for a
  // ColorProvider. For Views, this is the Widget. For Cocoa, this is the
  // AppControl.
  ui::ColorProvider* GetColorProvider();

  // Builds an autogenerated theme from a given |color| and applies it.
  virtual void BuildAutogeneratedThemeFromColor(SkColor color);

  // Builds an autogenerated theme from a given |color| and applies it.
  virtual void BuildAutogeneratedThemeFromColor(SkColor color,
                                                bool store_in_prefs);

  // Returns the theme color for an autogenerated theme.
  virtual SkColor GetAutogeneratedThemeColor() const;

  // Builds an autogenerated theme from the applied policy color and applies it.
  virtual void BuildAutogeneratedPolicyTheme();

  // Returns the theme color for the current policy theme.
  virtual SkColor GetPolicyThemeColor() const;

  // Sets the browser color scheme preference.
  virtual void SetBrowserColorScheme(BrowserColorScheme color_scheme);

  // Gets the browser color scheme preference.
  virtual BrowserColorScheme GetBrowserColorScheme() const;

  // Sets/gets the browser user color preference.
  virtual void SetUserColor(std::optional<SkColor> user_color);
  virtual std::optional<SkColor> GetUserColor() const;

  // Sets/gets the browser kSchemeVariant preference.
  void SetBrowserColorVariant(ui::mojom::BrowserColorVariant color_variant);
  virtual ui::mojom::BrowserColorVariant GetBrowserColorVariant() const;

  // Convenience method that allows setting both the kUserColor and
  // kSchemeVariant before propagating theme update notifications.
  virtual void SetUserColorAndBrowserColorVariant(
      SkColor user_color,
      ui::mojom::BrowserColorVariant color_variant);

  // Sets/gets the browser grayscale theme preference.
  virtual void SetIsGrayscale(bool is_grayscale);
  virtual bool GetIsGrayscale() const;

  // Returns true if the current theme is the "baseline" blue theme.
  virtual bool GetIsBaseline() const;

  // Returns |ThemeService::ThemeReinstaller| for the current theme.
  std::unique_ptr<ThemeService::ThemeReinstaller>
  BuildReinstallerForCurrentTheme();

  // Virtual for testing.
  virtual void AddObserver(ThemeServiceObserver* observer);

  void RemoveObserver(ThemeServiceObserver* observer);

  const ThemeHelper& theme_helper_for_testing() const { return *theme_helper_; }

  // Don't create "Cached Theme.pak" in the extension directory, for testing.
  static void DisableThemePackForTesting();

  void ResetThemeSyncableServiceForTest();

 protected:
  // Set a custom default theme instead of the normal default theme.
  virtual void SetCustomDefaultTheme(
      scoped_refptr<CustomThemeSupplier> theme_supplier);

  // Returns the theme service type that should be used on startup.
  virtual ui::SystemTheme GetDefaultSystemTheme() const;

  // Clears override fields and saves the dictionary.
  virtual void ClearThemeData(bool clear_ntp_background);

  // Initialize current theme state data from preferences.
  virtual void InitFromPrefs();

  // Let all the browser views know that themes have changed.
  virtual void NotifyThemeChanged();

  // If there is an inconsistency in preferences, change preferences to a
  // consistent state.
  virtual void FixInconsistentPreferencesIfNeeded();

  Profile* profile() const { return profile_; }

  void set_ready() { ready_ = true; }

  // True if the theme service is ready to be used.
  // TODO(pkotwicz): Add DCHECKS to the theme service's getters once
  // ThemeSource no longer uses the ThemeService when it is not ready.
  bool ready_ = false;

 private:
  // This class implements ui::ThemeProvider on behalf of ThemeHelper and
  // keeps track of the incognito state and CustemThemeSupplier for the calling
  // code.
  class BrowserThemeProvider : public ui::ThemeProvider {
   public:
    BrowserThemeProvider(const ThemeHelper& theme_helper,
                         bool incognito,
                         const BrowserThemeProviderDelegate* delegate);
    BrowserThemeProvider(const BrowserThemeProvider&) = delete;
    BrowserThemeProvider& operator=(const BrowserThemeProvider&) = delete;
    ~BrowserThemeProvider() override;

    // Overridden from ui::ThemeProvider:
    gfx::ImageSkia* GetImageSkiaNamed(int id) const override;
    color_utils::HSL GetTint(int original_id) const override;
    int GetDisplayProperty(int id) const override;
    bool ShouldUseNativeFrame() const override;
    bool HasCustomImage(int id) const override;
    base::RefCountedMemory* GetRawData(
        int id,
        ui::ResourceScaleFactor scale_factor) const override;

   private:
    CustomThemeSupplier* GetThemeSupplier() const;

    const raw_ref<const ThemeHelper> theme_helper_;
    bool incognito_;
    raw_ptr<const BrowserThemeProviderDelegate> delegate_;
  };
  friend class BrowserThemeProvider;
  friend class theme_service_internal::ThemeServiceTest;

  // virtual for testing.
  virtual void DoSetTheme(const extensions::Extension* extension,
                          bool suppress_infobar);

  // Called when the extension service is ready.
  void OnExtensionServiceReady();

  // Migrate the theme to the new theme pack schema by recreating the data pack
  // from the extension.
  void MigrateTheme();

  // Replaces the current theme supplier with a new one and calls
  // StopUsingTheme() or StartUsingTheme() as appropriate.
  void SwapThemeSupplier(scoped_refptr<CustomThemeSupplier> theme_supplier);

  // Implementation of SetTheme() (and the fallback from InitFromPrefs() in
  // case we don't have a theme pack). |new_theme| indicates whether this is a
  // newly installed theme or a migration.
  void BuildFromExtension(const extensions::Extension* extension,
                          bool new_theme);

  // Callback when |pack| has finished or failed building.
  void OnThemeBuiltFromExtension(const extensions::ExtensionId& extension_id,
                                 scoped_refptr<BrowserThemePack> pack,
                                 bool new_theme);

  // Handles theme color policy pref updates. if policy value contains valid
  // color(s), sets browser theme accordingly.
  void HandlePolicyColorUpdate();

  // Functions that modify theme prefs.
  void ClearThemePrefs();
  void SetThemePrefsForExtension(const extensions::Extension* extension);
  void SetThemePrefsForColor(SkColor color);

  bool DisableExtension(const std::string& extension_id);

  raw_ptr<Profile> profile_;
  PrefChangeRegistrar pref_change_registrar_;

  const raw_ref<const ThemeHelper> theme_helper_;
  scoped_refptr<CustomThemeSupplier> theme_supplier_;

  // The id of the theme extension which has just been installed but has not
  // been loaded yet. The theme extension with |installed_pending_load_id_| may
  // never be loaded if the install is due to updating a disabled theme.
  // |pending_install_id_| should be set to |kDefaultThemeID| if there are no
  // recently installed theme extensions
  std::string installed_pending_load_id_ = ThemeHelper::kDefaultThemeID;

  // The number of infobars currently displayed.
  int number_of_reinstallers_ = 0;

  // Configuring ThemeService into a desired theme state may involve the
  // configuration of multiple theme prefs. However updating a single theme pref
  // may result in requests to propagate theme update notifications. This flag
  // is used to avoid propagating updates until all theme prefs have been set
  // to their desired values.
  bool should_suppress_theme_updates_ = false;

  // Declared before |theme_syncable_service_|, because ThemeSyncableService
  // removes itself from the |observers_| list on destruction.
  base::ObserverList<ThemeServiceObserver> observers_;

  std::unique_ptr<ThemeSyncableService> theme_syncable_service_;

#if BUILDFLAG(ENABLE_EXTENSIONS)
  class ThemeObserver;
  std::unique_ptr<ThemeObserver> theme_observer_;
#endif

  BrowserThemeProvider original_theme_provider_;
  BrowserThemeProvider incognito_theme_provider_;

  // Allows us to cancel building a theme pack from an extension.
  base::CancelableTaskTracker build_extension_task_tracker_;

  // The ID of the theme that's currently being built on a different thread.
  // We hold onto this just to be sure not to uninstall the extension view
  // RemoveUnusedThemes while it's still being built.
  std::string building_extension_id_;

  base::WeakPtrFactory<ThemeService> weak_ptr_factory_{this};
};

#endif  // CHROME_BROWSER_THEMES_THEME_SERVICE_H_