1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_THEMES_THEME_SERVICE_H_ 6 #define CHROME_BROWSER_THEMES_THEME_SERVICE_H_ 7 8 #include <map> 9 #include <memory> 10 #include <string> 11 12 #include "base/compiler_specific.h" 13 #include "base/macros.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/scoped_observer.h" 17 #include "base/task/cancelable_task_tracker.h" 18 #include "chrome/browser/themes/theme_helper.h" 19 #include "chrome/common/buildflags.h" 20 #include "components/keyed_service/core/keyed_service.h" 21 #include "extensions/buildflags/buildflags.h" 22 #include "extensions/common/extension_id.h" 23 #include "ui/base/theme_provider.h" 24 #include "ui/native_theme/native_theme.h" 25 #include "ui/native_theme/native_theme_observer.h" 26 27 class BrowserThemePack; 28 class CustomThemeSupplier; 29 class ThemeSyncableService; 30 class Profile; 31 32 namespace extensions { 33 class Extension; 34 } 35 36 namespace theme_service_internal { 37 class ThemeServiceTest; 38 } 39 40 class BrowserThemeProviderDelegate { 41 public: 42 virtual const CustomThemeSupplier* GetThemeSupplier() const = 0; 43 }; 44 45 class ThemeService : public KeyedService, 46 public ui::NativeThemeObserver, 47 public BrowserThemeProviderDelegate { 48 public: 49 // This class keeps track of the number of existing |ThemeReinstaller| 50 // objects. When that number reaches 0 then unused themes will be deleted. 51 class ThemeReinstaller { 52 public: 53 ThemeReinstaller(Profile* profile, base::OnceClosure installer); 54 ~ThemeReinstaller(); 55 56 void Reinstall(); 57 58 private: 59 base::OnceClosure installer_; 60 ThemeService* const theme_service_; 61 62 DISALLOW_COPY_AND_ASSIGN(ThemeReinstaller); 63 }; 64 65 // Constant ID to use for all autogenerated themes. 66 static const char kAutogeneratedThemeID[]; 67 68 // Creates a ThemeProvider with a custom theme supplier specified via 69 // |delegate|. The return value must not outlive |profile|'s ThemeService. 70 static std::unique_ptr<ui::ThemeProvider> CreateBoundThemeProvider( 71 Profile* profile, 72 BrowserThemeProviderDelegate* delegate); 73 74 explicit ThemeService(Profile* profile, const ThemeHelper& theme_helper); 75 ~ThemeService() override; 76 77 void Init(); 78 79 // KeyedService: 80 void Shutdown() override; 81 82 // Overridden from ui::NativeThemeObserver: 83 void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override; 84 85 // Overridden from BrowserThemeProviderDelegate: 86 const CustomThemeSupplier* GetThemeSupplier() const override; 87 88 // Set the current theme to the theme defined in |extension|. 89 // |extension| must already be added to this profile's 90 // ExtensionService. 91 void SetTheme(const extensions::Extension* extension); 92 93 // Similar to SetTheme, but doesn't show an undo infobar. 94 void RevertToExtensionTheme(const std::string& extension_id); 95 96 // Reset the theme to default. 97 virtual void UseDefaultTheme(); 98 99 // Set the current theme to the system theme. On some platforms, the system 100 // theme is the default theme. 101 virtual void UseSystemTheme(); 102 103 // Returns true if the default theme and system theme are not the same on 104 // this platform. 105 virtual bool IsSystemThemeDistinctFromDefaultTheme() const; 106 107 // Forwards to ThemeProviderBase::IsDefaultTheme(). 108 // Virtual for testing. 109 virtual bool UsingDefaultTheme() const; 110 111 // Whether we are using the system theme. On GTK, the system theme is the GTK 112 // theme, not the "Classic" theme. 113 virtual bool UsingSystemTheme() const; 114 115 // Forwards to ThemeProviderBase::IsExtensionTheme(). 116 // Virtual for testing. 117 virtual bool UsingExtensionTheme() const; 118 119 // Forwards to ThemeProviderBase::IsAutogeneratedTheme(). 120 // Virtual for testing. 121 virtual bool UsingAutogeneratedTheme() const; 122 123 // Gets the id of the last installed theme. (The theme may have been further 124 // locally customized.) 125 virtual std::string GetThemeID() const; 126 127 // Uninstall theme extensions which are no longer in use. 128 void RemoveUnusedThemes(); 129 130 // Returns the syncable service for syncing theme. The returned service is 131 // owned by |this| object. 132 virtual ThemeSyncableService* GetThemeSyncableService() const; 133 134 // Gets the ThemeProvider for |profile|. This will be different for an 135 // incognito profile and its original profile, even though both profiles use 136 // the same ThemeService. 137 static const ui::ThemeProvider& GetThemeProviderForProfile(Profile* profile); 138 139 // Builds an autogenerated theme from a given |color| and applies it. 140 virtual void BuildAutogeneratedThemeFromColor(SkColor color); 141 142 // Returns the theme color for an autogenerated theme. 143 virtual SkColor GetAutogeneratedThemeColor() const; 144 145 // Returns |ThemeService::ThemeReinstaller| for the current theme. 146 std::unique_ptr<ThemeService::ThemeReinstaller> 147 BuildReinstallerForCurrentTheme(); 148 theme_helper_for_testing()149 const ThemeHelper& theme_helper_for_testing() const { return theme_helper_; } 150 151 // Don't create "Cached Theme.pak" in the extension directory, for testing. 152 static void DisableThemePackForTesting(); 153 154 protected: 155 // Set a custom default theme instead of the normal default theme. 156 virtual void SetCustomDefaultTheme( 157 scoped_refptr<CustomThemeSupplier> theme_supplier); 158 159 // Returns true if the ThemeService should use the system theme on startup. 160 virtual bool ShouldInitWithSystemTheme() const; 161 162 // Clears all the override fields and saves the dictionary. 163 virtual void ClearAllThemeData(); 164 165 // Initialize current theme state data from preferences. 166 virtual void InitFromPrefs(); 167 168 // Let all the browser views know that themes have changed. 169 virtual void NotifyThemeChanged(); 170 171 // If there is an inconsistency in preferences, change preferences to a 172 // consistent state. 173 virtual void FixInconsistentPreferencesIfNeeded(); 174 profile()175 Profile* profile() const { return profile_; } 176 set_ready()177 void set_ready() { ready_ = true; } 178 179 // True if the theme service is ready to be used. 180 // TODO(pkotwicz): Add DCHECKS to the theme service's getters once 181 // ThemeSource no longer uses the ThemeService when it is not ready. 182 bool ready_ = false; 183 184 private: 185 // This class implements ui::ThemeProvider on behalf of ThemeHelper and 186 // keeps track of the incognito state and CustemThemeSupplier for the calling 187 // code. 188 class BrowserThemeProvider : public ui::ThemeProvider { 189 public: 190 BrowserThemeProvider(const ThemeHelper& theme_helper, 191 bool incognito, 192 const BrowserThemeProviderDelegate* delegate); 193 ~BrowserThemeProvider() override; 194 195 // Overridden from ui::ThemeProvider: 196 gfx::ImageSkia* GetImageSkiaNamed(int id) const override; 197 SkColor GetColor(int original_id) const override; 198 color_utils::HSL GetTint(int original_id) const override; 199 int GetDisplayProperty(int id) const override; 200 bool ShouldUseNativeFrame() const override; 201 bool HasCustomImage(int id) const override; 202 bool HasCustomColor(int id) const override; 203 base::RefCountedMemory* GetRawData(int id, ui::ScaleFactor scale_factor) 204 const override; 205 206 private: 207 const CustomThemeSupplier* GetThemeSupplier() const; 208 209 const ThemeHelper& theme_helper_; 210 bool incognito_; 211 const BrowserThemeProviderDelegate* delegate_; 212 213 DISALLOW_COPY_AND_ASSIGN(BrowserThemeProvider); 214 }; 215 friend class BrowserThemeProvider; 216 friend class theme_service_internal::ThemeServiceTest; 217 218 // virtual for testing. 219 virtual void DoSetTheme(const extensions::Extension* extension, 220 bool suppress_infobar); 221 222 223 // Called when the extension service is ready. 224 void OnExtensionServiceReady(); 225 226 // Migrate the theme to the new theme pack schema by recreating the data pack 227 // from the extension. 228 void MigrateTheme(); 229 230 // Replaces the current theme supplier with a new one and calls 231 // StopUsingTheme() or StartUsingTheme() as appropriate. 232 void SwapThemeSupplier(scoped_refptr<CustomThemeSupplier> theme_supplier); 233 234 // Implementation of SetTheme() (and the fallback from InitFromPrefs() in 235 // case we don't have a theme pack). |new_theme| indicates whether this is a 236 // newly installed theme or a migration. 237 void BuildFromExtension(const extensions::Extension* extension, 238 bool new_theme); 239 240 // Callback when |pack| has finished or failed building. 241 void OnThemeBuiltFromExtension(const extensions::ExtensionId& extension_id, 242 scoped_refptr<BrowserThemePack> pack, 243 bool new_theme); 244 245 #if BUILDFLAG(ENABLE_SUPERVISED_USERS) 246 // Returns true if the profile belongs to a supervised user. 247 bool IsSupervisedUser() const; 248 249 // Sets the current theme to the supervised user theme. Should only be used 250 // for supervised user profiles. 251 void SetSupervisedUserTheme(); 252 #endif 253 254 // Functions that modify theme prefs. 255 void ClearThemePrefs(); 256 void SetThemePrefsForExtension(const extensions::Extension* extension); 257 void SetThemePrefsForColor(SkColor color); 258 259 bool DisableExtension(const std::string& extension_id); 260 261 Profile* profile_; 262 263 const ThemeHelper& theme_helper_; 264 scoped_refptr<CustomThemeSupplier> theme_supplier_; 265 266 // The id of the theme extension which has just been installed but has not 267 // been loaded yet. The theme extension with |installed_pending_load_id_| may 268 // never be loaded if the install is due to updating a disabled theme. 269 // |pending_install_id_| should be set to |kDefaultThemeID| if there are no 270 // recently installed theme extensions 271 std::string installed_pending_load_id_ = ThemeHelper::kDefaultThemeID; 272 273 // The number of infobars currently displayed. 274 int number_of_reinstallers_ = 0; 275 276 std::unique_ptr<ThemeSyncableService> theme_syncable_service_; 277 278 #if BUILDFLAG(ENABLE_EXTENSIONS) 279 class ThemeObserver; 280 std::unique_ptr<ThemeObserver> theme_observer_; 281 #endif 282 283 BrowserThemeProvider original_theme_provider_; 284 BrowserThemeProvider incognito_theme_provider_; 285 286 // Allows us to cancel building a theme pack from an extension. 287 base::CancelableTaskTracker build_extension_task_tracker_; 288 289 // The ID of the theme that's currently being built on a different thread. 290 // We hold onto this just to be sure not to uninstall the extension view 291 // RemoveUnusedThemes while it's still being built. 292 std::string building_extension_id_; 293 294 ScopedObserver<ui::NativeTheme, ui::NativeThemeObserver> 295 native_theme_observer_{this}; 296 297 base::WeakPtrFactory<ThemeService> weak_ptr_factory_{this}; 298 299 DISALLOW_COPY_AND_ASSIGN(ThemeService); 300 }; 301 302 #endif // CHROME_BROWSER_THEMES_THEME_SERVICE_H_ 303