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

Side by Side Diff: chrome/browser/themes/theme_service.cc

Issue 19462009: [DRAFT] Allow a user to revert to their previous theme without closing infobar (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/themes/theme_service.h" 5 #include "chrome/browser/themes/theme_service.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/ref_counted_memory.h" 8 #include "base/memory/ref_counted_memory.h"
9 #include "base/prefs/pref_service.h" 9 #include "base/prefs/pref_service.h"
10 #include "base/sequenced_task_runner.h" 10 #include "base/sequenced_task_runner.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 const char* ThemeService::kDefaultThemeID = ""; 48 const char* ThemeService::kDefaultThemeID = "";
49 49
50 namespace { 50 namespace {
51 51
52 // The default theme if we've gone to the theme gallery and installed the 52 // The default theme if we've gone to the theme gallery and installed the
53 // "Default" theme. We have to detect this case specifically. (By the time we 53 // "Default" theme. We have to detect this case specifically. (By the time we
54 // realize we've installed the default theme, we already have an extension 54 // realize we've installed the default theme, we already have an extension
55 // unpacked on the filesystem.) 55 // unpacked on the filesystem.)
56 const char* kDefaultThemeGalleryID = "hkacjpbfdknhflllbcmjibkdeoafencn"; 56 const char* kDefaultThemeGalleryID = "hkacjpbfdknhflllbcmjibkdeoafencn";
57 57
58 // Wait this many seconds after startup to garbage collect unused themes.
Yoyo Zhou 2013/07/24 21:55:03 Why wait?
59 const int kRemoveUnusedThemesStartupDelay = 30;
60
58 SkColor TintForUnderline(SkColor input) { 61 SkColor TintForUnderline(SkColor input) {
59 return SkColorSetA(input, SkColorGetA(input) / 3); 62 return SkColorSetA(input, SkColorGetA(input) / 3);
60 } 63 }
61 64
62 SkColor IncreaseLightness(SkColor color, double percent) { 65 SkColor IncreaseLightness(SkColor color, double percent) {
63 color_utils::HSL result; 66 color_utils::HSL result;
64 color_utils::SkColorToHSL(color, &result); 67 color_utils::SkColorToHSL(color, &result);
65 result.l += (1 - result.l) * percent; 68 result.l += (1 - result.l) * percent;
66 return color_utils::HSLToSkColor(result, SkColorGetA(color)); 69 return color_utils::HSLToSkColor(result, SkColorGetA(color));
67 } 70 }
68 71
69 // Writes the theme pack to disk on a separate thread. 72 // Writes the theme pack to disk on a separate thread.
70 void WritePackToDiskCallback(BrowserThemePack* pack, 73 void WritePackToDiskCallback(BrowserThemePack* pack,
71 const base::FilePath& path) { 74 const base::FilePath& path) {
72 if (!pack->WriteToDisk(path)) 75 if (!pack->WriteToDisk(path))
73 NOTREACHED() << "Could not write theme pack to disk"; 76 NOTREACHED() << "Could not write theme pack to disk";
74 } 77 }
75 78
76 } // namespace 79 } // namespace
77 80
78 ThemeService::ThemeService() 81 ThemeService::ThemeService()
79 : rb_(ResourceBundle::GetSharedInstance()), 82 : rb_(ResourceBundle::GetSharedInstance()),
80 profile_(NULL), 83 profile_(NULL),
81 ready_(false), 84 ready_(false),
82 number_of_infobars_(0) { 85 number_of_infobars_(0),
86 installed_pending_load_id_(kDefaultThemeID),
87 weak_ptr_factory_(this) {
83 } 88 }
84 89
85 ThemeService::~ThemeService() { 90 ThemeService::~ThemeService() {
86 FreePlatformCaches(); 91 FreePlatformCaches();
87 } 92 }
88 93
89 void ThemeService::Init(Profile* profile) { 94 void ThemeService::Init(Profile* profile) {
90 DCHECK(CalledOnValidThread()); 95 DCHECK(CalledOnValidThread());
91 profile_ = profile; 96 profile_ = profile;
92 97
93 LoadThemePrefs(); 98 LoadThemePrefs();
94 99
95 if (!ready_) { 100 if (!ready_) {
96 registrar_.Add(this, 101 registrar_.Add(this,
97 chrome::NOTIFICATION_EXTENSIONS_READY, 102 chrome::NOTIFICATION_EXTENSIONS_READY,
98 content::Source<Profile>(profile_)); 103 content::Source<Profile>(profile_));
99 } 104 }
100 105
101 theme_syncable_service_.reset(new ThemeSyncableService(profile_, this)); 106 theme_syncable_service_.reset(new ThemeSyncableService(profile_, this));
107
108 registrar_.Add(this,
109 chrome::NOTIFICATION_EXTENSION_INSTALLED,
110 content::Source<Profile>(profile_));
111 registrar_.Add(this,
112 chrome::NOTIFICATION_EXTENSION_LOADED,
113 content::Source<Profile>(profile_));
114 registrar_.Add(this,
115 chrome::NOTIFICATION_EXTENSION_ENABLED,
116 content::Source<Profile>(profile_));
117 registrar_.Add(this,
118 chrome::NOTIFICATION_EXTENSION_UNLOADED,
119 content::Source<Profile>(profile_));
120
121 base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
122 base::Bind(&ThemeService::RemoveUnusedThemes,
123 weak_ptr_factory_.GetWeakPtr(),
124 false),
125 base::TimeDelta::FromSeconds(kRemoveUnusedThemesStartupDelay));
102 } 126 }
103 127
104 gfx::Image ThemeService::GetImageNamed(int id) const { 128 gfx::Image ThemeService::GetImageNamed(int id) const {
105 DCHECK(CalledOnValidThread()); 129 DCHECK(CalledOnValidThread());
106 130
107 // For a managed user, use the special frame instead of the default one. 131 // For a managed user, use the special frame instead of the default one.
108 // TODO(akuegel): Remove this once we have the default managed user theme. 132 // TODO(akuegel): Remove this once we have the default managed user theme.
109 if (IsManagedUser()) { 133 if (IsManagedUser()) {
110 if (id == IDR_THEME_FRAME) 134 if (id == IDR_THEME_FRAME)
111 id = IDR_MANAGED_USER_THEME_FRAME; 135 id = IDR_MANAGED_USER_THEME_FRAME;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 data = theme_pack_->GetRawData(id, scale_factor); 246 data = theme_pack_->GetRawData(id, scale_factor);
223 if (!data) 247 if (!data)
224 data = rb_.LoadDataResourceBytesForScale(id, ui::SCALE_FACTOR_100P); 248 data = rb_.LoadDataResourceBytesForScale(id, ui::SCALE_FACTOR_100P);
225 249
226 return data; 250 return data;
227 } 251 }
228 252
229 void ThemeService::Observe(int type, 253 void ThemeService::Observe(int type,
230 const content::NotificationSource& source, 254 const content::NotificationSource& source,
231 const content::NotificationDetails& details) { 255 const content::NotificationDetails& details) {
232 DCHECK(type == chrome::NOTIFICATION_EXTENSIONS_READY); 256 using content::Details;
233 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY, 257 switch (type) {
234 content::Source<Profile>(profile_)); 258 case chrome::NOTIFICATION_EXTENSIONS_READY:
259 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY,
260 content::Source<Profile>(profile_));
235 261
236 MigrateTheme(); 262 MigrateTheme();
237 set_ready(); 263 set_ready();
238 264
239 // Send notification in case anyone requested data and cached it when the 265 // Send notification in case anyone requested data and cached it when the
240 // theme service was not ready yet. 266 // theme service was not ready yet.
241 NotifyThemeChanged(); 267 NotifyThemeChanged();
268 break;
269 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
270 {
271 Details<const extensions::InstalledExtensionInfo> installed_details(
272 details);
273 // The theme may be initially disabled. Wait till it is loaded (if ever)
Yoyo Zhou 2013/07/24 21:55:03 I don't see why we need to listen for extension in
pkotwicz 2013/07/25 01:25:29 You are right. I should be able to move registerin
274 // to change the current theme.
275 if (installed_details->extension->is_theme())
276 installed_pending_load_id_ = installed_details->extension->id();
277 break;
278 }
279 case chrome::NOTIFICATION_EXTENSION_LOADED:
280 {
281 const Extension* extension = Details<const Extension>(details).ptr();
282 if (extension->is_theme() &&
283 installed_pending_load_id_ != kDefaultThemeID &&
284 installed_pending_load_id_ == extension->id()) {
Yoyo Zhou 2013/07/24 21:55:03 What's the scenario where we load a theme and don'
285 SetTheme(extension);
286 }
287 installed_pending_load_id_ = kDefaultThemeID;
288 }
289 case chrome::NOTIFICATION_EXTENSION_ENABLED:
290 {
291 const Extension* extension = Details<const Extension>(details).ptr();
292 if (extension->is_theme())
293 SetTheme(extension);
294 break;
295 }
296 case chrome::NOTIFICATION_EXTENSION_UNLOADED:
297 {
298 Details<const extensions::UnloadedExtensionInfo> unloaded_details(
299 details);
300 if (unloaded_details->reason != extension_misc::UNLOAD_REASON_UPDATE &&
301 unloaded_details->extension->is_theme() &&
302 unloaded_details->extension->id() == GetThemeID()) {
303 UseDefaultTheme();
304 }
305 break;
306 }
307 }
242 } 308 }
243 309
244 void ThemeService::SetTheme(const Extension* extension) { 310 void ThemeService::SetTheme(const Extension* extension) {
311 DCHECK(extension->is_theme());
312 ExtensionService* service =
313 extensions::ExtensionSystem::Get(profile_)->extension_service();
314 if (!service->IsExtensionEnabled(extension->id())) {
315 // |extension| is disabled when reverting to the previous theme via an
316 // infobar.
317 service->EnableExtension(extension->id());
318 // Enabling the extension will call back to SetTheme().
319 return;
320 }
321
322 std::string previous_theme_id = GetThemeID();
323
245 // Clear our image cache. 324 // Clear our image cache.
246 FreePlatformCaches(); 325 FreePlatformCaches();
247 326
248 DCHECK(extension);
249 DCHECK(extension->is_theme());
250 if (DCHECK_IS_ON()) {
251 ExtensionService* service =
252 extensions::ExtensionSystem::Get(profile_)->extension_service();
253 DCHECK(service);
254 DCHECK(service->GetExtensionById(extension->id(), false));
255 }
256
257 BuildFromExtension(extension); 327 BuildFromExtension(extension);
258 SaveThemeID(extension->id()); 328 SaveThemeID(extension->id());
259 329
260 NotifyThemeChanged(); 330 NotifyThemeChanged();
261 content::RecordAction(UserMetricsAction("Themes_Installed")); 331 content::RecordAction(UserMetricsAction("Themes_Installed"));
332
333 if (previous_theme_id != kDefaultThemeID &&
334 previous_theme_id != extension->id()) {
335 // Disable the old theme.
336 service->DisableExtension(previous_theme_id,
337 extensions::Extension::DISABLE_USER_ACTION);
338 }
262 } 339 }
263 340
264 void ThemeService::RemoveUnusedThemes() { 341 void ThemeService::RemoveUnusedThemes(bool ignore_infobars) {
342 if (!ignore_infobars && number_of_infobars_ != 0)
343 return;
265 if (!profile_) 344 if (!profile_)
266 return; 345 return;
267 ExtensionService* service = profile_->GetExtensionService(); 346 ExtensionService* service = profile_->GetExtensionService();
268 if (!service) 347 if (!service)
269 return; 348 return;
270 std::string current_theme = GetThemeID(); 349 std::string current_theme = GetThemeID();
271 std::vector<std::string> remove_list; 350 std::vector<std::string> remove_list;
272 const ExtensionSet* extensions = service->extensions(); 351 const ExtensionSet* extensions = service->extensions();
273 for (ExtensionSet::const_iterator it = extensions->begin(); 352 for (ExtensionSet::const_iterator it = extensions->begin();
274 it != extensions->end(); ++it) { 353 it != extensions->end(); ++it) {
275 if ((*it)->is_theme() && (*it)->id() != current_theme) { 354 if ((*it)->is_theme() && (*it)->id() != current_theme) {
276 remove_list.push_back((*it)->id()); 355 remove_list.push_back((*it)->id());
277 } 356 }
278 } 357 }
358 extensions = service->disabled_extensions();
359 for (ExtensionSet::const_iterator it = extensions->begin();
360 it != extensions->end(); ++it) {
361 if ((*it)->is_theme() && (*it)->id() != current_theme) {
362 remove_list.push_back((*it)->id());
363 }
364 }
279 for (size_t i = 0; i < remove_list.size(); ++i) 365 for (size_t i = 0; i < remove_list.size(); ++i)
280 service->UninstallExtension(remove_list[i], false, NULL); 366 service->UninstallExtension(remove_list[i], false, NULL);
281 } 367 }
282 368
283 void ThemeService::UseDefaultTheme() { 369 void ThemeService::UseDefaultTheme() {
284 ClearAllThemeData(); 370 ClearAllThemeData();
285 NotifyThemeChanged(); 371 NotifyThemeChanged();
286 content::RecordAction(UserMetricsAction("Themes_Reset")); 372 content::RecordAction(UserMetricsAction("Themes_Reset"));
287 } 373 }
288 374
(...skipping 26 matching lines...) Expand all
315 } 401 }
316 402
317 void ThemeService::ClearAllThemeData() { 403 void ThemeService::ClearAllThemeData() {
318 // Clear our image cache. 404 // Clear our image cache.
319 FreePlatformCaches(); 405 FreePlatformCaches();
320 theme_pack_ = NULL; 406 theme_pack_ = NULL;
321 407
322 profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename); 408 profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename);
323 SaveThemeID(kDefaultThemeID); 409 SaveThemeID(kDefaultThemeID);
324 410
325 RemoveUnusedThemes(); 411 // There should be no more infobars. This may not be the case because of
412 // http://crbug.com/62154
413 base::MessageLoop::current()->PostTask(FROM_HERE,
414 base::Bind(&ThemeService::RemoveUnusedThemes,
415 weak_ptr_factory_.GetWeakPtr(),
416 true));
326 } 417 }
327 418
328 void ThemeService::LoadThemePrefs() { 419 void ThemeService::LoadThemePrefs() {
329 PrefService* prefs = profile_->GetPrefs(); 420 PrefService* prefs = profile_->GetPrefs();
330 421
331 std::string current_id = GetThemeID(); 422 std::string current_id = GetThemeID();
332 if (current_id == kDefaultThemeID) { 423 if (current_id == kDefaultThemeID) {
333 set_ready(); 424 set_ready();
334 return; 425 return;
335 } 426 }
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 } 532 }
442 533
443 void ThemeService::OnInfobarDisplayed() { 534 void ThemeService::OnInfobarDisplayed() {
444 number_of_infobars_++; 535 number_of_infobars_++;
445 } 536 }
446 537
447 void ThemeService::OnInfobarDestroyed() { 538 void ThemeService::OnInfobarDestroyed() {
448 number_of_infobars_--; 539 number_of_infobars_--;
449 540
450 if (number_of_infobars_ == 0) 541 if (number_of_infobars_ == 0)
451 RemoveUnusedThemes(); 542 RemoveUnusedThemes(false);
452 } 543 }
453 544
454 ThemeSyncableService* ThemeService::GetThemeSyncableService() const { 545 ThemeSyncableService* ThemeService::GetThemeSyncableService() const {
455 return theme_syncable_service_.get(); 546 return theme_syncable_service_.get();
456 } 547 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698