[Extensions Toolbar Mac] Fix actions bar min size, spacing
[chromium-blink-merge.git] / chrome / browser / ui / webui / help / version_updater_mac.mm
blobd185a873470ec5869772468ec73efc330a87e811
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/webui/help/version_updater_mac.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "chrome/browser/lifetime/application_lifetime.h"
10 #import "chrome/browser/mac/keystone_glue.h"
11 #include "chrome/browser/mac/obsolete_system.h"
12 #include "chrome/grit/chromium_strings.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "ui/base/l10n/l10n_util.h"
16 // KeystoneObserver is a simple notification observer for Keystone status
17 // updates. It will be created and managed by VersionUpdaterMac.
18 @interface KeystoneObserver : NSObject {
19  @private
20   VersionUpdaterMac* versionUpdater_;  // Weak.
23 // Initialize an observer with an updater. The updater owns this object.
24 - (id)initWithUpdater:(VersionUpdaterMac*)updater;
26 // Notification callback, called with the status of keystone operations.
27 - (void)handleStatusNotification:(NSNotification*)notification;
29 @end  // @interface KeystoneObserver
31 @implementation KeystoneObserver
33 - (id)initWithUpdater:(VersionUpdaterMac*)updater {
34   if ((self = [super init])) {
35     versionUpdater_ = updater;
36     NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
37     [center addObserver:self
38                selector:@selector(handleStatusNotification:)
39                    name:kAutoupdateStatusNotification
40                  object:nil];
41   }
42   return self;
45 - (void)dealloc {
46   [[NSNotificationCenter defaultCenter] removeObserver:self];
47   [super dealloc];
50 - (void)handleStatusNotification:(NSNotification*)notification {
51   versionUpdater_->UpdateStatus([notification userInfo]);
54 @end  // @implementation KeystoneObserver
56 VersionUpdater* VersionUpdater::Create(content::BrowserContext* /* context */) {
57   return new VersionUpdaterMac;
60 VersionUpdaterMac::VersionUpdaterMac()
61     : show_promote_button_(false),
62       keystone_observer_([[KeystoneObserver alloc] initWithUpdater:this]) {
65 VersionUpdaterMac::~VersionUpdaterMac() {
68 void VersionUpdaterMac::CheckForUpdate(
69     const StatusCallback& status_callback,
70     const PromoteCallback& promote_callback) {
71   // Copy the callbacks, we will re-use this for the remaining lifetime
72   // of this object.
73   status_callback_ = status_callback;
74   promote_callback_ = promote_callback;
76   KeystoneGlue* keystone_glue = [KeystoneGlue defaultKeystoneGlue];
77   if (keystone_glue && ![keystone_glue isOnReadOnlyFilesystem]) {
78     AutoupdateStatus recent_status = [keystone_glue recentStatus];
79     if ([keystone_glue asyncOperationPending] ||
80         recent_status == kAutoupdateRegisterFailed ||
81         recent_status == kAutoupdateNeedsPromotion) {
82       // If an asynchronous update operation is currently pending, such as a
83       // check for updates or an update installation attempt, set the status
84       // up correspondingly without launching a new update check.
85       //
86       // If registration failed, no other operations make sense, so just go
87       // straight to the error.
88       UpdateStatus([[keystone_glue recentNotification] userInfo]);
89     } else {
90       // Launch a new update check, even if one was already completed, because
91       // a new update may be available or a new update may have been installed
92       // in the background since the last time the Help page was displayed.
93       [keystone_glue checkForUpdate];
95       // Immediately, kAutoupdateStatusNotification will be posted, with status
96       // kAutoupdateChecking.
97       //
98       // Upon completion, kAutoupdateStatusNotification will be posted with a
99       // status indicating the result of the check.
100     }
102     UpdateShowPromoteButton();
103   } else {
104     // There is no glue, or the application is on a read-only filesystem.
105     // Updates and promotions are impossible.
106     status_callback_.Run(DISABLED, 0, base::string16());
107   }
110 void VersionUpdaterMac::PromoteUpdater() const {
111   // Tell Keystone to make software updates available for all users.
112   [[KeystoneGlue defaultKeystoneGlue] promoteTicket];
114   // Immediately, kAutoupdateStatusNotification will be posted, and
115   // UpdateStatus() will be called with status kAutoupdatePromoting.
116   //
117   // Upon completion, kAutoupdateStatusNotification will be posted, and
118   // UpdateStatus() will be called with a status indicating a result of the
119   // installation attempt.
120   //
121   // If the promotion was successful, KeystoneGlue will re-register the ticket
122   // and UpdateStatus() will be called again indicating first that
123   // registration is in progress and subsequently that it has completed.
126 void VersionUpdaterMac::RelaunchBrowser() const {
127   // Tell the Broweser to restart if possible.
128   chrome::AttemptRestart();
131 void VersionUpdaterMac::UpdateStatus(NSDictionary* dictionary) {
132   AutoupdateStatus keystone_status = static_cast<AutoupdateStatus>(
133       [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
135   bool enable_promote_button = true;
136   base::string16 message;
138   Status status;
139   switch (keystone_status) {
140     case kAutoupdateRegistering:
141     case kAutoupdateChecking:
142       status = CHECKING;
143       enable_promote_button = false;
144       break;
146     case kAutoupdateRegistered:
147     case kAutoupdatePromoted:
148       UpdateShowPromoteButton();
149       // Go straight into an update check. Return immediately, this routine
150       // will be re-entered shortly with kAutoupdateChecking.
151       [[KeystoneGlue defaultKeystoneGlue] checkForUpdate];
152       return;
154     case kAutoupdateCurrent:
155       status = UPDATED;
156       break;
158     case kAutoupdateAvailable:
159       // Install the update automatically. Return immediately, this routine
160       // will be re-entered shortly with kAutoupdateInstalling.
161       [[KeystoneGlue defaultKeystoneGlue] installUpdate];
162       return;
164     case kAutoupdateInstalling:
165       status = UPDATING;
166       enable_promote_button = false;
167       break;
169     case kAutoupdateInstalled:
170       status = NEARLY_UPDATED;
171       break;
173     case kAutoupdatePromoting:
174 #if 1
175       // TODO(mark): KSRegistration currently handles the promotion
176       // synchronously, meaning that the main thread's loop doesn't spin,
177       // meaning that animations and other updates to the window won't occur
178       // until KSRegistration is done with promotion. This looks laggy and bad
179       // and probably qualifies as "jank." For now, there just won't be any
180       // visual feedback while promotion is in progress, but it should complete
181       // (or fail) very quickly.  http://b/2290009.
182       return;
183 #endif
184       status = CHECKING;
185       enable_promote_button = false;
186       break;
188     case kAutoupdateRegisterFailed:
189       enable_promote_button = false;
190       // Fall through.
191     case kAutoupdateCheckFailed:
192     case kAutoupdateInstallFailed:
193     case kAutoupdatePromoteFailed:
194       status = FAILED;
195       message = l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR,
196                                               keystone_status);
197       break;
199     case kAutoupdateNeedsPromotion:
200       {
201         status = FAILED;
202         base::string16 product_name =
203             l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
204         message = l10n_util::GetStringFUTF16(IDS_PROMOTE_INFOBAR_TEXT,
205                                              product_name);
206       }
207       break;
209     default:
210       NOTREACHED();
211       return;
212   }
213   if (!status_callback_.is_null())
214     status_callback_.Run(status, 0, message);
216   if (!promote_callback_.is_null()) {
217     PromotionState promotion_state = PROMOTE_HIDDEN;
218     if (show_promote_button_)
219       promotion_state = enable_promote_button ? PROMOTE_ENABLED
220                                               : PROMOTE_DISABLED;
221     promote_callback_.Run(promotion_state);
222   }
225 void VersionUpdaterMac::UpdateShowPromoteButton() {
226   if (ObsoleteSystemMac::Has32BitOnlyCPU() &&
227       ObsoleteSystemMac::Is32BitEndOfTheLine()) {
228     // Promotion is moot upon reaching the end of the line.
229     show_promote_button_ = false;
230     return;
231   }
233   KeystoneGlue* keystone_glue = [KeystoneGlue defaultKeystoneGlue];
234   AutoupdateStatus recent_status = [keystone_glue recentStatus];
235   if (recent_status == kAutoupdateRegistering ||
236       recent_status == kAutoupdateRegisterFailed ||
237       recent_status == kAutoupdatePromoted) {
238     // Promotion isn't possible at this point.
239     show_promote_button_ = false;
240   } else if (recent_status == kAutoupdatePromoting ||
241              recent_status == kAutoupdatePromoteFailed) {
242     // Show promotion UI because the user either just clicked that button or
243     // because the user should be able to click it again.
244     show_promote_button_ = true;
245   } else {
246     // Show the promote button if promotion is a possibility.
247     show_promote_button_ = [keystone_glue wantsPromotion];
248   }