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 <set> 10 #include <string> 11 #include <utility> 12 13 #include "base/compiler_specific.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/threading/non_thread_safe.h" 18 #include "components/browser_context_keyed_service/browser_context_keyed_service.h" 19 #include "content/public/browser/notification_observer.h" 20 #include "content/public/browser/notification_registrar.h" 21 #include "ui/base/theme_provider.h" 22 23 class CustomThemeSupplier; 24 class BrowserThemePack; 25 class ThemeSyncableService; 26 class Profile; 27 28 namespace base { 29 class FilePath; 30 } 31 32 namespace color_utils { 33 struct HSL; 34 } 35 36 namespace extensions { 37 class Extension; 38 } 39 40 namespace gfx { 41 class Image; 42 } 43 44 namespace theme_service_internal { 45 class ThemeServiceTest; 46 } 47 48 namespace ui { 49 class ResourceBundle; 50 } 51 52 #ifdef __OBJC__ 53 @class NSString; 54 // Sent whenever the browser theme changes. Object => NSValue wrapping the 55 // ThemeService that changed. 56 extern "C" NSString* const kBrowserThemeDidChangeNotification; 57 #endif // __OBJC__ 58 59 class ThemeService : public base::NonThreadSafe, 60 public content::NotificationObserver, 61 public BrowserContextKeyedService, 62 public ui::ThemeProvider { 63 public: 64 // Public constants used in ThemeService and its subclasses: 65 static const char* kDefaultThemeID; 66 67 ThemeService(); 68 virtual ~ThemeService(); 69 70 virtual void Init(Profile* profile); 71 72 // Returns a cross platform image for an id. 73 // 74 // TODO(erg): Make this part of the ui::ThemeProvider and the main way to get 75 // theme properties out of the theme provider since it's cross platform. 76 virtual gfx::Image GetImageNamed(int id) const; 77 78 // Overridden from ui::ThemeProvider: 79 virtual gfx::ImageSkia* GetImageSkiaNamed(int id) const OVERRIDE; 80 virtual SkColor GetColor(int id) const OVERRIDE; 81 virtual int GetDisplayProperty(int id) const OVERRIDE; 82 virtual bool ShouldUseNativeFrame() const OVERRIDE; 83 virtual bool HasCustomImage(int id) const OVERRIDE; 84 virtual base::RefCountedMemory* GetRawData( 85 int id, 86 ui::ScaleFactor scale_factor) const OVERRIDE; 87 #if defined(OS_MACOSX) 88 virtual NSImage* GetNSImageNamed(int id) const OVERRIDE; 89 virtual NSColor* GetNSImageColorNamed(int id) const OVERRIDE; 90 virtual NSColor* GetNSColor(int id) const OVERRIDE; 91 virtual NSColor* GetNSColorTint(int id) const OVERRIDE; 92 virtual NSGradient* GetNSGradient(int id) const OVERRIDE; 93 #elif defined(OS_POSIX) && !defined(TOOLKIT_VIEWS) && !defined(OS_ANDROID) 94 // This mismatch between what this class defines and whether or not it 95 // overrides ui::ThemeProvider is http://crbug.com/105040 . 96 // GdkPixbufs returned by GetPixbufNamed and GetRTLEnabledPixbufNamed are 97 // shared instances owned by the theme provider and should not be freed. 98 virtual GdkPixbuf* GetRTLEnabledPixbufNamed(int id) const OVERRIDE; 99 #endif 100 101 // Overridden from content::NotificationObserver: 102 virtual void Observe(int type, 103 const content::NotificationSource& source, 104 const content::NotificationDetails& details) OVERRIDE; 105 106 // Set the current theme to the theme defined in |extension|. 107 // |extension| must already be added to this profile's 108 // ExtensionService. 109 virtual void SetTheme(const extensions::Extension* extension); 110 111 // Reset the theme to default. 112 virtual void UseDefaultTheme(); 113 114 // Set the current theme to the native theme. On some platforms, the native 115 // theme is the default theme. 116 virtual void SetNativeTheme(); 117 118 // Whether we're using the chrome default theme. Virtual so linux can check 119 // if we're using the GTK theme. 120 virtual bool UsingDefaultTheme() const; 121 122 // Whether we're using the native theme (which may or may not be the 123 // same as the default theme). 124 virtual bool UsingNativeTheme() const; 125 126 // Gets the id of the last installed theme. (The theme may have been further 127 // locally customized.) 128 virtual std::string GetThemeID() const; 129 130 // This class needs to keep track of the number of theme infobars so that we 131 // clean up unused themes. 132 void OnInfobarDisplayed(); 133 134 // Decrements the number of theme infobars. If the last infobar has been 135 // destroyed, uninstalls all themes that aren't the currently selected. 136 void OnInfobarDestroyed(); 137 138 // Uninstall theme extensions which are no longer in use. |ignore_infobars| is 139 // whether unused themes should be removed despite a theme infobar being 140 // visible. 141 void RemoveUnusedThemes(bool ignore_infobars); 142 143 // Returns the syncable service for syncing theme. The returned service is 144 // owned by |this| object. 145 virtual ThemeSyncableService* GetThemeSyncableService() const; 146 147 // Save the images to be written to disk, mapping file path to id. 148 typedef std::map<base::FilePath, int> ImagesDiskCache; 149 150 protected: 151 // Set a custom default theme instead of the normal default theme. 152 virtual void SetCustomDefaultTheme( 153 scoped_refptr<CustomThemeSupplier> theme_supplier); 154 155 // Returns true if the ThemeService should use the native theme on startup. 156 virtual bool ShouldInitWithNativeTheme() const; 157 158 // Get the specified tint - |id| is one of the TINT_* enum values. 159 color_utils::HSL GetTint(int id) const; 160 161 // Clears all the override fields and saves the dictionary. 162 virtual void ClearAllThemeData(); 163 164 // Load theme data from preferences. 165 virtual void LoadThemePrefs(); 166 167 // Let all the browser views know that themes have changed. 168 virtual void NotifyThemeChanged(); 169 170 #if defined(OS_MACOSX) 171 // Let all the browser views know that themes have changed in a platform way. 172 virtual void NotifyPlatformThemeChanged(); 173 #endif // OS_MACOSX 174 175 // Clears the platform-specific caches. Do not call directly; it's called 176 // from ClearAllThemeData(). 177 virtual void FreePlatformCaches(); 178 179 Profile* profile() const { return profile_; } 180 181 void set_ready() { ready_ = true; } 182 183 const CustomThemeSupplier* get_theme_supplier() const { 184 return theme_supplier_.get(); 185 } 186 187 // True if the theme service is ready to be used. 188 // TODO(pkotwicz): Add DCHECKS to the theme service's getters once 189 // ThemeSource no longer uses the ThemeService when it is not ready. 190 bool ready_; 191 192 private: 193 friend class theme_service_internal::ThemeServiceTest; 194 195 // Called when the extension service is ready. 196 void OnExtensionServiceReady(); 197 198 // Migrate the theme to the new theme pack schema by recreating the data pack 199 // from the extension. 200 void MigrateTheme(); 201 202 // Replaces the current theme supplier with a new one and calls 203 // StopUsingTheme() or StartUsingTheme() as appropriate. 204 void SwapThemeSupplier(scoped_refptr<CustomThemeSupplier> theme_supplier); 205 206 // Saves the filename of the cached theme pack. 207 void SavePackName(const base::FilePath& pack_path); 208 209 // Save the id of the last theme installed. 210 void SaveThemeID(const std::string& id); 211 212 // Implementation of SetTheme() (and the fallback from LoadThemePrefs() in 213 // case we don't have a theme pack). 214 void BuildFromExtension(const extensions::Extension* extension); 215 216 // Returns true if the profile belongs to a managed user. 217 bool IsManagedUser() const; 218 219 // Sets the current theme to the managed user theme. Should only be used for 220 // managed user profiles. 221 void SetManagedUserTheme(); 222 223 // Sets the managed user theme if the user has no custom theme yet. 224 void OnManagedUserInitialized(); 225 226 #if defined(TOOLKIT_GTK) 227 // Loads an image and flips it horizontally if |rtl_enabled| is true. 228 GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled) const; 229 #endif 230 231 #if defined(TOOLKIT_GTK) 232 typedef std::map<int, GdkPixbuf*> GdkPixbufMap; 233 mutable GdkPixbufMap gdk_pixbufs_; 234 #elif defined(OS_MACOSX) 235 // |nsimage_cache_| retains the images it has cached. 236 typedef std::map<int, NSImage*> NSImageMap; 237 mutable NSImageMap nsimage_cache_; 238 239 // |nscolor_cache_| retains the colors it has cached. 240 typedef std::map<int, NSColor*> NSColorMap; 241 mutable NSColorMap nscolor_cache_; 242 243 typedef std::map<int, NSGradient*> NSGradientMap; 244 mutable NSGradientMap nsgradient_cache_; 245 #endif 246 247 ui::ResourceBundle& rb_; 248 Profile* profile_; 249 250 scoped_refptr<CustomThemeSupplier> theme_supplier_; 251 252 // The id of the theme extension which has just been installed but has not 253 // been loaded yet. The theme extension with |installed_pending_load_id_| may 254 // never be loaded if the install is due to updating a disabled theme. 255 // |pending_install_id_| should be set to |kDefaultThemeID| if there are no 256 // recently installed theme extensions 257 std::string installed_pending_load_id_; 258 259 // The number of infobars currently displayed. 260 int number_of_infobars_; 261 262 content::NotificationRegistrar registrar_; 263 264 scoped_ptr<ThemeSyncableService> theme_syncable_service_; 265 266 base::WeakPtrFactory<ThemeService> weak_ptr_factory_; 267 268 DISALLOW_COPY_AND_ASSIGN(ThemeService); 269 }; 270 271 #endif // CHROME_BROWSER_THEMES_THEME_SERVICE_H_ 272