keystone_infobar.mm revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
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 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/cocoa/keystone_infobar.h" 6 7#import <AppKit/AppKit.h> 8 9#include <string> 10 11#include "app/l10n_util.h" 12#include "app/resource_bundle.h" 13#include "base/command_line.h" 14#include "base/message_loop.h" 15#include "base/task.h" 16#include "chrome/browser/first_run/first_run.h" 17#include "chrome/browser/prefs/pref_service.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/tab_contents/infobar_delegate.h" 20#include "chrome/browser/tab_contents/navigation_controller.h" 21#include "chrome/browser/tab_contents/tab_contents.h" 22#include "chrome/browser/ui/browser.h" 23#include "chrome/browser/ui/browser_list.h" 24#import "chrome/browser/ui/cocoa/keystone_glue.h" 25#include "chrome/common/chrome_switches.h" 26#include "chrome/common/pref_names.h" 27#include "grit/chromium_strings.h" 28#include "grit/generated_resources.h" 29#include "grit/theme_resources.h" 30 31class SkBitmap; 32 33namespace { 34 35class KeystonePromotionInfoBarDelegate : public ConfirmInfoBarDelegate { 36 public: 37 KeystonePromotionInfoBarDelegate(TabContents* tab_contents) 38 : ConfirmInfoBarDelegate(tab_contents), 39 profile_(tab_contents->profile()), 40 can_expire_(false), 41 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 42 const int kCanExpireOnNavigationAfterMilliseconds = 8 * 1000; 43 MessageLoop::current()->PostDelayedTask( 44 FROM_HERE, 45 method_factory_.NewRunnableMethod( 46 &KeystonePromotionInfoBarDelegate::SetCanExpire), 47 kCanExpireOnNavigationAfterMilliseconds); 48 } 49 50 virtual ~KeystonePromotionInfoBarDelegate() {} 51 52 // Inherited from InfoBarDelegate and overridden. 53 54 virtual bool ShouldExpire( 55 const NavigationController::LoadCommittedDetails& details) { 56 return can_expire_; 57 } 58 59 virtual void InfoBarClosed() { 60 delete this; 61 } 62 63 // Inherited from AlertInfoBarDelegate and overridden. 64 65 virtual string16 GetMessageText() const { 66 return l10n_util::GetStringFUTF16(IDS_PROMOTE_INFOBAR_TEXT, 67 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 68 } 69 70 virtual SkBitmap* GetIcon() const { 71 return ResourceBundle::GetSharedInstance().GetBitmapNamed( 72 IDR_PRODUCT_ICON_32); 73 } 74 75 // Inherited from ConfirmInfoBarDelegate and overridden. 76 77 virtual int GetButtons() const { 78 return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT; 79 } 80 81 virtual string16 GetButtonLabel(InfoBarButton button) const { 82 return button == BUTTON_OK ? 83 l10n_util::GetStringUTF16(IDS_PROMOTE_INFOBAR_PROMOTE_BUTTON) : 84 l10n_util::GetStringUTF16(IDS_PROMOTE_INFOBAR_DONT_ASK_BUTTON); 85 } 86 87 virtual bool Accept() { 88 [[KeystoneGlue defaultKeystoneGlue] promoteTicket]; 89 return true; 90 } 91 92 virtual bool Cancel() { 93 profile_->GetPrefs()->SetBoolean(prefs::kShowUpdatePromotionInfoBar, false); 94 return true; 95 } 96 97 private: 98 // Sets this info bar to be able to expire. Called a predetermined amount 99 // of time after this object is created. 100 void SetCanExpire() { 101 can_expire_ = true; 102 } 103 104 // The TabContents' profile. 105 Profile* profile_; // weak 106 107 // Whether the info bar should be dismissed on the next navigation. 108 bool can_expire_; 109 110 // Used to delay the expiration of the info bar. 111 ScopedRunnableMethodFactory<KeystonePromotionInfoBarDelegate> method_factory_; 112 113 DISALLOW_COPY_AND_ASSIGN(KeystonePromotionInfoBarDelegate); 114}; 115 116} // namespace 117 118@interface KeystonePromotionInfoBar : NSObject 119- (void)checkAndShowInfoBarForProfile:(Profile*)profile; 120- (void)updateStatus:(NSNotification*)notification; 121- (void)removeObserver; 122@end // @interface KeystonePromotionInfoBar 123 124@implementation KeystonePromotionInfoBar 125 126- (void)dealloc { 127 [self removeObserver]; 128 [super dealloc]; 129} 130 131- (void)checkAndShowInfoBarForProfile:(Profile*)profile { 132 // If this is the first run, the user clicked the "don't ask again" button 133 // at some point in the past, or if the "don't ask about the default 134 // browser" command-line switch is present, bail out. That command-line 135 // switch is recycled here because it's likely that the set of users that 136 // don't want to be nagged about the default browser also don't want to be 137 // nagged about the update check. (Automated testers, I'm thinking of 138 // you...) 139 CommandLine* commandLine = CommandLine::ForCurrentProcess(); 140 if (FirstRun::IsChromeFirstRun() || 141 !profile->GetPrefs()->GetBoolean(prefs::kShowUpdatePromotionInfoBar) || 142 commandLine->HasSwitch(switches::kNoDefaultBrowserCheck)) { 143 return; 144 } 145 146 // If there is no Keystone glue (maybe because this application isn't 147 // Keystone-enabled) or the application is on a read-only filesystem, 148 // doing anything related to auto-update is pointless. Bail out. 149 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue]; 150 if (!keystoneGlue || [keystoneGlue isOnReadOnlyFilesystem]) { 151 return; 152 } 153 154 // Stay alive as long as needed. This is balanced by a release in 155 // -updateStatus:. 156 [self retain]; 157 158 AutoupdateStatus recentStatus = [keystoneGlue recentStatus]; 159 if (recentStatus == kAutoupdateNone || 160 recentStatus == kAutoupdateRegistering) { 161 NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; 162 [center addObserver:self 163 selector:@selector(updateStatus:) 164 name:kAutoupdateStatusNotification 165 object:nil]; 166 } else { 167 [self updateStatus:[keystoneGlue recentNotification]]; 168 } 169} 170 171- (void)updateStatus:(NSNotification*)notification { 172 NSDictionary* dictionary = [notification userInfo]; 173 AutoupdateStatus status = static_cast<AutoupdateStatus>( 174 [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]); 175 176 if (status == kAutoupdateNone || status == kAutoupdateRegistering) { 177 return; 178 } 179 180 [self removeObserver]; 181 182 if (status != kAutoupdateRegisterFailed && 183 [[KeystoneGlue defaultKeystoneGlue] needsPromotion]) { 184 Browser* browser = BrowserList::GetLastActive(); 185 if (browser) { 186 TabContents* tabContents = browser->GetSelectedTabContents(); 187 188 // Only show if no other info bars are showing, because that's how the 189 // default browser info bar works. 190 if (tabContents && tabContents->infobar_delegate_count() == 0) { 191 tabContents->AddInfoBar( 192 new KeystonePromotionInfoBarDelegate(tabContents)); 193 } 194 } 195 } 196 197 [self release]; 198} 199 200- (void)removeObserver { 201 [[NSNotificationCenter defaultCenter] removeObserver:self]; 202} 203 204@end // @implementation KeystonePromotionInfoBar 205 206// static 207void KeystoneInfoBar::PromotionInfoBar(Profile* profile) { 208 KeystonePromotionInfoBar* promotionInfoBar = 209 [[[KeystonePromotionInfoBar alloc] init] autorelease]; 210 211 [promotionInfoBar checkAndShowInfoBarForProfile:profile]; 212} 213