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_
|