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.
5 #include "chrome/browser/ui/cocoa/keystone_infobar_delegate.h"
7 #import <AppKit/AppKit.h>
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/prefs/pref_service.h"
16 #include "chrome/browser/first_run/first_run.h"
17 #include "chrome/browser/infobars/infobar_service.h"
18 #import "chrome/browser/mac/keystone_glue.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/grit/chromium_strings.h"
26 #include "chrome/grit/generated_resources.h"
27 #include "components/infobars/core/confirm_infobar_delegate.h"
28 #include "components/infobars/core/infobar.h"
29 #include "content/public/browser/web_contents.h"
30 #include "grit/theme_resources.h"
31 #include "ui/base/l10n/l10n_util.h"
37 // KeystonePromotionInfoBarDelegate -------------------------------------------
39 class KeystonePromotionInfoBarDelegate : public ConfirmInfoBarDelegate {
41 // If there's an active tab, creates a keystone promotion delegate and adds it
42 // to the InfoBarService associated with that tab.
46 explicit KeystonePromotionInfoBarDelegate(PrefService* prefs);
47 ~KeystonePromotionInfoBarDelegate() override;
49 // Sets this info bar to be able to expire. Called a predetermined amount
50 // of time after this object is created.
51 void SetCanExpire() { can_expire_ = true; }
53 // ConfirmInfoBarDelegate
54 int GetIconId() const override;
55 bool ShouldExpire(const NavigationDetails& details) const override;
56 base::string16 GetMessageText() const override;
57 base::string16 GetButtonLabel(InfoBarButton button) const override;
58 bool Accept() override;
59 bool Cancel() override;
62 PrefService* prefs_; // weak
64 // Whether the info bar should be dismissed on the next navigation.
67 // Used to delay the expiration of the info bar.
68 base::WeakPtrFactory<KeystonePromotionInfoBarDelegate> weak_ptr_factory_;
70 DISALLOW_COPY_AND_ASSIGN(KeystonePromotionInfoBarDelegate);
74 void KeystonePromotionInfoBarDelegate::Create() {
75 Browser* browser = chrome::GetLastActiveBrowser();
78 content::WebContents* webContents =
79 browser->tab_strip_model()->GetActiveWebContents();
82 InfoBarService* infobar_service =
83 InfoBarService::FromWebContents(webContents);
84 infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar(
85 scoped_ptr<ConfirmInfoBarDelegate>(new KeystonePromotionInfoBarDelegate(
86 Profile::FromBrowserContext(
87 webContents->GetBrowserContext())->GetPrefs()))));
90 KeystonePromotionInfoBarDelegate::KeystonePromotionInfoBarDelegate(
92 : ConfirmInfoBarDelegate(),
95 weak_ptr_factory_(this) {
96 const base::TimeDelta kCanExpireOnNavigationAfterDelay =
97 base::TimeDelta::FromSeconds(8);
98 base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
99 base::Bind(&KeystonePromotionInfoBarDelegate::SetCanExpire,
100 weak_ptr_factory_.GetWeakPtr()),
101 kCanExpireOnNavigationAfterDelay);
104 KeystonePromotionInfoBarDelegate::~KeystonePromotionInfoBarDelegate() {
107 int KeystonePromotionInfoBarDelegate::GetIconId() const {
108 return IDR_PRODUCT_LOGO_32;
111 bool KeystonePromotionInfoBarDelegate::ShouldExpire(
112 const NavigationDetails& details) const {
113 return can_expire_ && ConfirmInfoBarDelegate::ShouldExpire(details);
116 base::string16 KeystonePromotionInfoBarDelegate::GetMessageText() const {
117 return l10n_util::GetStringFUTF16(IDS_PROMOTE_INFOBAR_TEXT,
118 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
121 base::string16 KeystonePromotionInfoBarDelegate::GetButtonLabel(
122 InfoBarButton button) const {
123 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
124 IDS_PROMOTE_INFOBAR_PROMOTE_BUTTON : IDS_PROMOTE_INFOBAR_DONT_ASK_BUTTON);
127 bool KeystonePromotionInfoBarDelegate::Accept() {
128 [[KeystoneGlue defaultKeystoneGlue] promoteTicket];
132 bool KeystonePromotionInfoBarDelegate::Cancel() {
133 prefs_->SetBoolean(prefs::kShowUpdatePromotionInfoBar, false);
140 // KeystonePromotionInfoBar ---------------------------------------------------
142 @interface KeystonePromotionInfoBar : NSObject
143 - (void)checkAndShowInfoBarForProfile:(Profile*)profile;
144 - (void)updateStatus:(NSNotification*)notification;
145 - (void)removeObserver;
146 @end // @interface KeystonePromotionInfoBar
148 @implementation KeystonePromotionInfoBar
151 [self removeObserver];
155 - (void)checkAndShowInfoBarForProfile:(Profile*)profile {
156 // If this is the first run, the user clicked the "don't ask again" button
157 // at some point in the past, or if the "don't ask about the default
158 // browser" command-line switch is present, bail out. That command-line
159 // switch is recycled here because it's likely that the set of users that
160 // don't want to be nagged about the default browser also don't want to be
161 // nagged about the update check. (Automated testers, I'm thinking of
163 base::CommandLine* commandLine = base::CommandLine::ForCurrentProcess();
164 if (first_run::IsChromeFirstRun() ||
165 !profile->GetPrefs()->GetBoolean(prefs::kShowUpdatePromotionInfoBar) ||
166 commandLine->HasSwitch(switches::kNoDefaultBrowserCheck)) {
170 // If there is no Keystone glue (maybe because this application isn't
171 // Keystone-enabled) or the application is on a read-only filesystem,
172 // doing anything related to auto-update is pointless. Bail out.
173 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue];
174 if (!keystoneGlue || [keystoneGlue isOnReadOnlyFilesystem]) {
178 // Stay alive as long as needed. This is balanced by a release in
182 AutoupdateStatus recentStatus = [keystoneGlue recentStatus];
183 if (recentStatus == kAutoupdateNone ||
184 recentStatus == kAutoupdateRegistering) {
185 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
186 [center addObserver:self
187 selector:@selector(updateStatus:)
188 name:kAutoupdateStatusNotification
191 [self updateStatus:[keystoneGlue recentNotification]];
195 - (void)updateStatus:(NSNotification*)notification {
196 NSDictionary* dictionary = [notification userInfo];
197 AutoupdateStatus status = static_cast<AutoupdateStatus>(
198 [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
200 if (status == kAutoupdateNone || status == kAutoupdateRegistering) {
204 [self removeObserver];
206 if (status != kAutoupdateRegisterFailed &&
207 [[KeystoneGlue defaultKeystoneGlue] needsPromotion]) {
208 KeystonePromotionInfoBarDelegate::Create();
214 - (void)removeObserver {
215 [[NSNotificationCenter defaultCenter] removeObserver:self];
218 @end // @implementation KeystonePromotionInfoBar
221 void KeystoneInfoBar::PromotionInfoBar(Profile* profile) {
222 KeystonePromotionInfoBar* promotionInfoBar =
223 [[[KeystonePromotionInfoBar alloc] init] autorelease];
225 [promotionInfoBar checkAndShowInfoBarForProfile:profile];