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