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 #include "chrome/browser/extensions/theme_installed_infobar_delegate.h" 6 7 #include <string> 8 9 #include "base/strings/utf_string_conversions.h" 10 #include "chrome/browser/chrome_notification_types.h" 11 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/infobars/infobar_service.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/themes/theme_service.h" 15 #include "chrome/browser/themes/theme_service_factory.h" 16 #include "chrome/browser/ui/browser_finder.h" 17 #include "chrome/browser/ui/tabs/tab_strip_model.h" 18 #include "components/infobars/core/infobar.h" 19 #include "content/public/browser/notification_source.h" 20 #include "extensions/common/extension.h" 21 #include "grit/generated_resources.h" 22 #include "grit/theme_resources.h" 23 #include "ui/base/l10n/l10n_util.h" 24 25 26 // static 27 void ThemeInstalledInfoBarDelegate::Create( 28 const extensions::Extension* new_theme, 29 Profile* profile, 30 const std::string& previous_theme_id, 31 bool previous_using_system_theme) { 32 DCHECK(new_theme); 33 if (!new_theme->is_theme()) 34 return; 35 36 // Create the new infobar. 37 // FindTabbedBrowser() is called with |match_original_profiles| true because a 38 // theme install in either a normal or incognito window for a profile affects 39 // all normal and incognito windows for that profile. 40 Browser* browser = 41 chrome::FindTabbedBrowser(profile, true, chrome::GetActiveDesktop()); 42 if (!browser) 43 return; 44 content::WebContents* web_contents = 45 browser->tab_strip_model()->GetActiveWebContents(); 46 if (!web_contents) 47 return; 48 InfoBarService* infobar_service = 49 InfoBarService::FromWebContents(web_contents); 50 ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile); 51 scoped_ptr<infobars::InfoBar> new_infobar( 52 ConfirmInfoBarDelegate::CreateInfoBar(scoped_ptr<ConfirmInfoBarDelegate>( 53 new ThemeInstalledInfoBarDelegate( 54 profile->GetExtensionService(), theme_service, new_theme, 55 previous_theme_id, previous_using_system_theme)))); 56 57 // If there's a previous theme infobar, just replace that instead of adding a 58 // new one. 59 for (size_t i = 0; i < infobar_service->infobar_count(); ++i) { 60 infobars::InfoBar* old_infobar = infobar_service->infobar_at(i); 61 ThemeInstalledInfoBarDelegate* theme_infobar = 62 old_infobar->delegate()->AsThemePreviewInfobarDelegate(); 63 if (theme_infobar) { 64 // If the user installed the same theme twice, ignore the second install 65 // and keep the first install info bar, so that they can easily undo to 66 // get back the previous theme. 67 if (theme_infobar->theme_id_ != new_theme->id()) { 68 infobar_service->ReplaceInfoBar(old_infobar, new_infobar.Pass()); 69 theme_service->OnInfobarDisplayed(); 70 } 71 return; 72 } 73 } 74 75 // No previous theme infobar, so add this. 76 infobar_service->AddInfoBar(new_infobar.Pass()); 77 theme_service->OnInfobarDisplayed(); 78 } 79 80 ThemeInstalledInfoBarDelegate::ThemeInstalledInfoBarDelegate( 81 ExtensionService* extension_service, 82 ThemeService* theme_service, 83 const extensions::Extension* new_theme, 84 const std::string& previous_theme_id, 85 bool previous_using_system_theme) 86 : ConfirmInfoBarDelegate(), 87 extension_service_(extension_service), 88 theme_service_(theme_service), 89 name_(new_theme->name()), 90 theme_id_(new_theme->id()), 91 previous_theme_id_(previous_theme_id), 92 previous_using_system_theme_(previous_using_system_theme) { 93 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 94 content::Source<ThemeService>(theme_service_)); 95 } 96 97 ThemeInstalledInfoBarDelegate::~ThemeInstalledInfoBarDelegate() { 98 // We don't want any notifications while we're running our destructor. 99 registrar_.RemoveAll(); 100 101 theme_service_->OnInfobarDestroyed(); 102 } 103 104 int ThemeInstalledInfoBarDelegate::GetIconID() const { 105 // TODO(aa): Reply with the theme's icon, but this requires reading it 106 // asynchronously from disk. 107 return IDR_INFOBAR_THEME; 108 } 109 110 infobars::InfoBarDelegate::Type ThemeInstalledInfoBarDelegate::GetInfoBarType() 111 const { 112 return PAGE_ACTION_TYPE; 113 } 114 115 ThemeInstalledInfoBarDelegate* 116 ThemeInstalledInfoBarDelegate::AsThemePreviewInfobarDelegate() { 117 return this; 118 } 119 120 base::string16 ThemeInstalledInfoBarDelegate::GetMessageText() const { 121 return l10n_util::GetStringFUTF16(IDS_THEME_INSTALL_INFOBAR_LABEL, 122 base::UTF8ToUTF16(name_)); 123 } 124 125 int ThemeInstalledInfoBarDelegate::GetButtons() const { 126 return BUTTON_CANCEL; 127 } 128 129 base::string16 ThemeInstalledInfoBarDelegate::GetButtonLabel( 130 InfoBarButton button) const { 131 DCHECK_EQ(BUTTON_CANCEL, button); 132 return l10n_util::GetStringUTF16(IDS_THEME_INSTALL_INFOBAR_UNDO_BUTTON); 133 } 134 135 bool ThemeInstalledInfoBarDelegate::Cancel() { 136 if (!previous_theme_id_.empty()) { 137 const extensions::Extension* previous_theme = 138 extension_service_->GetExtensionById(previous_theme_id_, true); 139 if (previous_theme) { 140 theme_service_->SetTheme(previous_theme); 141 return false; // The theme change will close us. 142 } 143 } 144 145 if (previous_using_system_theme_) 146 theme_service_->UseSystemTheme(); 147 else 148 theme_service_->UseDefaultTheme(); 149 return false; // The theme change will close us. 150 } 151 152 void ThemeInstalledInfoBarDelegate::Observe( 153 int type, 154 const content::NotificationSource& source, 155 const content::NotificationDetails& details) { 156 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type); 157 // If the new theme is different from what this info bar is associated with, 158 // close this info bar since it is no longer relevant. 159 if (theme_id_ != theme_service_->GetThemeID()) 160 infobar()->RemoveSelf(); 161 } 162