Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Side by Side Diff: chrome/browser/browser_theme_provider.cc

Issue 499004: Try 2: Completely redo how themes are stored on disk and processed at install time. (Closed)
Patch Set: Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/browser_theme_provider.h" 5 #include "chrome/browser/browser_theme_provider.h"
6 6
7 #include "app/gfx/codec/png_codec.h" 7 #include "app/gfx/codec/png_codec.h"
8 #include "app/gfx/skbitmap_operations.h" 8 #include "app/gfx/skbitmap_operations.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "base/thread.h" 12 #include "base/thread.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/browser/browser_list.h" 14 #include "chrome/browser/browser_list.h"
15 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/browser_theme_pack.h"
16 #include "chrome/browser/browser_window.h" 17 #include "chrome/browser/browser_window.h"
17 #include "chrome/browser/extensions/extensions_service.h" 18 #include "chrome/browser/extensions/extensions_service.h"
18 #include "chrome/browser/metrics/user_metrics.h" 19 #include "chrome/browser/metrics/user_metrics.h"
19 #include "chrome/browser/profile.h" 20 #include "chrome/browser/profile.h"
20 #include "chrome/browser/theme_resources_util.h" 21 #include "chrome/browser/theme_resources_util.h"
21 #include "chrome/common/chrome_constants.h" 22 #include "chrome/common/chrome_constants.h"
22 #include "chrome/common/extensions/extension.h" 23 #include "chrome/common/extensions/extension.h"
23 #include "chrome/common/notification_service.h" 24 #include "chrome/common/notification_service.h"
24 #include "chrome/common/notification_type.h" 25 #include "chrome/common/notification_type.h"
25 #include "chrome/common/pref_names.h" 26 #include "chrome/common/pref_names.h"
26 #include "chrome/common/pref_service.h" 27 #include "chrome/common/pref_service.h"
27 #include "grit/app_resources.h" 28 #include "grit/app_resources.h"
28 #include "grit/theme_resources.h" 29 #include "grit/theme_resources.h"
29 #include "net/base/file_stream.h" 30 #include "net/base/file_stream.h"
30 #include "net/base/net_errors.h" 31 #include "net/base/net_errors.h"
31 #include "third_party/skia/include/core/SkBitmap.h" 32 #include "third_party/skia/include/core/SkBitmap.h"
32 #include "third_party/skia/include/core/SkCanvas.h" 33 #include "third_party/skia/include/core/SkCanvas.h"
33 #include "third_party/skia/include/core/SkUnPreMultiply.h" 34 #include "third_party/skia/include/core/SkUnPreMultiply.h"
34 35
35 #if defined(OS_WIN) 36 #if defined(OS_WIN)
36 #include "app/win_util.h" 37 #include "app/win_util.h"
37 #endif 38 #endif
38 39
39 // Strings used by themes to identify colors for different parts of our UI.
40 const char* BrowserThemeProvider::kColorFrame = "frame";
41 const char* BrowserThemeProvider::kColorFrameInactive = "frame_inactive";
42 const char* BrowserThemeProvider::kColorFrameIncognito = "frame_incognito";
43 const char* BrowserThemeProvider::kColorFrameIncognitoInactive =
44 "frame_incognito_inactive";
45 const char* BrowserThemeProvider::kColorToolbar = "toolbar";
46 const char* BrowserThemeProvider::kColorTabText = "tab_text";
47 const char* BrowserThemeProvider::kColorBackgroundTabText =
48 "tab_background_text";
49 const char* BrowserThemeProvider::kColorBookmarkText = "bookmark_text";
50 const char* BrowserThemeProvider::kColorNTPBackground = "ntp_background";
51 const char* BrowserThemeProvider::kColorNTPText = "ntp_text";
52 const char* BrowserThemeProvider::kColorNTPLink = "ntp_link";
53 const char* BrowserThemeProvider::kColorNTPLinkUnderline = "ntp_link_underline";
54 const char* BrowserThemeProvider::kColorNTPHeader = "ntp_header";
55 const char* BrowserThemeProvider::kColorNTPSection = "ntp_section";
56 const char* BrowserThemeProvider::kColorNTPSectionText = "ntp_section_text";
57 const char* BrowserThemeProvider::kColorNTPSectionLink = "ntp_section_link";
58 const char* BrowserThemeProvider::kColorNTPSectionLinkUnderline =
59 "ntp_section_link_underline";
60 const char* BrowserThemeProvider::kColorControlBackground =
61 "control_background";
62 const char* BrowserThemeProvider::kColorButtonBackground = "button_background";
63
64 // Strings used by themes to identify tints to apply to different parts of
65 // our UI. The frame tints apply to the frame color and produce the
66 // COLOR_FRAME* colors.
67 const char* BrowserThemeProvider::kTintButtons = "buttons";
68 const char* BrowserThemeProvider::kTintFrame = "frame";
69 const char* BrowserThemeProvider::kTintFrameInactive = "frame_inactive";
70 const char* BrowserThemeProvider::kTintFrameIncognito = "frame_incognito";
71 const char* BrowserThemeProvider::kTintFrameIncognitoInactive =
72 "frame_incognito_inactive";
73 const char* BrowserThemeProvider::kTintBackgroundTab = "background_tab";
74
75 // Strings used by themes to identify miscellaneous numerical properties.
76 const char* BrowserThemeProvider::kDisplayPropertyNTPAlignment =
77 "ntp_background_alignment";
78 const char* BrowserThemeProvider::kDisplayPropertyNTPTiling =
79 "ntp_background_repeat";
80 const char* BrowserThemeProvider::kDisplayPropertyNTPInverseLogo =
81 "ntp_logo_alternate";
82
83 // Strings used in alignment properties. 40 // Strings used in alignment properties.
84 const char* BrowserThemeProvider::kAlignmentTop = "top"; 41 const char* BrowserThemeProvider::kAlignmentTop = "top";
85 const char* BrowserThemeProvider::kAlignmentBottom = "bottom"; 42 const char* BrowserThemeProvider::kAlignmentBottom = "bottom";
86 const char* BrowserThemeProvider::kAlignmentLeft = "left"; 43 const char* BrowserThemeProvider::kAlignmentLeft = "left";
87 const char* BrowserThemeProvider::kAlignmentRight = "right"; 44 const char* BrowserThemeProvider::kAlignmentRight = "right";
88 45
89 // Strings used in background tiling repetition properties. 46 // Strings used in background tiling repetition properties.
90 const char* BrowserThemeProvider::kTilingNoRepeat = "no-repeat"; 47 const char* BrowserThemeProvider::kTilingNoRepeat = "no-repeat";
91 const char* BrowserThemeProvider::kTilingRepeatX = "repeat-x"; 48 const char* BrowserThemeProvider::kTilingRepeatX = "repeat-x";
92 const char* BrowserThemeProvider::kTilingRepeatY = "repeat-y"; 49 const char* BrowserThemeProvider::kTilingRepeatY = "repeat-y";
93 const char* BrowserThemeProvider::kTilingRepeat = "repeat"; 50 const char* BrowserThemeProvider::kTilingRepeat = "repeat";
94 51
95 // Default colors.
96 const SkColor BrowserThemeProvider::kDefaultColorFrame =
97 SkColorSetRGB(77, 139, 217);
98 const SkColor BrowserThemeProvider::kDefaultColorFrameInactive =
99 SkColorSetRGB(152, 188, 233);
100 const SkColor BrowserThemeProvider::kDefaultColorFrameIncognito =
101 SkColorSetRGB(83, 106, 139);
102 const SkColor BrowserThemeProvider::kDefaultColorFrameIncognitoInactive =
103 SkColorSetRGB(126, 139, 156);
104 const SkColor BrowserThemeProvider::kDefaultColorToolbar =
105 SkColorSetRGB(210, 225, 246);
106 const SkColor BrowserThemeProvider::kDefaultColorTabText = SK_ColorBLACK;
107 const SkColor BrowserThemeProvider::kDefaultColorBackgroundTabText =
108 SkColorSetRGB(64, 64, 64);
109 const SkColor BrowserThemeProvider::kDefaultColorBookmarkText =
110 SkColorSetRGB(18, 50, 114);
111 #if defined(OS_WIN)
112 const SkColor BrowserThemeProvider::kDefaultColorNTPBackground =
113 color_utils::GetSysSkColor(COLOR_WINDOW);
114 const SkColor BrowserThemeProvider::kDefaultColorNTPText =
115 color_utils::GetSysSkColor(COLOR_WINDOWTEXT);
116 const SkColor BrowserThemeProvider::kDefaultColorNTPLink =
117 color_utils::GetSysSkColor(COLOR_HOTLIGHT);
118 #else
119 // TODO(beng): source from theme provider.
120 const SkColor BrowserThemeProvider::kDefaultColorNTPBackground = SK_ColorWHITE;
121 const SkColor BrowserThemeProvider::kDefaultColorNTPText = SK_ColorBLACK;
122 const SkColor BrowserThemeProvider::kDefaultColorNTPLink =
123 SkColorSetRGB(6, 55, 116);
124 #endif
125 const SkColor BrowserThemeProvider::kDefaultColorNTPHeader =
126 SkColorSetRGB(75, 140, 220);
127 const SkColor BrowserThemeProvider::kDefaultColorNTPSection =
128 SkColorSetRGB(229, 239, 254);
129 const SkColor BrowserThemeProvider::kDefaultColorNTPSectionText = SK_ColorBLACK;
130 const SkColor BrowserThemeProvider::kDefaultColorNTPSectionLink =
131 SkColorSetRGB(6, 55, 116);
132 const SkColor BrowserThemeProvider::kDefaultColorControlBackground =
133 SkColorSetARGB(0, 0, 0, 0);
134 const SkColor BrowserThemeProvider::kDefaultColorButtonBackground =
135 SkColorSetARGB(0, 0, 0, 0);
136
137 // Default tints.
138 const color_utils::HSL BrowserThemeProvider::kDefaultTintButtons =
139 { -1, -1, -1 };
140 const color_utils::HSL BrowserThemeProvider::kDefaultTintFrame = { -1, -1, -1 };
141 const color_utils::HSL BrowserThemeProvider::kDefaultTintFrameInactive =
142 { -1, -1, 0.75f };
143 const color_utils::HSL BrowserThemeProvider::kDefaultTintFrameIncognito =
144 { -1, 0.2f, 0.35f };
145 const color_utils::HSL
146 BrowserThemeProvider::kDefaultTintFrameIncognitoInactive =
147 { -1, 0.3f, 0.6f };
148 const color_utils::HSL BrowserThemeProvider::kDefaultTintBackgroundTab =
149 { -1, 0.5, 0.75 };
150
151 // Saved default values. 52 // Saved default values.
152 const char* BrowserThemeProvider::kDefaultThemeID = ""; 53 const char* BrowserThemeProvider::kDefaultThemeID = "";
153 54
154 Lock BrowserThemeProvider::themed_image_cache_lock_; 55 namespace {
155 56
156 namespace { 57 SkColor TintForUnderline(SkColor input) {
58 return SkColorSetA(input, SkColorGetA(input) / 3);
59 }
60
61 // Default colors.
62 const SkColor kDefaultColorFrame = SkColorSetRGB(77, 139, 217);
63 const SkColor kDefaultColorFrameInactive = SkColorSetRGB(152, 188, 233);
64 const SkColor kDefaultColorFrameIncognito = SkColorSetRGB(83, 106, 139);
65 const SkColor kDefaultColorFrameIncognitoInactive =
66 SkColorSetRGB(126, 139, 156);
67 const SkColor kDefaultColorToolbar = SkColorSetRGB(210, 225, 246);
68 const SkColor kDefaultColorTabText = SK_ColorBLACK;
69 const SkColor kDefaultColorBackgroundTabText = SkColorSetRGB(64, 64, 64);
70 const SkColor kDefaultColorBookmarkText = SkColorSetRGB(18, 50, 114);
71 #if defined(OS_WIN)
72 const SkColor kDefaultColorNTPBackground =
73 color_utils::GetSysSkColor(COLOR_WINDOW);
74 const SkColor kDefaultColorNTPText =
75 color_utils::GetSysSkColor(COLOR_WINDOWTEXT);
76 const SkColor kDefaultColorNTPLink =
77 color_utils::GetSysSkColor(COLOR_HOTLIGHT);
78 #else
79 // TODO(beng): source from theme provider.
80 const SkColor kDefaultColorNTPBackground = SK_ColorWHITE;
81 const SkColor kDefaultColorNTPText = SK_ColorBLACK;
82 const SkColor kDefaultColorNTPLink = SkColorSetRGB(6, 55, 116);
83 #endif
84 const SkColor kDefaultColorNTPHeader = SkColorSetRGB(75, 140, 220);
85 const SkColor kDefaultColorNTPSection = SkColorSetRGB(229, 239, 254);
86 const SkColor kDefaultColorNTPSectionText = SK_ColorBLACK;
87 const SkColor kDefaultColorNTPSectionLink = SkColorSetRGB(6, 55, 116);
88 const SkColor kDefaultColorControlBackground = SkColorSetARGB(0, 0, 0, 0);
89 const SkColor kDefaultColorButtonBackground = SkColorSetARGB(0, 0, 0, 0);
90
91 // Default tints.
92 const color_utils::HSL kDefaultTintButtons = { -1, -1, -1 };
93 const color_utils::HSL kDefaultTintFrame = { -1, -1, -1 };
94 const color_utils::HSL kDefaultTintFrameInactive = { -1, -1, 0.75f };
95 const color_utils::HSL kDefaultTintFrameIncognito = { -1, 0.2f, 0.35f };
96 const color_utils::HSL kDefaultTintFrameIncognitoInactive = { -1, 0.3f, 0.6f };
97 const color_utils::HSL kDefaultTintBackgroundTab = { -1, 0.5, 0.75 };
157 98
158 // Default display properties. 99 // Default display properties.
159 const int kDefaultDisplayPropertyNTPAlignment = 100 const int kDefaultDisplayPropertyNTPAlignment =
160 BrowserThemeProvider::ALIGN_BOTTOM; 101 BrowserThemeProvider::ALIGN_BOTTOM;
161 const int kDefaultDisplayPropertyNTPTiling = 102 const int kDefaultDisplayPropertyNTPTiling =
162 BrowserThemeProvider::NO_REPEAT; 103 BrowserThemeProvider::NO_REPEAT;
163 const int kDefaultDisplayPropertyNTPInverseLogo = 0; 104 const int kDefaultDisplayPropertyNTPInverseLogo = 0;
164 105
165 // The sum of kFrameBorderThickness and kNonClientRestoredExtraThickness from 106 // The sum of kFrameBorderThickness and kNonClientRestoredExtraThickness from
166 // OpaqueBrowserFrameView. 107 // OpaqueBrowserFrameView.
167 const int kRestoredTabVerticalOffset = 15; 108 const int kRestoredTabVerticalOffset = 15;
168 109
169 // The image resources that will be tinted by the 'button' tint value.
170 const int kToolbarButtonIDs[] = {
171 IDR_BACK, IDR_BACK_D, IDR_BACK_H, IDR_BACK_P,
172 IDR_FORWARD, IDR_FORWARD_D, IDR_FORWARD_H, IDR_FORWARD_P,
173 IDR_RELOAD, IDR_RELOAD_H, IDR_RELOAD_P,
174 IDR_HOME, IDR_HOME_H, IDR_HOME_P,
175 IDR_STAR, IDR_STAR_NOBORDER, IDR_STAR_NOBORDER_CENTER, IDR_STAR_D, IDR_STAR_H,
176 IDR_STAR_P,
177 IDR_STARRED, IDR_STARRED_NOBORDER, IDR_STARRED_NOBORDER_CENTER, IDR_STARRED_H,
178 IDR_STARRED_P,
179 IDR_GO, IDR_GO_NOBORDER, IDR_GO_NOBORDER_CENTER, IDR_GO_H, IDR_GO_P,
180 IDR_STOP, IDR_STOP_NOBORDER, IDR_STOP_NOBORDER_CENTER, IDR_STOP_H, IDR_STOP_P,
181 IDR_MENU_BOOKMARK,
182 IDR_MENU_PAGE, IDR_MENU_PAGE_RTL,
183 IDR_MENU_CHROME, IDR_MENU_CHROME_RTL,
184 IDR_MENU_DROPARROW,
185 IDR_THROBBER, IDR_THROBBER_WAITING, IDR_THROBBER_LIGHT,
186 IDR_LOCATIONBG
187 };
188
189 bool HasButtonImage(int toolbar_button_id) {
190 static std::map<int, bool> button_images;
191 if (button_images.empty()) {
192 for (size_t i = 0; i < arraysize(kToolbarButtonIDs); ++i)
193 button_images[kToolbarButtonIDs[i]] = true;
194 }
195 return button_images.count(toolbar_button_id) > 0;
196 }
197
198 // The image resources we will allow people to theme. 110 // The image resources we will allow people to theme.
199 const int kThemeableImages[] = { 111 const int kThemeableImages[] = {
200 IDR_THEME_FRAME, 112 IDR_THEME_FRAME,
201 IDR_THEME_FRAME_INACTIVE, 113 IDR_THEME_FRAME_INACTIVE,
202 IDR_THEME_FRAME_INCOGNITO, 114 IDR_THEME_FRAME_INCOGNITO,
203 IDR_THEME_FRAME_INCOGNITO_INACTIVE, 115 IDR_THEME_FRAME_INCOGNITO_INACTIVE,
204 IDR_THEME_TOOLBAR, 116 IDR_THEME_TOOLBAR,
205 IDR_THEME_TAB_BACKGROUND, 117 IDR_THEME_TAB_BACKGROUND,
206 IDR_THEME_TAB_BACKGROUND_INCOGNITO, 118 IDR_THEME_TAB_BACKGROUND_INCOGNITO,
207 IDR_THEME_TAB_BACKGROUND_V, 119 IDR_THEME_TAB_BACKGROUND_V,
208 IDR_THEME_NTP_BACKGROUND, 120 IDR_THEME_NTP_BACKGROUND,
209 IDR_THEME_FRAME_OVERLAY, 121 IDR_THEME_FRAME_OVERLAY,
210 IDR_THEME_FRAME_OVERLAY_INACTIVE, 122 IDR_THEME_FRAME_OVERLAY_INACTIVE,
211 IDR_THEME_BUTTON_BACKGROUND, 123 IDR_THEME_BUTTON_BACKGROUND,
212 IDR_THEME_NTP_ATTRIBUTION, 124 IDR_THEME_NTP_ATTRIBUTION,
213 IDR_THEME_WINDOW_CONTROL_BACKGROUND 125 IDR_THEME_WINDOW_CONTROL_BACKGROUND
214 }; 126 };
215 127
216 bool HasThemeableImage(int themeable_image_id) { 128 bool HasThemeableImage(int themeable_image_id) {
217 static std::map<int, bool> themeable_images; 129 static std::map<int, bool> themeable_images;
218 if (themeable_images.empty()) { 130 if (themeable_images.empty()) {
219 for (size_t i = 0; i < arraysize(kThemeableImages); ++i) 131 for (size_t i = 0; i < arraysize(kThemeableImages); ++i)
220 themeable_images[kThemeableImages[i]] = true; 132 themeable_images[kThemeableImages[i]] = true;
221 } 133 }
222 return themeable_images.count(themeable_image_id) > 0; 134 return themeable_images.count(themeable_image_id) > 0;
223 } 135 }
224 136
225 137 // Writes the theme pack to disk on a separate thread.
226 class WriteImagesToDiskTask : public Task { 138 class WritePackToDiskTask : public Task {
227 public: 139 public:
228 WriteImagesToDiskTask( 140 WritePackToDiskTask(BrowserThemePack* pack, const FilePath& path)
229 const BrowserThemeProvider::ImagesDiskCache& images_disk_cache, 141 : theme_pack_(pack), pack_path_(path) {}
230 const BrowserThemeProvider::ImageCache& themed_image_cache) :
231 images_disk_cache_(images_disk_cache),
232 themed_image_cache_(themed_image_cache) {
233 }
234 142
235 virtual void Run() { 143 virtual void Run() {
236 AutoLock lock(BrowserThemeProvider::themed_image_cache_lock_); 144 if (!theme_pack_->WriteToDisk(pack_path_)) {
237 for (BrowserThemeProvider::ImagesDiskCache::const_iterator iter( 145 NOTREACHED() << "Could not write theme pack to disk";
238 images_disk_cache_.begin()); iter != images_disk_cache_.end();
239 ++iter) {
240 FilePath image_path = iter->first;
241 BrowserThemeProvider::ImageCache::const_iterator themed_iter =
242 themed_image_cache_.find(iter->second);
243 if (themed_iter != themed_image_cache_.end()) {
244 SkBitmap* bitmap = themed_iter->second;
245 std::vector<unsigned char> image_data;
246 if (!gfx::PNGCodec::EncodeBGRASkBitmap(*bitmap, false, &image_data)) {
247 NOTREACHED() << "Image file could not be encoded.";
248 return;
249 }
250 const char* image_data_ptr =
251 reinterpret_cast<const char*>(&image_data[0]);
252 if (!file_util::WriteFile(image_path,
253 image_data_ptr, image_data.size())) {
254 NOTREACHED() << "Image file could not be written to disk.";
255 return;
256 }
257 } else {
258 NOTREACHED() << "Themed image missing from cache.";
259 return;
260 }
261 } 146 }
262 } 147 }
263 148
264 private: 149 private:
265 // References to data held in the BrowserThemeProvider. 150 scoped_refptr<BrowserThemePack> theme_pack_;
266 const BrowserThemeProvider::ImagesDiskCache& images_disk_cache_; 151 FilePath pack_path_;
267 const BrowserThemeProvider::ImageCache& themed_image_cache_;
268 }; 152 };
269 153
270 } // namespace 154 } // namespace
271 155
272 bool BrowserThemeProvider::IsThemeableImage(int resource_id) { 156 bool BrowserThemeProvider::IsThemeableImage(int resource_id) {
273 return HasThemeableImage(resource_id); 157 return HasThemeableImage(resource_id);
274 } 158 }
275 159
276 BrowserThemeProvider::BrowserThemeProvider() 160 BrowserThemeProvider::BrowserThemeProvider()
277 : rb_(ResourceBundle::GetSharedInstance()), 161 : rb_(ResourceBundle::GetSharedInstance()),
278 profile_(NULL), 162 profile_(NULL) {
279 process_images_(false) {
280 // Initialize the themeable image map so we can use it on other threads. 163 // Initialize the themeable image map so we can use it on other threads.
281 HasThemeableImage(0); 164 HasThemeableImage(0);
282 resource_names_[IDR_THEME_FRAME] = "theme_frame";
283 resource_names_[IDR_THEME_FRAME_INACTIVE] = "theme_frame_inactive";
284 resource_names_[IDR_THEME_FRAME_OVERLAY] = "theme_frame_overlay";
285 resource_names_[IDR_THEME_FRAME_OVERLAY_INACTIVE] =
286 "theme_frame_overlay_inactive";
287 resource_names_[IDR_THEME_FRAME_INCOGNITO] = "theme_frame_incognito";
288 resource_names_[IDR_THEME_FRAME_INCOGNITO_INACTIVE] =
289 "theme_frame_incognito_inactive";
290 resource_names_[IDR_THEME_TAB_BACKGROUND] = "theme_tab_background";
291 resource_names_[IDR_THEME_TAB_BACKGROUND_INCOGNITO] =
292 "theme_tab_background_incognito";
293 resource_names_[IDR_THEME_TOOLBAR] = "theme_toolbar";
294 resource_names_[IDR_THEME_TAB_BACKGROUND_V] = "theme_tab_background_v";
295 resource_names_[IDR_THEME_NTP_BACKGROUND] = "theme_ntp_background";
296 resource_names_[IDR_THEME_BUTTON_BACKGROUND] = "theme_button_background";
297 resource_names_[IDR_THEME_NTP_ATTRIBUTION] = "theme_ntp_attribution";
298 resource_names_[IDR_THEME_WINDOW_CONTROL_BACKGROUND] =
299 "theme_window_control_background";
300 } 165 }
301 166
302 BrowserThemeProvider::~BrowserThemeProvider() { 167 BrowserThemeProvider::~BrowserThemeProvider() {
303 ClearCaches(); 168 FreePlatformCaches();
304 169
305 RemoveUnusedThemes(); 170 RemoveUnusedThemes();
306 } 171 }
307 172
308 void BrowserThemeProvider::Init(Profile* profile) { 173 void BrowserThemeProvider::Init(Profile* profile) {
309 DCHECK(CalledOnValidThread()); 174 DCHECK(CalledOnValidThread());
310 profile_ = profile; 175 profile_ = profile;
311 176
312 image_dir_ = profile_->GetPath().Append(chrome::kThemeImagesDirname);
313 if (!file_util::PathExists(image_dir_))
314 file_util::CreateDirectory(image_dir_);
315
316 LoadThemePrefs(); 177 LoadThemePrefs();
317 } 178 }
318 179
319 SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) const { 180 SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) const {
320 DCHECK(CalledOnValidThread()); 181 DCHECK(CalledOnValidThread());
321 182
322 // First check to see if the Skia image is in the themed cache. The themed 183 SkBitmap* bitmap = NULL;
323 // cache is not changed in this method, so it can remain unlocked.
324 ImageCache::const_iterator themed_iter = themed_image_cache_.find(id);
325 if (themed_iter != themed_image_cache_.end())
326 return themed_iter->second;
327 184
328 // If Skia image is not in themed cache, check regular cache, and possibly 185 if (theme_pack_.get())
329 // generate and store. 186 bitmap = theme_pack_->GetBitmapNamed(id);
330 ImageCache::const_iterator image_iter = image_cache_.find(id);
331 if (image_iter != image_cache_.end())
332 return image_iter->second;
333 187
334 scoped_ptr<SkBitmap> result; 188 if (!bitmap)
189 bitmap = rb_.GetBitmapNamed(id);
335 190
336 // Try to load the image from the extension. 191 return bitmap;
337 result.reset(LoadThemeBitmap(id));
338
339 // If we still don't have an image, load it from resourcebundle.
340 if (!result.get())
341 result.reset(new SkBitmap(*rb_.GetBitmapNamed(id)));
342
343 if (result.get()) {
344 // If the requested image is part of the toolbar button set, and we have
345 // a provided tint for that set, tint it appropriately.
346 if (HasButtonImage(id) && tints_.count(kTintButtons)) {
347 SkBitmap* tinted =
348 new SkBitmap(TintBitmap(*result.release(), TINT_BUTTONS));
349 result.reset(tinted);
350 }
351
352 // We loaded successfully. Cache the bitmap.
353 image_cache_[id] = result.get();
354 return result.release();
355 } else {
356 NOTREACHED() << "Failed to load a requested image";
357 return NULL;
358 }
359 } 192 }
360 193
361 SkColor BrowserThemeProvider::GetColor(int id) const { 194 SkColor BrowserThemeProvider::GetColor(int id) const {
362 DCHECK(CalledOnValidThread()); 195 DCHECK(CalledOnValidThread());
363 196
364 // Special-case NTP header - if the color isn't provided, we fall back to 197 SkColor color;
365 // the section color. 198 if (theme_pack_.get() && theme_pack_->GetColor(id, &color))
366 if (id == COLOR_NTP_HEADER) { 199 return color;
367 ColorMap::const_iterator color_iter = colors_.find(kColorNTPHeader);
368 if (color_iter != colors_.end())
369 return color_iter->second;
370 color_iter = colors_.find(kColorNTPSection);
371 return (color_iter == colors_.end()) ?
372 GetDefaultColor(id) : color_iter->second;
373 }
374 200
375 // Special case the underline colors to use semi transparent in case not 201 return GetDefaultColor(id);
376 // defined.
377 if (id == COLOR_NTP_SECTION_LINK_UNDERLINE) {
378 ColorMap::const_iterator color_iter =
379 colors_.find(kColorNTPSectionLinkUnderline);
380 if (color_iter != colors_.end())
381 return color_iter->second;
382 SkColor color_section_link = GetColor(COLOR_NTP_SECTION_LINK);
383 return SkColorSetA(color_section_link, SkColorGetA(color_section_link) / 3);
384 }
385
386 if (id == COLOR_NTP_LINK_UNDERLINE) {
387 ColorMap::const_iterator color_iter = colors_.find(kColorNTPLinkUnderline);
388 if (color_iter != colors_.end())
389 return color_iter->second;
390 SkColor color_link = GetColor(COLOR_NTP_LINK);
391 return SkColorSetA(color_link, SkColorGetA(color_link) / 3);
392 }
393
394 // TODO(glen): Figure out if we need to tint these. http://crbug.com/11578
395 ColorMap::const_iterator color_iter = colors_.find(GetColorKey(id));
396 return (color_iter == colors_.end()) ?
397 GetDefaultColor(id) : color_iter->second;
398 } 202 }
399 203
400 bool BrowserThemeProvider::GetDisplayProperty(int id, int* result) const { 204 bool BrowserThemeProvider::GetDisplayProperty(int id, int* result) const {
401 switch (id) { 205 if (theme_pack_.get())
402 case NTP_BACKGROUND_ALIGNMENT: { 206 return theme_pack_->GetDisplayProperty(id, result);
403 DisplayPropertyMap::const_iterator display_iter = 207
404 display_properties_.find(kDisplayPropertyNTPAlignment); 208 return GetDefaultDisplayProperty(id, result);
405 *result = (display_iter == display_properties_.end()) ?
406 kDefaultDisplayPropertyNTPAlignment : display_iter->second;
407 return true;
408 }
409 case NTP_BACKGROUND_TILING: {
410 DisplayPropertyMap::const_iterator display_iter =
411 display_properties_.find(kDisplayPropertyNTPTiling);
412 *result = (display_iter == display_properties_.end()) ?
413 kDefaultDisplayPropertyNTPTiling : display_iter->second;
414 return true;
415 }
416 case NTP_LOGO_ALTERNATE: {
417 DisplayPropertyMap::const_iterator display_iter =
418 display_properties_.find(kDisplayPropertyNTPInverseLogo);
419 *result = (display_iter == display_properties_.end()) ?
420 kDefaultDisplayPropertyNTPInverseLogo : display_iter->second;
421 return true;
422 }
423 default:
424 NOTREACHED() << "Unknown property requested";
425 }
426 return false;
427 } 209 }
428 210
429 bool BrowserThemeProvider::ShouldUseNativeFrame() const { 211 bool BrowserThemeProvider::ShouldUseNativeFrame() const {
430 if (HasCustomImage(IDR_THEME_FRAME)) 212 if (HasCustomImage(IDR_THEME_FRAME))
431 return false; 213 return false;
432 #if defined(OS_WIN) 214 #if defined(OS_WIN)
433 return win_util::ShouldUseVistaFrame(); 215 return win_util::ShouldUseVistaFrame();
434 #else 216 #else
435 return false; 217 return false;
436 #endif 218 #endif
437 } 219 }
438 220
439 bool BrowserThemeProvider::HasCustomImage(int id) const { 221 bool BrowserThemeProvider::HasCustomImage(int id) const {
440 if (!HasThemeableImage(id)) 222 if (!HasThemeableImage(id))
441 return false; 223 return false;
442 224
443 // A custom image = base name is NOT equal to resource name. See note in 225 if (theme_pack_)
444 // SaveThemeBitmap describing the process by which an original image is 226 return theme_pack_->HasCustomImage(id);
445 // tagged. 227
446 ImageMap::const_iterator images_iter = images_.find(id); 228 return false;
447 ResourceNameMap::const_iterator names_iter = resource_names_.find(id);
448 if ((images_iter == images_.end()) || (names_iter == resource_names_.end()))
449 return false;
450 return !EndsWith(UTF8ToWide(images_iter->second),
451 UTF8ToWide(names_iter->second), false);
452 } 229 }
453 230
454 RefCountedMemory* BrowserThemeProvider::GetRawData(int id) const { 231 RefCountedMemory* BrowserThemeProvider::GetRawData(int id) const {
455 // Check to see whether we should substitute some images. 232 // Check to see whether we should substitute some images.
456 int ntp_alternate; 233 int ntp_alternate;
457 GetDisplayProperty(NTP_LOGO_ALTERNATE, &ntp_alternate); 234 GetDisplayProperty(NTP_LOGO_ALTERNATE, &ntp_alternate);
458 if (id == IDR_PRODUCT_LOGO && ntp_alternate != 0) 235 if (id == IDR_PRODUCT_LOGO && ntp_alternate != 0)
459 id = IDR_PRODUCT_LOGO_WHITE; 236 id = IDR_PRODUCT_LOGO_WHITE;
460 237
461 RawDataMap::const_iterator data_iter = raw_data_.find(id); 238 RefCountedMemory* data = NULL;
462 if (data_iter != raw_data_.end()) 239 if (theme_pack_.get())
463 return data_iter->second; 240 data = theme_pack_->GetRawData(id);
464
465 RefCountedMemory* data = ReadThemeFileData(id);
466 if (!data) 241 if (!data)
467 data = rb_.LoadDataResourceBytes(id); 242 data = rb_.LoadDataResourceBytes(id);
468 if (!data)
469 return NULL;
470 243
471 raw_data_[id] = data;
472 return data; 244 return data;
473 } 245 }
474 246
475 void BrowserThemeProvider::SetTheme(Extension* extension) { 247 void BrowserThemeProvider::SetTheme(Extension* extension) {
476 // Clear our image cache. 248 // Clear our image cache.
477 ClearCaches(); 249 FreePlatformCaches();
478 250
479 DCHECK(extension); 251 DCHECK(extension);
480 DCHECK(extension->IsTheme()); 252 DCHECK(extension->IsTheme());
481 SetImageData(extension->GetThemeImages(),
482 extension->path());
483 SetColorData(extension->GetThemeColors());
484 SetTintData(extension->GetThemeTints());
485 253
486 // Drop out to default theme if the theme data is empty. 254 BuildFromExtension(extension);
487 if (images_.empty() && colors_.empty() && tints_.empty()) {
488 UseDefaultTheme();
489 return;
490 }
491
492 SetDisplayPropertyData(extension->GetThemeDisplayProperties());
493 raw_data_.clear();
494
495 SaveImageData(extension->GetThemeImages());
496 SaveColorData();
497 SaveTintData();
498 SaveDisplayPropertyData();
499 SaveThemeID(extension->id()); 255 SaveThemeID(extension->id());
500 256
501 // Process all images when we first set theme.
502 process_images_ = true;
503
504 GenerateFrameColors();
505 if (ShouldTintFrames()) {
506 AutoLock lock(themed_image_cache_lock_);
507 GenerateFrameImages();
508 GenerateTabImages();
509 }
510
511 WriteImagesToDisk();
512 NotifyThemeChanged(); 257 NotifyThemeChanged();
513 UserMetrics::RecordAction("Themes_Installed", profile_); 258 UserMetrics::RecordAction("Themes_Installed", profile_);
514 } 259 }
515 260
516 void BrowserThemeProvider::RemoveUnusedThemes() { 261 void BrowserThemeProvider::RemoveUnusedThemes() {
517 if (!profile_) 262 if (!profile_)
518 return; 263 return;
519 ExtensionsService* service = profile_->GetExtensionsService(); 264 ExtensionsService* service = profile_->GetExtensionsService();
520 if (!service) 265 if (!service)
521 return; 266 return;
(...skipping 14 matching lines...) Expand all
536 ClearAllThemeData(); 281 ClearAllThemeData();
537 NotifyThemeChanged(); 282 NotifyThemeChanged();
538 UserMetrics::RecordAction("Themes_Reset", profile_); 283 UserMetrics::RecordAction("Themes_Reset", profile_);
539 } 284 }
540 285
541 std::string BrowserThemeProvider::GetThemeID() const { 286 std::string BrowserThemeProvider::GetThemeID() const {
542 std::wstring id = profile_->GetPrefs()->GetString(prefs::kCurrentThemeID); 287 std::wstring id = profile_->GetPrefs()->GetString(prefs::kCurrentThemeID);
543 return WideToUTF8(id); 288 return WideToUTF8(id);
544 } 289 }
545 290
546 RefCountedMemory* BrowserThemeProvider::ReadThemeFileData(int id) const {
547 ImageMap::const_iterator images_iter = images_.find(id);
548 if (images_iter != images_.end()) {
549 // First check to see if we have a registered theme extension and whether
550 // it can handle this resource.
551 #if defined(OS_WIN)
552 FilePath path = FilePath(UTF8ToWide(images_iter->second));
553 #else
554 FilePath path = FilePath(images_iter->second);
555 #endif
556 if (!path.empty()) {
557 net::FileStream file;
558 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
559 if (file.Open(path, flags) == net::OK) {
560 int64 avail = file.Available();
561 if (avail > 0 && avail < INT_MAX) {
562 size_t size = static_cast<size_t>(avail);
563 std::vector<unsigned char> raw_data;
564 raw_data.resize(size);
565 char* data = reinterpret_cast<char*>(&(raw_data.front()));
566 if (file.ReadUntilComplete(data, size) == avail)
567 return RefCountedBytes::TakeVector(&raw_data);
568 }
569 }
570 }
571 }
572
573 return NULL;
574 }
575
576 // static 291 // static
577 std::string BrowserThemeProvider::AlignmentToString(int alignment) { 292 std::string BrowserThemeProvider::AlignmentToString(int alignment) {
578 // Convert from an AlignmentProperty back into a string. 293 // Convert from an AlignmentProperty back into a string.
579 std::string vertical_string; 294 std::string vertical_string;
580 std::string horizontal_string; 295 std::string horizontal_string;
581 296
582 if (alignment & BrowserThemeProvider::ALIGN_TOP) 297 if (alignment & BrowserThemeProvider::ALIGN_TOP)
583 vertical_string = kAlignmentTop; 298 vertical_string = kAlignmentTop;
584 else if (alignment & BrowserThemeProvider::ALIGN_BOTTOM) 299 else if (alignment & BrowserThemeProvider::ALIGN_BOTTOM)
585 vertical_string = kAlignmentBottom; 300 vertical_string = kAlignmentBottom;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 if (base::strcasecmp(component, kTilingRepeatX) == 0) 354 if (base::strcasecmp(component, kTilingRepeatX) == 0)
640 return BrowserThemeProvider::REPEAT_X; 355 return BrowserThemeProvider::REPEAT_X;
641 if (base::strcasecmp(component, kTilingRepeatY) == 0) 356 if (base::strcasecmp(component, kTilingRepeatY) == 0)
642 return BrowserThemeProvider::REPEAT_Y; 357 return BrowserThemeProvider::REPEAT_Y;
643 if (base::strcasecmp(component, kTilingRepeat) == 0) 358 if (base::strcasecmp(component, kTilingRepeat) == 0)
644 return BrowserThemeProvider::REPEAT; 359 return BrowserThemeProvider::REPEAT;
645 // NO_REPEAT is the default choice. 360 // NO_REPEAT is the default choice.
646 return BrowserThemeProvider::NO_REPEAT; 361 return BrowserThemeProvider::NO_REPEAT;
647 } 362 }
648 363
649 void BrowserThemeProvider::SetColor(const char* key, const SkColor& color) { 364 // static
650 colors_[key] = color; 365 color_utils::HSL BrowserThemeProvider::GetDefaultTint(int id) {
651 }
652
653 void BrowserThemeProvider::SetTint(const char* key,
654 const color_utils::HSL& tint) {
655 tints_[key] = tint;
656 }
657
658 color_utils::HSL BrowserThemeProvider::GetTint(int id) const {
659 DCHECK(CalledOnValidThread());
660
661 TintMap::const_iterator tint_iter = tints_.find(GetTintKey(id));
662 return (tint_iter == tints_.end()) ? GetDefaultTint(id) : tint_iter->second;
663 }
664
665 void BrowserThemeProvider::GenerateFrameColors() {
666 // Generate any secondary frame colors that weren't provided.
667 SkColor frame = GetColor(COLOR_FRAME);
668
669 if (!colors_.count(kColorFrame))
670 colors_[kColorFrame] = HSLShift(frame, GetTint(TINT_FRAME));
671 if (!colors_.count(kColorFrameInactive)) {
672 colors_[kColorFrameInactive] =
673 HSLShift(frame, GetTint(TINT_FRAME_INACTIVE));
674 }
675 if (!colors_.count(kColorFrameIncognito)) {
676 colors_[kColorFrameIncognito] =
677 HSLShift(frame, GetTint(TINT_FRAME_INCOGNITO));
678 }
679 if (!colors_.count(kColorFrameIncognitoInactive)) {
680 colors_[kColorFrameIncognitoInactive] =
681 HSLShift(frame, GetTint(TINT_FRAME_INCOGNITO_INACTIVE));
682 }
683 }
684
685 void BrowserThemeProvider::GenerateFrameImages() const {
686 // A map of frame image IDs to the tints for those ids.
687 typedef std::map<int, int> FrameTintMap;
688 static FrameTintMap frame_tints;
689 if (frame_tints.empty()) {
690 frame_tints[IDR_THEME_FRAME] = TINT_FRAME;
691 frame_tints[IDR_THEME_FRAME_INACTIVE] = TINT_FRAME_INACTIVE;
692 frame_tints[IDR_THEME_FRAME_OVERLAY] = TINT_FRAME;
693 frame_tints[IDR_THEME_FRAME_OVERLAY_INACTIVE] = TINT_FRAME_INACTIVE;
694 frame_tints[IDR_THEME_FRAME_INCOGNITO] = TINT_FRAME_INCOGNITO;
695 frame_tints[IDR_THEME_FRAME_INCOGNITO_INACTIVE] =
696 TINT_FRAME_INCOGNITO_INACTIVE;
697 }
698
699 for (FrameTintMap::const_iterator iter(frame_tints.begin());
700 iter != frame_tints.end(); ++iter) {
701 int id = iter->first;
702 scoped_ptr<SkBitmap> frame;
703 // If there's no frame image provided for the specified id, then load
704 // the default provided frame. If that's not provided, skip this whole
705 // thing and just use the default images.
706 int base_id;
707 std::string resource_name;
708
709 // If we've already processed the images for this theme, they're all
710 // waiting on disk -- just load them in.
711 if (!process_images_) {
712 frame.reset(LoadThemeBitmap(id));
713 if (frame.get())
714 themed_image_cache_[id] = new SkBitmap(*frame.get());
715 } else {
716 resource_name = resource_names_.find(id)->second;
717 if (id == IDR_THEME_FRAME_INCOGNITO_INACTIVE) {
718 base_id = HasCustomImage(IDR_THEME_FRAME_INCOGNITO) ?
719 IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
720 } else if (id == IDR_THEME_FRAME_OVERLAY_INACTIVE) {
721 base_id = IDR_THEME_FRAME_OVERLAY;
722 } else if (id == IDR_THEME_FRAME_INACTIVE) {
723 base_id = IDR_THEME_FRAME;
724 } else if (id == IDR_THEME_FRAME_INCOGNITO &&
725 !HasCustomImage(IDR_THEME_FRAME_INCOGNITO)) {
726 base_id = IDR_THEME_FRAME;
727 } else {
728 base_id = id;
729 }
730
731 if (HasCustomImage(id)) {
732 frame.reset(LoadThemeBitmap(id));
733 } else if (base_id != id && HasCustomImage(base_id)) {
734 frame.reset(LoadThemeBitmap(base_id));
735 } else if (base_id == IDR_THEME_FRAME_OVERLAY &&
736 HasCustomImage(IDR_THEME_FRAME)) {
737 // If there is no theme overlay, don't tint the default frame,
738 // because it will overwrite the custom frame image when we cache and
739 // reload from disk.
740 frame.reset(NULL);
741 } else {
742 // If the theme doesn't specify an image, then apply the tint to
743 // the default frame.
744 frame.reset(new SkBitmap(*rb_.GetBitmapNamed(IDR_THEME_FRAME)));
745 }
746
747 if (frame.get()) {
748 SkBitmap* tinted = new SkBitmap(TintBitmap(*frame, iter->second));
749 themed_image_cache_[id] = tinted;
750 SaveThemeBitmap(resource_name, id);
751 }
752 }
753 }
754 }
755
756 void BrowserThemeProvider::GenerateTabImages() const {
757 GenerateTabBackgroundBitmap(IDR_THEME_TAB_BACKGROUND);
758 GenerateTabBackgroundBitmap(IDR_THEME_TAB_BACKGROUND_INCOGNITO);
759 }
760
761 void BrowserThemeProvider::ClearAllThemeData() {
762 // Clear our image cache.
763 ClearCaches();
764
765 images_.clear();
766 colors_.clear();
767 tints_.clear();
768 display_properties_.clear();
769 raw_data_.clear();
770
771 SaveImageData(NULL);
772 SaveColorData();
773 SaveTintData();
774 SaveDisplayPropertyData();
775 SaveThemeID(kDefaultThemeID);
776 }
777
778 void BrowserThemeProvider::LoadThemePrefs() {
779 process_images_ = false;
780 PrefService* prefs = profile_->GetPrefs();
781
782 // TODO(glen): Figure out if any custom prefs were loaded, and if so UMA-log
783 // the fact that a theme was loaded.
784 if (!prefs->HasPrefPath(prefs::kCurrentThemeImages) &&
785 !prefs->HasPrefPath(prefs::kCurrentThemeColors) &&
786 !prefs->HasPrefPath(prefs::kCurrentThemeTints))
787 return;
788
789 // Our prefs already have the extension path baked in, so we don't need to
790 // provide it.
791 SetImageData(prefs->GetMutableDictionary(prefs::kCurrentThemeImages),
792 FilePath());
793 SetColorData(prefs->GetMutableDictionary(prefs::kCurrentThemeColors));
794 SetTintData(prefs->GetMutableDictionary(prefs::kCurrentThemeTints));
795 SetDisplayPropertyData(
796 prefs->GetMutableDictionary(prefs::kCurrentThemeDisplayProperties));
797
798 // If we're not loading the frame from the cached image dir, we are using an
799 // old preferences file, or the processed images were not saved correctly.
800 // Force image reprocessing and caching.
801 ImageMap::const_iterator images_iter = images_.find(IDR_THEME_FRAME);
802 if (images_iter != images_.end()) {
803 #if defined(OS_WIN)
804 FilePath cache_path = FilePath(UTF8ToWide(images_iter->second));
805 #else
806 FilePath cache_path = FilePath(images_iter->second);
807 #endif
808 process_images_ = !file_util::ContainsPath(image_dir_, cache_path);
809 }
810
811 GenerateFrameColors();
812 // Scope for AutoLock on themed_image_cache.
813 {
814 AutoLock lock(themed_image_cache_lock_);
815 GenerateFrameImages();
816 GenerateTabImages();
817 }
818
819 if (process_images_) {
820 WriteImagesToDisk();
821 UserMetrics::RecordAction("Migrated noncached to cached theme.", profile_);
822 }
823 UserMetrics::RecordAction("Themes_loaded", profile_);
824 }
825
826 void BrowserThemeProvider::NotifyThemeChanged() {
827 // Redraw!
828 NotificationService* service = NotificationService::current();
829 service->Notify(NotificationType::BROWSER_THEME_CHANGED,
830 Source<BrowserThemeProvider>(this),
831 NotificationService::NoDetails());
832 }
833
834 SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) const {
835 DCHECK(CalledOnValidThread());
836
837 if (!HasThemeableImage(id))
838 return NULL;
839
840 scoped_refptr<RefCountedMemory> raw_data;
841
842 // We special case images related to the NTP so we first try raw data. Why?
843 // Because the DOMUI stuff uses that interface to return raw PNG data instead
844 // of the normal theme interface which returns SkBitmaps. GetRawData() also
845 // caches the PNG data so it opens new tab pages faster. If we didn't try and
846 // otherwise we would be loading big images twice, once through GetRawData()
847 // and once here. Ouch. So either we prime the GetRawData() cache for when
848 // DOMUIThemeSource requests our image, or we take advantage of the already
849 // loaded data, saving a trip to disk.
850 if (id == IDR_THEME_NTP_BACKGROUND)
851 raw_data = GetRawData(id);
852
853 if (!raw_data)
854 raw_data = ReadThemeFileData(id);
855
856 if (raw_data) {
857 // Decode the PNG.
858 SkBitmap bitmap;
859 if (!gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(),
860 &bitmap)) {
861 NOTREACHED() << "Unable to decode theme image resource " << id;
862 return NULL;
863 }
864
865 return new SkBitmap(bitmap);
866 } else {
867 // TODO(glen): File no-longer exists, we're out of date. We should
868 // clear the theme (or maybe just the pref that points to this
869 // image).
870 return NULL;
871 }
872 }
873
874 void BrowserThemeProvider::SaveThemeBitmap(std::string resource_name,
875 int id) const {
876 DCHECK(CalledOnValidThread());
877 if (!themed_image_cache_.count(id)) {
878 NOTREACHED();
879 return;
880 }
881
882 // The images_ directory, at this point, contains only the custom images
883 // provided by the extension. We tag these images "_original" in the prefs
884 // file so we can distinguish them from images which have been generated and
885 // saved to disk by the theme caching process (WriteImagesToDisk). This way,
886 // when we call HasCustomImage, we can check for the "_original" tag to see
887 // whether an image was originally provided by the extension, or saved
888 // in the caching process.
889 if (images_.count(id))
890 resource_name.append("_original");
891
892 #if defined(OS_WIN)
893 FilePath image_path = image_dir_.Append(UTF8ToWide(resource_name));
894 #elif defined(OS_POSIX)
895 FilePath image_path = image_dir_.Append(resource_name);
896 #endif
897
898 images_disk_cache_[image_path] = id;
899 }
900
901 #if defined(OS_WIN)
902 void BrowserThemeProvider::FreePlatformCaches() {
903 // Views (Skia) has no platform image cache to clear.
904 }
905 #endif
906
907 SkBitmap* BrowserThemeProvider::GenerateTabBackgroundBitmapImpl(int id) const {
908 int base_id = (id == IDR_THEME_TAB_BACKGROUND) ?
909 IDR_THEME_FRAME : IDR_THEME_FRAME_INCOGNITO;
910 // According to Miranda, it is safe to read from the themed_image_cache_ here
911 // because we only lock to write on the UI thread, and we only lock to read
912 // on the cache writing thread.
913 ImageCache::const_iterator themed_iter = themed_image_cache_.find(base_id);
914 if (themed_iter == themed_image_cache_.end())
915 return NULL;
916
917 SkBitmap bg_tint = TintBitmap(*(themed_iter->second), TINT_BACKGROUND_TAB);
918 int vertical_offset = HasCustomImage(id) ? kRestoredTabVerticalOffset : 0;
919 SkBitmap* bg_tab = new SkBitmap(SkBitmapOperations::CreateTiledBitmap(
920 bg_tint, 0, vertical_offset, bg_tint.width(), bg_tint.height()));
921
922 // If they've provided a custom image, overlay it.
923 if (HasCustomImage(id)) {
924 SkBitmap* overlay = LoadThemeBitmap(id);
925 if (overlay) {
926 SkCanvas canvas(*bg_tab);
927 for (int x = 0; x < bg_tab->width(); x += overlay->width())
928 canvas.drawBitmap(*overlay, static_cast<SkScalar>(x), 0, NULL);
929 }
930 }
931
932 return bg_tab;
933 }
934
935 const std::string BrowserThemeProvider::GetTintKey(int id) const {
936 switch (id) {
937 case TINT_FRAME:
938 return kTintFrame;
939 case TINT_FRAME_INACTIVE:
940 return kTintFrameInactive;
941 case TINT_FRAME_INCOGNITO:
942 return kTintFrameIncognito;
943 case TINT_FRAME_INCOGNITO_INACTIVE:
944 return kTintFrameIncognitoInactive;
945 case TINT_BUTTONS:
946 return kTintButtons;
947 case TINT_BACKGROUND_TAB:
948 return kTintBackgroundTab;
949 default:
950 NOTREACHED() << "Unknown tint requested";
951 return "";
952 }
953 }
954
955 color_utils::HSL BrowserThemeProvider::GetDefaultTint(int id) const {
956 switch (id) { 366 switch (id) {
957 case TINT_FRAME: 367 case TINT_FRAME:
958 return kDefaultTintFrame; 368 return kDefaultTintFrame;
959 case TINT_FRAME_INACTIVE: 369 case TINT_FRAME_INACTIVE:
960 return kDefaultTintFrameInactive; 370 return kDefaultTintFrameInactive;
961 case TINT_FRAME_INCOGNITO: 371 case TINT_FRAME_INCOGNITO:
962 return kDefaultTintFrameIncognito; 372 return kDefaultTintFrameIncognito;
963 case TINT_FRAME_INCOGNITO_INACTIVE: 373 case TINT_FRAME_INCOGNITO_INACTIVE:
964 return kDefaultTintFrameIncognitoInactive; 374 return kDefaultTintFrameIncognitoInactive;
965 case TINT_BUTTONS: 375 case TINT_BUTTONS:
966 return kDefaultTintButtons; 376 return kDefaultTintButtons;
967 case TINT_BACKGROUND_TAB: 377 case TINT_BACKGROUND_TAB:
968 return kDefaultTintBackgroundTab; 378 return kDefaultTintBackgroundTab;
969 default: 379 default:
970 color_utils::HSL result = {-1, -1, -1}; 380 color_utils::HSL result = {-1, -1, -1};
971 return result; 381 return result;
972 } 382 }
973 } 383 }
974 384
975 const std::string BrowserThemeProvider::GetColorKey(int id) const { 385 // static
976 switch (id) { 386 SkColor BrowserThemeProvider::GetDefaultColor(int id) {
977 case COLOR_FRAME:
978 return kColorFrame;
979 case COLOR_FRAME_INACTIVE:
980 return kColorFrameInactive;
981 case COLOR_FRAME_INCOGNITO:
982 return kColorFrameIncognito;
983 case COLOR_FRAME_INCOGNITO_INACTIVE:
984 return kColorFrameIncognitoInactive;
985 case COLOR_TOOLBAR:
986 return kColorToolbar;
987 case COLOR_TAB_TEXT:
988 return kColorTabText;
989 case COLOR_BACKGROUND_TAB_TEXT:
990 return kColorBackgroundTabText;
991 case COLOR_BOOKMARK_TEXT:
992 return kColorBookmarkText;
993 case COLOR_NTP_BACKGROUND:
994 return kColorNTPBackground;
995 case COLOR_NTP_TEXT:
996 return kColorNTPText;
997 case COLOR_NTP_LINK:
998 return kColorNTPLink;
999 case COLOR_NTP_LINK_UNDERLINE:
1000 return kColorNTPLinkUnderline;
1001 case COLOR_NTP_HEADER:
1002 return kColorNTPHeader;
1003 case COLOR_NTP_SECTION:
1004 return kColorNTPSection;
1005 case COLOR_NTP_SECTION_TEXT:
1006 return kColorNTPSectionText;
1007 case COLOR_NTP_SECTION_LINK:
1008 return kColorNTPSectionLink;
1009 case COLOR_NTP_SECTION_LINK_UNDERLINE:
1010 return kColorNTPSectionLinkUnderline;
1011 case COLOR_CONTROL_BACKGROUND:
1012 return kColorControlBackground;
1013 case COLOR_BUTTON_BACKGROUND:
1014 return kColorButtonBackground;
1015 default:
1016 NOTREACHED() << "Unknown color requested";
1017 return "";
1018 }
1019 }
1020
1021 SkColor BrowserThemeProvider::GetDefaultColor(int id) const {
1022 switch (id) { 387 switch (id) {
1023 case COLOR_FRAME: 388 case COLOR_FRAME:
1024 return kDefaultColorFrame; 389 return kDefaultColorFrame;
1025 case COLOR_FRAME_INACTIVE: 390 case COLOR_FRAME_INACTIVE:
1026 return kDefaultColorFrameInactive; 391 return kDefaultColorFrameInactive;
1027 case COLOR_FRAME_INCOGNITO: 392 case COLOR_FRAME_INCOGNITO:
1028 return kDefaultColorFrameIncognito; 393 return kDefaultColorFrameIncognito;
1029 case COLOR_FRAME_INCOGNITO_INACTIVE: 394 case COLOR_FRAME_INCOGNITO_INACTIVE:
1030 return kDefaultColorFrameIncognitoInactive; 395 return kDefaultColorFrameIncognitoInactive;
1031 case COLOR_TOOLBAR: 396 case COLOR_TOOLBAR:
1032 return kDefaultColorToolbar; 397 return kDefaultColorToolbar;
1033 case COLOR_TAB_TEXT: 398 case COLOR_TAB_TEXT:
1034 return kDefaultColorTabText; 399 return kDefaultColorTabText;
1035 case COLOR_BACKGROUND_TAB_TEXT: 400 case COLOR_BACKGROUND_TAB_TEXT:
1036 return kDefaultColorBackgroundTabText; 401 return kDefaultColorBackgroundTabText;
1037 case COLOR_BOOKMARK_TEXT: 402 case COLOR_BOOKMARK_TEXT:
1038 return kDefaultColorBookmarkText; 403 return kDefaultColorBookmarkText;
1039 case COLOR_NTP_BACKGROUND: 404 case COLOR_NTP_BACKGROUND:
1040 return kDefaultColorNTPBackground; 405 return kDefaultColorNTPBackground;
1041 case COLOR_NTP_TEXT: 406 case COLOR_NTP_TEXT:
1042 return kDefaultColorNTPText; 407 return kDefaultColorNTPText;
1043 case COLOR_NTP_LINK: 408 case COLOR_NTP_LINK:
1044 return kDefaultColorNTPLink; 409 return kDefaultColorNTPLink;
410 case COLOR_NTP_LINK_UNDERLINE:
411 return TintForUnderline(kDefaultColorNTPLink);
1045 case COLOR_NTP_HEADER: 412 case COLOR_NTP_HEADER:
1046 return kDefaultColorNTPHeader; 413 return kDefaultColorNTPHeader;
1047 case COLOR_NTP_SECTION: 414 case COLOR_NTP_SECTION:
1048 return kDefaultColorNTPSection; 415 return kDefaultColorNTPSection;
1049 case COLOR_NTP_SECTION_TEXT: 416 case COLOR_NTP_SECTION_TEXT:
1050 return kDefaultColorNTPSectionText; 417 return kDefaultColorNTPSectionText;
1051 case COLOR_NTP_SECTION_LINK: 418 case COLOR_NTP_SECTION_LINK:
1052 return kDefaultColorNTPSectionLink; 419 return kDefaultColorNTPSectionLink;
420 case COLOR_NTP_SECTION_LINK_UNDERLINE:
421 return TintForUnderline(kDefaultColorNTPSectionLink);
1053 case COLOR_CONTROL_BACKGROUND: 422 case COLOR_CONTROL_BACKGROUND:
1054 return kDefaultColorControlBackground; 423 return kDefaultColorControlBackground;
1055 case COLOR_BUTTON_BACKGROUND: 424 case COLOR_BUTTON_BACKGROUND:
1056 return kDefaultColorButtonBackground; 425 return kDefaultColorButtonBackground;
1057 default: 426 default:
1058 // Return a debugging red color. 427 // Return a debugging red color.
1059 return 0xffff0000; 428 return 0xffff0000;
1060 } 429 }
1061 } 430 }
1062 431
1063 SkBitmap BrowserThemeProvider::TintBitmap(const SkBitmap& bitmap, 432 // static
1064 int hsl_id) const { 433 bool BrowserThemeProvider::GetDefaultDisplayProperty(int id, int* result) {
1065 return SkBitmapOperations::CreateHSLShiftedBitmap(bitmap, GetTint(hsl_id)); 434 switch (id) {
435 case NTP_BACKGROUND_ALIGNMENT:
436 *result = kDefaultDisplayPropertyNTPAlignment;
437 return true;
438 case NTP_BACKGROUND_TILING:
439 *result = kDefaultDisplayPropertyNTPTiling;
440 return true;
441 case NTP_LOGO_ALTERNATE:
442 *result = kDefaultDisplayPropertyNTPInverseLogo;
443 return true;
444 }
445
446 return false;
1066 } 447 }
1067 448
1068 void BrowserThemeProvider::SetImageData(DictionaryValue* images_value, 449 color_utils::HSL BrowserThemeProvider::GetTint(int id) const {
1069 FilePath images_path) { 450 DCHECK(CalledOnValidThread());
1070 images_.clear();
1071 451
1072 if (!images_value) 452 color_utils::HSL hsl;
1073 return; 453 if (theme_pack_.get() && theme_pack_->GetTint(id, &hsl))
454 return hsl;
1074 455
1075 for (DictionaryValue::key_iterator iter(images_value->begin_keys()); 456 return GetDefaultTint(id);
1076 iter != images_value->end_keys(); ++iter) { 457 }
1077 std::string val; 458
1078 if (images_value->GetStringWithoutPathExpansion(*iter, &val)) { 459 void BrowserThemeProvider::ClearAllThemeData() {
1079 int id = ThemeResourcesUtil::GetId(WideToUTF8(*iter)); 460 // Clear our image cache.
1080 if (id != -1) { 461 FreePlatformCaches();
1081 if (!images_path.empty()) { 462 theme_pack_ = NULL;
1082 images_[id] = 463
1083 WideToUTF8(images_path.AppendASCII(val).ToWStringHack()); 464 profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename);
1084 resource_names_[id] = WideToASCII(*iter); 465 SaveThemeID(kDefaultThemeID);
466 }
467
468 void BrowserThemeProvider::LoadThemePrefs() {
469 PrefService* prefs = profile_->GetPrefs();
470
471 std::string current_id = GetThemeID();
472 if (current_id != kDefaultThemeID) {
473 bool loaded_pack = false;
474
475 // If we don't have a file pack, we're updating from an old version.
476 FilePath path = prefs->GetFilePath(prefs::kCurrentThemePackFilename);
477 if (path != FilePath()) {
478 theme_pack_ = BrowserThemePack::BuildFromDataPack(path, current_id);
479 loaded_pack = theme_pack_.get() != NULL;
480 }
481
482 if (loaded_pack) {
483 UserMetrics::RecordAction("Themes.Loaded", profile_);
484 } else {
485 // TODO(erg): We need to pop up a dialog informing the user that their
486 // theme is being migrated.
487 ExtensionsService* service = profile_->GetExtensionsService();
488 if (service) {
489 Extension* extension = service->GetExtensionById(current_id, false);
490 if (extension) {
491 DLOG(ERROR) << "Migrating theme";
492 BuildFromExtension(extension);
493 UserMetrics::RecordAction("Themes.Migrated", profile_);
1085 } else { 494 } else {
1086 images_[id] = val; 495 DLOG(ERROR) << "Theme is mysteriously gone.";
496 ClearAllThemeData();
497 UserMetrics::RecordAction("Themes.Gone", profile_);
1087 } 498 }
1088 } 499 }
1089 } 500 }
1090 } 501 }
1091 } 502 }
1092 503
1093 void BrowserThemeProvider::SetColorData(DictionaryValue* colors_value) { 504 void BrowserThemeProvider::NotifyThemeChanged() {
1094 colors_.clear(); 505 // Redraw!
1095 506 NotificationService* service = NotificationService::current();
1096 if (!colors_value) 507 service->Notify(NotificationType::BROWSER_THEME_CHANGED,
1097 return; 508 Source<BrowserThemeProvider>(this),
1098 509 NotificationService::NoDetails());
1099 for (DictionaryValue::key_iterator iter(colors_value->begin_keys());
1100 iter != colors_value->end_keys(); ++iter) {
1101 ListValue* color_list;
1102 if (colors_value->GetListWithoutPathExpansion(*iter, &color_list) &&
1103 ((color_list->GetSize() == 3) || (color_list->GetSize() == 4))) {
1104 int r, g, b;
1105 color_list->GetInteger(0, &r);
1106 color_list->GetInteger(1, &g);
1107 color_list->GetInteger(2, &b);
1108 if (color_list->GetSize() == 4) {
1109 double alpha;
1110 int alpha_int;
1111 if (color_list->GetReal(3, &alpha)) {
1112 colors_[WideToUTF8(*iter)] =
1113 SkColorSetARGB(static_cast<int>(alpha * 255), r, g, b);
1114 } else if (color_list->GetInteger(3, &alpha_int) &&
1115 (alpha_int == 0 || alpha_int == 1)) {
1116 colors_[WideToUTF8(*iter)] =
1117 SkColorSetARGB(alpha_int ? 255 : 0, r, g, b);
1118 }
1119 } else {
1120 colors_[WideToUTF8(*iter)] = SkColorSetRGB(r, g, b);
1121 }
1122 }
1123 }
1124 } 510 }
1125 511
1126 void BrowserThemeProvider::SetTintData(DictionaryValue* tints_value) { 512 #if defined(OS_WIN)
1127 tints_.clear(); 513 void BrowserThemeProvider::FreePlatformCaches() {
514 // Views (Skia) has no platform image cache to clear.
515 }
516 #endif
1128 517
1129 if (!tints_value) 518 void BrowserThemeProvider::SavePackName(const FilePath& pack_path) {
1130 return; 519 profile_->GetPrefs()->SetFilePath(
1131 520 prefs::kCurrentThemePackFilename, pack_path);
1132 for (DictionaryValue::key_iterator iter(tints_value->begin_keys());
1133 iter != tints_value->end_keys(); ++iter) {
1134 ListValue* tint_list;
1135 if (tints_value->GetListWithoutPathExpansion(*iter, &tint_list) &&
1136 (tint_list->GetSize() == 3)) {
1137 color_utils::HSL hsl = { -1, -1, -1 };
1138 int value = 0;
1139 if (!tint_list->GetReal(0, &hsl.h) && tint_list->GetInteger(0, &value))
1140 hsl.h = value;
1141 if (!tint_list->GetReal(1, &hsl.s) && tint_list->GetInteger(1, &value))
1142 hsl.s = value;
1143 if (!tint_list->GetReal(2, &hsl.l) && tint_list->GetInteger(2, &value))
1144 hsl.l = value;
1145
1146 tints_[WideToUTF8(*iter)] = hsl;
1147 }
1148 }
1149 }
1150
1151 void BrowserThemeProvider::SetDisplayPropertyData(
1152 DictionaryValue* display_properties_value) {
1153 display_properties_.clear();
1154
1155 if (!display_properties_value)
1156 return;
1157
1158 for (DictionaryValue::key_iterator iter(
1159 display_properties_value->begin_keys());
1160 iter != display_properties_value->end_keys(); ++iter) {
1161 // New tab page alignment and background tiling.
1162 if (base::strcasecmp(WideToUTF8(*iter).c_str(),
1163 kDisplayPropertyNTPAlignment) == 0) {
1164 std::string val;
1165 if (display_properties_value->GetStringWithoutPathExpansion(*iter,
1166 &val)) {
1167 display_properties_[kDisplayPropertyNTPAlignment] =
1168 StringToAlignment(val);
1169 }
1170 } else if (base::strcasecmp(WideToUTF8(*iter).c_str(),
1171 kDisplayPropertyNTPTiling) == 0) {
1172 std::string val;
1173 if (display_properties_value->GetStringWithoutPathExpansion(*iter, &val))
1174 display_properties_[kDisplayPropertyNTPTiling] = StringToTiling(val);
1175 }
1176 if (base::strcasecmp(WideToUTF8(*iter).c_str(),
1177 kDisplayPropertyNTPInverseLogo) == 0) {
1178 int val = 0;
1179 if (display_properties_value->GetIntegerWithoutPathExpansion(*iter, &val))
1180 display_properties_[kDisplayPropertyNTPInverseLogo] = val;
1181 }
1182 }
1183 }
1184
1185 SkBitmap* BrowserThemeProvider::GenerateTabBackgroundBitmap(int id) const {
1186 if (id == IDR_THEME_TAB_BACKGROUND ||
1187 id == IDR_THEME_TAB_BACKGROUND_INCOGNITO) {
1188 // The requested image is a background tab. Get a frame to create the
1189 // tab against. As themes don't use the glass frame, we don't have to
1190 // worry about compositing them together, as our default theme provides
1191 // the necessary bitmaps.
1192 if (!process_images_) {
1193 scoped_ptr<SkBitmap> frame;
1194 frame.reset(LoadThemeBitmap(id));
1195 if (frame.get())
1196 themed_image_cache_[id] = new SkBitmap(*frame.get());
1197 } else {
1198 SkBitmap* bg_tab = GenerateTabBackgroundBitmapImpl(id);
1199
1200 if (bg_tab) {
1201 std::string resource_name((id == IDR_THEME_TAB_BACKGROUND) ?
1202 "theme_tab_background" : "theme_tab_background_incognito");
1203 themed_image_cache_[id] = bg_tab;
1204 SaveThemeBitmap(resource_name, id);
1205 return bg_tab;
1206 }
1207 }
1208 }
1209 return NULL;
1210 }
1211
1212 void BrowserThemeProvider::SaveImageData(DictionaryValue* images_value) const {
1213 // Save our images data.
1214 DictionaryValue* pref_images =
1215 profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeImages);
1216 pref_images->Clear();
1217
1218 if (!images_value)
1219 return;
1220
1221 for (DictionaryValue::key_iterator iter(images_value->begin_keys());
1222 iter != images_value->end_keys(); ++iter) {
1223 std::string val;
1224 if (images_value->GetStringWithoutPathExpansion(*iter, &val)) {
1225 int id = ThemeResourcesUtil::GetId(WideToUTF8(*iter));
1226 if (id != -1) {
1227 pref_images->SetWithoutPathExpansion(*iter,
1228 Value::CreateStringValue(images_.find(id)->second));
1229 }
1230 }
1231 }
1232 }
1233
1234 void BrowserThemeProvider::SaveColorData() const {
1235 // Save our color data.
1236 DictionaryValue* pref_colors =
1237 profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeColors);
1238 pref_colors->Clear();
1239
1240 if (colors_.empty())
1241 return;
1242
1243 for (ColorMap::const_iterator iter(colors_.begin()); iter != colors_.end();
1244 ++iter) {
1245 SkColor rgba = iter->second;
1246 ListValue* rgb_list = new ListValue();
1247 rgb_list->Set(0, Value::CreateIntegerValue(SkColorGetR(rgba)));
1248 rgb_list->Set(1, Value::CreateIntegerValue(SkColorGetG(rgba)));
1249 rgb_list->Set(2, Value::CreateIntegerValue(SkColorGetB(rgba)));
1250 if (SkColorGetA(rgba) != 255)
1251 rgb_list->Set(3, Value::CreateRealValue(SkColorGetA(rgba) / 255.0));
1252 pref_colors->Set(UTF8ToWide(iter->first), rgb_list);
1253 }
1254 }
1255
1256 void BrowserThemeProvider::SaveTintData() const {
1257 // Save our tint data.
1258 DictionaryValue* pref_tints =
1259 profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeTints);
1260 pref_tints->Clear();
1261
1262 if (tints_.empty())
1263 return;
1264
1265 for (TintMap::const_iterator iter(tints_.begin()); iter != tints_.end();
1266 ++iter) {
1267 color_utils::HSL hsl = iter->second;
1268 ListValue* hsl_list = new ListValue();
1269 hsl_list->Set(0, Value::CreateRealValue(hsl.h));
1270 hsl_list->Set(1, Value::CreateRealValue(hsl.s));
1271 hsl_list->Set(2, Value::CreateRealValue(hsl.l));
1272 pref_tints->Set(UTF8ToWide(iter->first), hsl_list);
1273 }
1274 }
1275
1276 void BrowserThemeProvider::SaveDisplayPropertyData() const {
1277 // Save our display property data.
1278 DictionaryValue* pref_display_properties =
1279 profile_->GetPrefs()->
1280 GetMutableDictionary(prefs::kCurrentThemeDisplayProperties);
1281 pref_display_properties->Clear();
1282
1283 if (display_properties_.empty())
1284 return;
1285
1286 for (DisplayPropertyMap::const_iterator iter(display_properties_.begin());
1287 iter != display_properties_.end(); ++iter) {
1288 if (base::strcasecmp(iter->first.c_str(),
1289 kDisplayPropertyNTPAlignment) == 0) {
1290 pref_display_properties->SetString(UTF8ToWide(iter->first),
1291 AlignmentToString(iter->second));
1292 } else if (base::strcasecmp(iter->first.c_str(),
1293 kDisplayPropertyNTPTiling) == 0) {
1294 pref_display_properties->SetString(UTF8ToWide(iter->first),
1295 TilingToString(iter->second));
1296 }
1297 if (base::strcasecmp(iter->first.c_str(),
1298 kDisplayPropertyNTPInverseLogo) == 0) {
1299 pref_display_properties->SetInteger(UTF8ToWide(iter->first),
1300 iter->second);
1301 }
1302 }
1303 }
1304
1305 void BrowserThemeProvider::SaveCachedImageData() const {
1306 DictionaryValue* pref_images =
1307 profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeImages);
1308
1309 for (ImagesDiskCache::const_iterator it(images_disk_cache_.begin());
1310 it != images_disk_cache_.end(); ++it) {
1311 std::wstring disk_path = it->first.ToWStringHack();
1312 std::string pref_name = resource_names_.find(it->second)->second;
1313 pref_images->SetString(UTF8ToWide(pref_name), WideToUTF8(disk_path));
1314 }
1315 profile_->GetPrefs()->ScheduleSavePersistentPrefs();
1316 } 521 }
1317 522
1318 void BrowserThemeProvider::SaveThemeID(const std::string& id) { 523 void BrowserThemeProvider::SaveThemeID(const std::string& id) {
1319 profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, UTF8ToWide(id)); 524 profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, UTF8ToWide(id));
1320 } 525 }
1321 526
1322 void BrowserThemeProvider::ClearCaches() { 527 void BrowserThemeProvider::BuildFromExtension(Extension* extension) {
1323 FreePlatformCaches(); 528 scoped_refptr<BrowserThemePack> pack =
1324 STLDeleteValues(&image_cache_); 529 BrowserThemePack::BuildFromExtension(extension);
1325 530 if (!pack.get()) {
1326 // Scope for AutoLock on themed_image_cache. 531 NOTREACHED() << "Could not load theme.";
1327 { 532 return;
1328 AutoLock lock(themed_image_cache_lock_);
1329 STLDeleteValues(&themed_image_cache_);
1330 } 533 }
1331 534
1332 images_disk_cache_.clear(); 535 // Write the packed file to disk.
536 FilePath pack_path = extension->path().Append(chrome::kThemePackFilename);
537 ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
538 new WritePackToDiskTask(pack, pack_path));
539
540 SavePackName(pack_path);
541 theme_pack_ = pack;
1333 } 542 }
1334
1335 void BrowserThemeProvider::WriteImagesToDisk() const {
1336 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
1337 new WriteImagesToDiskTask(images_disk_cache_, themed_image_cache_));
1338 SaveCachedImageData();
1339 }
1340
1341 bool BrowserThemeProvider::ShouldTintFrames() const {
1342 return (HasCustomImage(IDR_THEME_FRAME) ||
1343 tints_.count(GetTintKey(TINT_BACKGROUND_TAB)) ||
1344 tints_.count(GetTintKey(TINT_FRAME)) ||
1345 tints_.count(GetTintKey(TINT_FRAME_INACTIVE)) ||
1346 tints_.count(GetTintKey(TINT_FRAME_INCOGNITO)) ||
1347 tints_.count(GetTintKey(TINT_FRAME_INCOGNITO_INACTIVE)));
1348 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698