keystone_infobar_delegate.mm revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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/ui/cocoa/keystone_infobar_delegate.h" 6 7#import <AppKit/AppKit.h> 8 9#include <string> 10 11#include "base/bind.h" 12#include "base/command_line.h" 13#include "base/memory/weak_ptr.h" 14#include "base/message_loop.h" 15#include "base/prefs/pref_service.h" 16#include "chrome/browser/first_run/first_run.h" 17#include "chrome/browser/infobars/confirm_infobar_delegate.h" 18#include "chrome/browser/infobars/infobar_service.h" 19#import "chrome/browser/mac/keystone_glue.h" 20#include "chrome/browser/profiles/profile.h" 21#include "chrome/browser/ui/browser.h" 22#include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h" 23#include "chrome/browser/ui/tabs/tab_strip_model.h" 24#include "chrome/common/chrome_switches.h" 25#include "chrome/common/pref_names.h" 26#include "content/public/browser/navigation_details.h" 27#include "content/public/browser/web_contents.h" 28#include "grit/chromium_strings.h" 29#include "grit/generated_resources.h" 30#include "grit/theme_resources.h" 31#include "ui/base/l10n/l10n_util.h" 32#include "ui/base/resource/resource_bundle.h" 33 34class SkBitmap; 35 36namespace { 37 38// KeystonePromotionInfoBarDelegate ------------------------------------------- 39 40class KeystonePromotionInfoBarDelegate : public ConfirmInfoBarDelegate { 41 public: 42 // If there's an active tab, creates a keystone promotion delegate and adds it 43 // to the InfoBarService associated with that tab. 44 static void Create(); 45 46 private: 47 KeystonePromotionInfoBarDelegate(InfoBarService* infobar_service, 48 PrefService* prefs); 49 virtual ~KeystonePromotionInfoBarDelegate(); 50 51 // Sets this info bar to be able to expire. Called a predetermined amount 52 // of time after this object is created. 53 void SetCanExpire() { can_expire_ = true; } 54 55 // ConfirmInfoBarDelegate 56 virtual gfx::Image* GetIcon() const OVERRIDE; 57 virtual string16 GetMessageText() const OVERRIDE; 58 virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE; 59 virtual bool Accept() OVERRIDE; 60 virtual bool Cancel() OVERRIDE; 61 virtual bool ShouldExpireInternal( 62 const content::LoadCommittedDetails& details) const OVERRIDE; 63 64 // The prefs to use. 65 PrefService* prefs_; // weak 66 67 // Whether the info bar should be dismissed on the next navigation. 68 bool can_expire_; 69 70 // Used to delay the expiration of the info bar. 71 base::WeakPtrFactory<KeystonePromotionInfoBarDelegate> weak_ptr_factory_; 72 73 DISALLOW_COPY_AND_ASSIGN(KeystonePromotionInfoBarDelegate); 74}; 75 76// static 77void KeystonePromotionInfoBarDelegate::Create() { 78 Browser* browser = chrome::GetLastActiveBrowser(); 79 if (browser) { 80 content::WebContents* webContents = 81 browser->tab_strip_model()->GetActiveWebContents(); 82 83 if (webContents) { 84 InfoBarService* infobar_service = 85 InfoBarService::FromWebContents(webContents); 86 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( 87 new KeystonePromotionInfoBarDelegate( 88 infobar_service, 89 Profile::FromBrowserContext( 90 webContents->GetBrowserContext())->GetPrefs()))); 91 } 92 } 93} 94 95KeystonePromotionInfoBarDelegate::KeystonePromotionInfoBarDelegate( 96 InfoBarService* infobar_service, 97 PrefService* prefs) 98 : ConfirmInfoBarDelegate(infobar_service), 99 prefs_(prefs), 100 can_expire_(false), 101 weak_ptr_factory_(this) { 102 const base::TimeDelta kCanExpireOnNavigationAfterDelay = 103 base::TimeDelta::FromSeconds(8); 104 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 105 base::Bind(&KeystonePromotionInfoBarDelegate::SetCanExpire, 106 weak_ptr_factory_.GetWeakPtr()), 107 kCanExpireOnNavigationAfterDelay); 108} 109 110KeystonePromotionInfoBarDelegate::~KeystonePromotionInfoBarDelegate() { 111} 112 113gfx::Image* KeystonePromotionInfoBarDelegate::GetIcon() const { 114 return &ResourceBundle::GetSharedInstance().GetNativeImageNamed( 115 IDR_PRODUCT_LOGO_32); 116} 117 118string16 KeystonePromotionInfoBarDelegate::GetMessageText() const { 119 return l10n_util::GetStringFUTF16(IDS_PROMOTE_INFOBAR_TEXT, 120 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 121} 122 123string16 KeystonePromotionInfoBarDelegate::GetButtonLabel( 124 InfoBarButton button) const { 125 return l10n_util::GetStringUTF16((button == BUTTON_OK) ? 126 IDS_PROMOTE_INFOBAR_PROMOTE_BUTTON : IDS_PROMOTE_INFOBAR_DONT_ASK_BUTTON); 127} 128 129bool KeystonePromotionInfoBarDelegate::Accept() { 130 [[KeystoneGlue defaultKeystoneGlue] promoteTicket]; 131 return true; 132} 133 134bool KeystonePromotionInfoBarDelegate::Cancel() { 135 prefs_->SetBoolean(prefs::kShowUpdatePromotionInfoBar, false); 136 return true; 137} 138 139bool KeystonePromotionInfoBarDelegate::ShouldExpireInternal( 140 const content::LoadCommittedDetails& details) const { 141 return can_expire_; 142} 143 144} // namespace 145 146 147// KeystonePromotionInfoBar --------------------------------------------------- 148 149@interface KeystonePromotionInfoBar : NSObject 150- (void)checkAndShowInfoBarForProfile:(Profile*)profile; 151- (void)updateStatus:(NSNotification*)notification; 152- (void)removeObserver; 153@end // @interface KeystonePromotionInfoBar 154 155@implementation KeystonePromotionInfoBar 156 157- (void)dealloc { 158 [self removeObserver]; 159 [super dealloc]; 160} 161 162- (void)checkAndShowInfoBarForProfile:(Profile*)profile { 163 // If this is the first run, the user clicked the "don't ask again" button 164 // at some point in the past, or if the "don't ask about the default 165 // browser" command-line switch is present, bail out. That command-line 166 // switch is recycled here because it's likely that the set of users that 167 // don't want to be nagged about the default browser also don't want to be 168 // nagged about the update check. (Automated testers, I'm thinking of 169 // you...) 170 CommandLine* commandLine = CommandLine::ForCurrentProcess(); 171 if (first_run::IsChromeFirstRun() || 172 !profile->GetPrefs()->GetBoolean(prefs::kShowUpdatePromotionInfoBar) || 173 commandLine->HasSwitch(switches::kNoDefaultBrowserCheck)) { 174 return; 175 } 176 177 // If there is no Keystone glue (maybe because this application isn't 178 // Keystone-enabled) or the application is on a read-only filesystem, 179 // doing anything related to auto-update is pointless. Bail out. 180 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue]; 181 if (!keystoneGlue || [keystoneGlue isOnReadOnlyFilesystem]) { 182 return; 183 } 184 185 // Stay alive as long as needed. This is balanced by a release in 186 // -updateStatus:. 187 [self retain]; 188 189 AutoupdateStatus recentStatus = [keystoneGlue recentStatus]; 190 if (recentStatus == kAutoupdateNone || 191 recentStatus == kAutoupdateRegistering) { 192 NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; 193 [center addObserver:self 194 selector:@selector(updateStatus:) 195 name:kAutoupdateStatusNotification 196 object:nil]; 197 } else { 198 [self updateStatus:[keystoneGlue recentNotification]]; 199 } 200} 201 202- (void)updateStatus:(NSNotification*)notification { 203 NSDictionary* dictionary = [notification userInfo]; 204 AutoupdateStatus status = static_cast<AutoupdateStatus>( 205 [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]); 206 207 if (status == kAutoupdateNone || status == kAutoupdateRegistering) { 208 return; 209 } 210 211 [self removeObserver]; 212 213 if (status != kAutoupdateRegisterFailed && 214 [[KeystoneGlue defaultKeystoneGlue] needsPromotion]) { 215 KeystonePromotionInfoBarDelegate::Create(); 216 } 217 218 [self release]; 219} 220 221- (void)removeObserver { 222 [[NSNotificationCenter defaultCenter] removeObserver:self]; 223} 224 225@end // @implementation KeystonePromotionInfoBar 226 227// static 228void KeystoneInfoBar::PromotionInfoBar(Profile* profile) { 229 KeystonePromotionInfoBar* promotionInfoBar = 230 [[[KeystonePromotionInfoBar alloc] init] autorelease]; 231 232 [promotionInfoBar checkAndShowInfoBarForProfile:profile]; 233} 234