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