1// Copyright (c) 2011 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#pragma once
8
9#include <map>
10#include <set>
11#include <string>
12
13#include "base/memory/ref_counted.h"
14#include "base/threading/non_thread_safe.h"
15#include "chrome/browser/profiles/profile_keyed_service.h"
16#include "content/common/notification_observer.h"
17#include "content/common/notification_registrar.h"
18#include "ui/base/theme_provider.h"
19
20class BrowserThemePack;
21class ThemeServiceTest;
22class Extension;
23class FilePath;
24class Profile;
25
26namespace color_utils {
27struct HSL;
28}
29
30namespace ui {
31class ResourceBundle;
32}
33using ui::ResourceBundle;
34
35#ifdef __OBJC__
36@class NSString;
37// Sent whenever the browser theme changes.  Object => NSValue wrapping the
38// ThemeService that changed.
39extern "C" NSString* const kBrowserThemeDidChangeNotification;
40#endif  // __OBJC__
41
42class ThemeService : public base::NonThreadSafe,
43                     public NotificationObserver,
44                     public ProfileKeyedService,
45                     public ui::ThemeProvider {
46 public:
47  // Public constants used in ThemeService and its subclasses:
48
49  // Strings used in alignment properties.
50  static const char* kAlignmentTop;
51  static const char* kAlignmentBottom;
52  static const char* kAlignmentLeft;
53  static const char* kAlignmentRight;
54
55  // Strings used in tiling properties.
56  static const char* kTilingNoRepeat;
57  static const char* kTilingRepeatX;
58  static const char* kTilingRepeatY;
59  static const char* kTilingRepeat;
60
61  static const char* kDefaultThemeID;
62
63  // Returns true if the image is themeable.  Safe to call on any thread.
64  static bool IsThemeableImage(int resource_id);
65
66  ThemeService();
67  virtual ~ThemeService();
68
69  enum {
70    COLOR_FRAME,
71    COLOR_FRAME_INACTIVE,
72    COLOR_FRAME_INCOGNITO,
73    COLOR_FRAME_INCOGNITO_INACTIVE,
74    COLOR_TOOLBAR,
75    COLOR_TAB_TEXT,
76    COLOR_BACKGROUND_TAB_TEXT,
77    COLOR_BOOKMARK_TEXT,
78    COLOR_NTP_BACKGROUND,
79    COLOR_NTP_TEXT,
80    COLOR_NTP_LINK,
81    COLOR_NTP_LINK_UNDERLINE,
82    COLOR_NTP_HEADER,
83    COLOR_NTP_SECTION,
84    COLOR_NTP_SECTION_TEXT,
85    COLOR_NTP_SECTION_LINK,
86    COLOR_NTP_SECTION_LINK_UNDERLINE,
87    COLOR_CONTROL_BACKGROUND,
88    COLOR_BUTTON_BACKGROUND,
89
90    // These colors don't have constant default values. They are derived from
91    // the runtime value of other colors.
92    COLOR_NTP_SECTION_HEADER_TEXT,
93    COLOR_NTP_SECTION_HEADER_TEXT_HOVER,
94    COLOR_NTP_SECTION_HEADER_RULE,
95    COLOR_NTP_SECTION_HEADER_RULE_LIGHT,
96    COLOR_NTP_TEXT_LIGHT,
97
98    TINT_BUTTONS,
99    TINT_FRAME,
100    TINT_FRAME_INACTIVE,
101    TINT_FRAME_INCOGNITO,
102    TINT_FRAME_INCOGNITO_INACTIVE,
103    TINT_BACKGROUND_TAB,
104    NTP_BACKGROUND_ALIGNMENT,
105    NTP_BACKGROUND_TILING,
106    NTP_LOGO_ALTERNATE
107#if defined(OS_MACOSX)
108    ,
109    COLOR_TOOLBAR_BEZEL = 1000,
110    COLOR_TOOLBAR_STROKE,
111    COLOR_TOOLBAR_STROKE_INACTIVE,
112    COLOR_TOOLBAR_BUTTON_STROKE,
113    COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE,
114    GRADIENT_FRAME_INCOGNITO,
115    GRADIENT_FRAME_INCOGNITO_INACTIVE,
116    GRADIENT_TOOLBAR,
117    GRADIENT_TOOLBAR_INACTIVE,
118    GRADIENT_TOOLBAR_BUTTON,
119    GRADIENT_TOOLBAR_BUTTON_INACTIVE,
120    GRADIENT_TOOLBAR_BUTTON_PRESSED,
121    GRADIENT_TOOLBAR_BUTTON_PRESSED_INACTIVE
122#endif  // OS_MACOSX
123  };
124
125  // A bitfield mask for alignments.
126  typedef enum {
127    ALIGN_CENTER = 0x0,
128    ALIGN_LEFT = 0x1,
129    ALIGN_TOP = 0x2,
130    ALIGN_RIGHT = 0x4,
131    ALIGN_BOTTOM = 0x8,
132  } AlignmentMasks;
133
134  // Background tiling choices.
135  typedef enum {
136    NO_REPEAT = 0,
137    REPEAT_X = 1,
138    REPEAT_Y = 2,
139    REPEAT = 3
140  } Tiling;
141
142  // ui::ThemeProvider implementation.
143  virtual void Init(Profile* profile);
144  virtual SkBitmap* GetBitmapNamed(int id) const;
145  virtual SkColor GetColor(int id) const;
146  virtual bool GetDisplayProperty(int id, int* result) const;
147  virtual bool ShouldUseNativeFrame() const;
148  virtual bool HasCustomImage(int id) const;
149  virtual RefCountedMemory* GetRawData(int id) const;
150#if defined(TOOLKIT_USES_GTK)
151  // GdkPixbufs returned by GetPixbufNamed and GetRTLEnabledPixbufNamed are
152  // shared instances owned by the theme provider and should not be freed.
153  virtual GdkPixbuf* GetPixbufNamed(int id) const;
154  virtual GdkPixbuf* GetRTLEnabledPixbufNamed(int id) const;
155#elif defined(OS_MACOSX)
156  virtual NSImage* GetNSImageNamed(int id, bool allow_default) const;
157  virtual NSColor* GetNSImageColorNamed(int id, bool allow_default) const;
158  virtual NSColor* GetNSColor(int id, bool allow_default) const;
159  virtual NSColor* GetNSColorTint(int id, bool allow_default) const;
160  virtual NSGradient* GetNSGradient(int id) const;
161#endif
162
163  // Set the current theme to the theme defined in |extension|.
164  virtual void SetTheme(const Extension* extension);
165
166  // Reset the theme to default.
167  virtual void UseDefaultTheme();
168
169  // Set the current theme to the native theme. On some platforms, the native
170  // theme is the default theme.
171  virtual void SetNativeTheme();
172
173  // Whether we're using the chrome default theme. Virtual so linux can check
174  // if we're using the GTK theme.
175  virtual bool UsingDefaultTheme();
176
177  // Gets the id of the last installed theme. (The theme may have been further
178  // locally customized.)
179  virtual std::string GetThemeID() const;
180
181  // This class needs to keep track of the number of theme infobars so that we
182  // clean up unused themes.
183  void OnInfobarDisplayed();
184
185  // Decrements the number of theme infobars. If the last infobar has been
186  // destroyed, uninstalls all themes that aren't the currently selected.
187  void OnInfobarDestroyed();
188
189  // Convert a bitfield alignment into a string like "top left". Public so that
190  // it can be used to generate CSS values. Takes a bitfield of AlignmentMasks.
191  static std::string AlignmentToString(int alignment);
192
193  // Parse alignments from something like "top left" into a bitfield of
194  // AlignmentMasks
195  static int StringToAlignment(const std::string& alignment);
196
197  // Convert a tiling value into a string like "no-repeat". Public
198  // so that it can be used to generate CSS values. Takes a Tiling.
199  static std::string TilingToString(int tiling);
200
201  // Parse tiling values from something like "no-repeat" into a Tiling value.
202  static int StringToTiling(const std::string& tiling);
203
204  // Returns the default tint for the given tint |id| TINT_* enum value.
205  static color_utils::HSL GetDefaultTint(int id);
206
207  // Returns the default color for the given color |id| COLOR_* enum value.
208  static SkColor GetDefaultColor(int id);
209
210  // Returns true and sets |result| to the requested default property, if |id|
211  // is valid.
212  static bool GetDefaultDisplayProperty(int id, int* result);
213
214  // Returns the set of IDR_* resources that should be tinted.
215  static const std::set<int>& GetTintableToolbarButtons();
216
217  // Remove preference values for themes that are no longer in use.
218  void RemoveUnusedThemes();
219
220  // Save the images to be written to disk, mapping file path to id.
221  typedef std::map<FilePath, int> ImagesDiskCache;
222
223 protected:
224  // Get the specified tint - |id| is one of the TINT_* enum values.
225  color_utils::HSL GetTint(int id) const;
226
227  // Clears all the override fields and saves the dictionary.
228  virtual void ClearAllThemeData();
229
230  // Load theme data from preferences.
231  virtual void LoadThemePrefs();
232
233  // Let all the browser views know that themes have changed.
234  virtual void NotifyThemeChanged();
235
236#if defined(OS_MACOSX)
237  // Let all the browser views know that themes have changed in a platform way.
238  virtual void NotifyPlatformThemeChanged();
239#endif  // OS_MACOSX
240
241  // Clears the platform-specific caches. Do not call directly; it's called
242  // from ClearCaches().
243  virtual void FreePlatformCaches();
244
245  Profile* profile() { return profile_; }
246
247  // NotificationObserver:
248  virtual void Observe(NotificationType type,
249                       const NotificationSource& source,
250                       const NotificationDetails& details);
251
252 private:
253  friend class ThemeServiceTest;
254
255  // Saves the filename of the cached theme pack.
256  void SavePackName(const FilePath& pack_path);
257
258  // Save the id of the last theme installed.
259  void SaveThemeID(const std::string& id);
260
261  // Implementation of SetTheme() (and the fallback from LoadThemePrefs() in
262  // case we don't have a theme pack).
263  void BuildFromExtension(const Extension* extension);
264
265#if defined(TOOLKIT_USES_GTK)
266  // Loads an image and flips it horizontally if |rtl_enabled| is true.
267  GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled) const;
268#endif
269
270#if defined(TOOLKIT_USES_GTK)
271  typedef std::map<int, GdkPixbuf*> GdkPixbufMap;
272  mutable GdkPixbufMap gdk_pixbufs_;
273#elif defined(OS_MACOSX)
274  typedef std::map<int, NSImage*> NSImageMap;
275  mutable NSImageMap nsimage_cache_;
276
277  // The bool member of the pair is whether the color is a default color.
278  typedef std::map<int, std::pair<NSColor*, bool> > NSColorMap;
279  mutable NSColorMap nscolor_cache_;
280
281  typedef std::map<int, NSGradient*> NSGradientMap;
282  mutable NSGradientMap nsgradient_cache_;
283#endif
284
285  ResourceBundle& rb_;
286  Profile* profile_;
287
288  scoped_refptr<BrowserThemePack> theme_pack_;
289
290  // The number of infobars currently displayed.
291  int number_of_infobars_;
292
293  NotificationRegistrar registrar_;
294
295  DISALLOW_COPY_AND_ASSIGN(ThemeService);
296};
297
298#endif  // CHROME_BROWSER_THEMES_THEME_SERVICE_H_
299