Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(712)

Side by Side Diff: chrome/browser/cocoa/about_window_controller.mm

Issue 437053: In-application Keystone ticket promotion (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/cocoa/about_window_controller.h"
6
5 #include "app/l10n_util_mac.h" 7 #include "app/l10n_util_mac.h"
6 #include "app/resource_bundle.h" 8 #include "app/resource_bundle.h"
7 #include "base/logging.h" 9 #include "base/logging.h"
8 #include "base/mac_util.h" 10 #include "base/mac_util.h"
9 #include "base/string_util.h" 11 #include "base/string_util.h"
10 #include "base/sys_string_conversions.h" 12 #include "base/sys_string_conversions.h"
11 #import "chrome/app/keystone_glue.h"
12 #include "chrome/browser/browser_list.h" 13 #include "chrome/browser/browser_list.h"
13 #import "chrome/browser/cocoa/about_window_controller.h"
14 #import "chrome/browser/cocoa/background_tile_view.h" 14 #import "chrome/browser/cocoa/background_tile_view.h"
15 #import "chrome/browser/cocoa/keystone_glue.h"
15 #include "chrome/browser/cocoa/restart_browser.h" 16 #include "chrome/browser/cocoa/restart_browser.h"
16 #include "grit/chromium_strings.h" 17 #include "grit/chromium_strings.h"
17 #include "grit/generated_resources.h" 18 #include "grit/generated_resources.h"
18 #include "grit/theme_resources.h" 19 #include "grit/theme_resources.h"
19 #include "grit/locale_settings.h" 20 #include "grit/locale_settings.h"
20 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" 21 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
21 22
22 namespace { 23 namespace {
23 24
24 void AttributedStringAppendString(NSMutableAttributedString* attr_str, 25 void AttributedStringAppendString(NSMutableAttributedString* attr_str,
(...skipping 27 matching lines...) Expand all
52 range:range]; 53 range:range];
53 } 54 }
54 55
55 } // namespace 56 } // namespace
56 57
57 @interface AboutWindowController(Private) 58 @interface AboutWindowController(Private)
58 59
59 // Launches a check for available updates. 60 // Launches a check for available updates.
60 - (void)checkForUpdate; 61 - (void)checkForUpdate;
61 62
63 // Turns the update and promotion blocks on and off as needed based on whether
64 // updates are possible and promotion is desired or required.
65 - (void)adjustUpdateUIVisibility;
66
67 // Maintains the update and promotion block visibility and window sizing.
68 // This uses bool instead of BOOL for the convenience of the internal
69 // implementation.
70 - (void)setAllowsUpdate:(bool)update allowsPromotion:(bool)promotion;
71
62 // Notification callback, called with the status of asynchronous 72 // Notification callback, called with the status of asynchronous
63 // -checkForUpdate and -updateNow: operations. 73 // -checkForUpdate and -updateNow: operations.
64 - (void)updateStatus:(NSNotification*)notification; 74 - (void)updateStatus:(NSNotification*)notification;
65 75
66 // These methods maintain the image (or throbber) and text displayed regarding 76 // These methods maintain the image (or throbber) and text displayed regarding
67 // update status. -setUpdateThrobberMessage: starts a progress throbber and 77 // update status. -setUpdateThrobberMessage: starts a progress throbber and
68 // sets the text. -setUpdateImage:message: displays an image and sets the 78 // sets the text. -setUpdateImage:message: displays an image and sets the
69 // text. 79 // text.
70 - (void)setUpdateThrobberMessage:(NSString*)message; 80 - (void)setUpdateThrobberMessage:(NSString*)message;
71 - (void)setUpdateImage:(int)imageID message:(NSString*)message; 81 - (void)setUpdateImage:(int)imageID message:(NSString*)message;
(...skipping 27 matching lines...) Expand all
99 } 109 }
100 110
101 - (void)dealloc { 111 - (void)dealloc {
102 [[NSNotificationCenter defaultCenter] removeObserver:self]; 112 [[NSNotificationCenter defaultCenter] removeObserver:self];
103 [super dealloc]; 113 [super dealloc];
104 } 114 }
105 115
106 // YES when an About box is currently showing the kAutoupdateInstallFailed 116 // YES when an About box is currently showing the kAutoupdateInstallFailed
107 // status, or if no About box is visible, if the most recent About box to be 117 // status, or if no About box is visible, if the most recent About box to be
108 // closed was closed while showing this status. When an About box opens, if 118 // closed was closed while showing this status. When an About box opens, if
109 // the recent status is kAutoupdateInstallFailed and 119 // the recent status is kAutoupdateInstallFailed or kAutoupdatePromoteFailed
110 // recentShownInstallFailedStatus is NO, the failure needs to be shown instead 120 // and recentShownUserActionFailedStatus is NO, the failure needs to be shown
111 // of launching a new update check. recentShownInstallFailedStatus is 121 // instead of launching a new update check. recentShownInstallFailedStatus is
112 // maintained by -updateStatus:. 122 // maintained by -updateStatus:.
113 static BOOL recentShownInstallFailedStatus = NO; 123 static BOOL recentShownUserActionFailedStatus = NO;
114 124
115 - (void)awakeFromNib { 125 - (void)awakeFromNib {
116 NSBundle* bundle = mac_util::MainAppBundle(); 126 NSBundle* bundle = mac_util::MainAppBundle();
117 NSString* chromeVersion = 127 NSString* chromeVersion =
118 [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 128 [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
119 129
120 #if defined(GOOGLE_CHROME_BUILD) 130 #if defined(GOOGLE_CHROME_BUILD)
121 NSString* version = chromeVersion; 131 NSString* version = chromeVersion;
122 #else // GOOGLE_CHROME_BUILD 132 #else // GOOGLE_CHROME_BUILD
123 // The format string is not localized, but this is how the displayed version 133 // The format string is not localized, but this is how the displayed version
(...skipping 15 matching lines...) Expand all
139 [logoView_ setImage:logoImage]; 149 [logoView_ setImage:logoImage];
140 150
141 [[legalText_ textStorage] setAttributedString:[[self class] legalTextBlock]]; 151 [[legalText_ textStorage] setAttributedString:[[self class] legalTextBlock]];
142 152
143 // Resize our text view now so that the |updateShift| below is set 153 // Resize our text view now so that the |updateShift| below is set
144 // correctly. The About box has its controls manually positioned, so we need 154 // correctly. The About box has its controls manually positioned, so we need
145 // to calculate how much larger (or smaller) our text box is and store that 155 // to calculate how much larger (or smaller) our text box is and store that
146 // difference in |legalShift|. We do something similar with |updateShift| 156 // difference in |legalShift|. We do something similar with |updateShift|
147 // below, which is either 0, or the amount of space to offset the window size 157 // below, which is either 0, or the amount of space to offset the window size
148 // because the view that contains the update button has been removed because 158 // because the view that contains the update button has been removed because
149 // this build doesn't have KeyStone. 159 // this build doesn't have Keystone.
150 NSRect oldLegalRect = [legalBlock_ frame]; 160 NSRect oldLegalRect = [legalBlock_ frame];
151 [legalText_ sizeToFit]; 161 [legalText_ sizeToFit];
152 NSRect newRect = oldLegalRect; 162 NSRect newRect = oldLegalRect;
153 newRect.size.height = [legalText_ frame].size.height; 163 newRect.size.height = [legalText_ frame].size.height;
154 [legalBlock_ setFrame:newRect]; 164 [legalBlock_ setFrame:newRect];
155 CGFloat legalShift = newRect.size.height - oldLegalRect.size.height; 165 CGFloat legalShift = newRect.size.height - oldLegalRect.size.height;
156 166
157 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue]; 167 NSRect backgroundFrame = [backgroundView_ frame];
158 CGFloat updateShift; 168 backgroundFrame.origin.y += legalShift;
159 if (keystoneGlue) { 169 [backgroundView_ setFrame:backgroundFrame];
170
171 NSSize windowDelta = NSMakeSize(0.0, legalShift);
172 [GTMUILocalizerAndLayoutTweaker
173 resizeWindowWithoutAutoResizingSubViews:[self window]
174 delta:windowDelta];
175
176 windowHeight_ = [[self window] frame].size.height;
177
178 [self adjustUpdateUIVisibility];
179
180 // Don't do anything update-related if adjustUpdateUIVisibility decided that
181 // updates aren't possible.
182 if (![updateBlock_ isHidden]) {
183 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue];
184 AutoupdateStatus recentStatus = [keystoneGlue recentStatus];
160 if ([keystoneGlue asyncOperationPending] || 185 if ([keystoneGlue asyncOperationPending] ||
161 ([keystoneGlue recentStatus] == kAutoupdateInstallFailed && 186 recentStatus == kAutoupdateRegisterFailed ||
162 !recentShownInstallFailedStatus)) { 187 ((recentStatus == kAutoupdateInstallFailed ||
188 recentStatus == kAutoupdatePromoteFailed) &&
189 !recentShownUserActionFailedStatus)) {
163 // If an asynchronous update operation is currently pending, such as a 190 // If an asynchronous update operation is currently pending, such as a
164 // check for updates or an update installation attempt, set the status 191 // check for updates or an update installation attempt, set the status
165 // up correspondingly without launching a new update check. 192 // up correspondingly without launching a new update check.
166 // 193 //
167 // If a previous update attempt was unsuccessful but no About box was 194 // If registration failed, no other operations make sense, so just go
168 // around to report the error, show it now, and allow another chance to 195 // straight to the error.
169 // install the update. 196 //
197 // If a previous update or promotion attempt was unsuccessful but no
198 // About box was around to report the error, show it now, and allow
199 // another chance to perform the action.
170 [self updateStatus:[keystoneGlue recentNotification]]; 200 [self updateStatus:[keystoneGlue recentNotification]];
171 } else { 201 } else {
172 // Launch a new update check, even if one was already completed, because 202 // Launch a new update check, even if one was already completed, because
173 // a new update may be available or a new update may have been installed 203 // a new update may be available or a new update may have been installed
174 // in the background since the last time an About box was displayed. 204 // in the background since the last time an About box was displayed.
175 [self checkForUpdate]; 205 [self checkForUpdate];
176 } 206 }
177
178 updateShift = 0.0;
179 } else {
180 // Hide all the update UI
181 [updateBlock_ setHidden:YES];
182
183 // Figure out the amount being removed by taking out the update block
184 // and its spacing.
185 updateShift = NSMinY([legalBlock_ frame]) - NSMinY([updateBlock_ frame]);
186
187 NSRect legalFrame = [legalBlock_ frame];
188 legalFrame.origin.y -= updateShift;
189 [legalBlock_ setFrame:legalFrame];
190 } 207 }
191 208
192 NSRect backgroundFrame = [backgroundView_ frame]; 209 [[self window] center];
193 backgroundFrame.origin.y += legalShift - updateShift;
194 [backgroundView_ setFrame:backgroundFrame];
195
196 NSSize windowDelta = NSMakeSize(0.0, legalShift - updateShift);
197
198 [GTMUILocalizerAndLayoutTweaker
199 resizeWindowWithoutAutoResizingSubViews:[self window]
200 delta:windowDelta];
201 } 210 }
202 211
203 - (void)windowWillClose:(NSNotification*)notification { 212 - (void)windowWillClose:(NSNotification*)notification {
204 [self autorelease]; 213 [self autorelease];
205 } 214 }
206 215
216 - (void)adjustUpdateUIVisibility {
217 bool allowUpdate;
218 bool allowPromotion;
219
220 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue];
221 if (keystoneGlue && ![keystoneGlue isOnReadOnlyFilesystem]) {
222 AutoupdateStatus recentStatus = [keystoneGlue recentStatus];
223 if (recentStatus == kAutoupdateRegistering ||
224 recentStatus == kAutoupdateRegisterFailed ||
225 recentStatus == kAutoupdatePromoted) {
226 // Show the update block while registering so that there's a progress
227 // spinner, and if registration failed so that there's an error message.
228 // Show it following a promotion because updates should be possible
229 // after promotion successfully completes.
230 allowUpdate = true;
231
232 // Promotion isn't possible at this point.
233 allowPromotion = false;
234 } else if (recentStatus == kAutoupdatePromoteFailed) {
235 // TODO(mark): Add kAutoupdatePromoting to this block. KSRegistration
236 // currently handles the promotion synchronously, meaning that the main
237 // thread's loop doesn't spin, meaning that animations and other updates
238 // to the window won't occur until KSRegistration is done with
239 // promotion. This looks laggy and bad and probably qualifies as
240 // "jank." For now, there just won't be any visual feedback while
241 // promotion is in progress, but it should complete (or fail) very
242 // quickly. http://b/2290009.
243 //
244 // Also see the TODO for kAutoupdatePromoting in -updateStatus:version:.
245 //
246 // Show the update block so that there's some visual feedback that
247 // promotion is under way or that it's failed. Show the promotion block
248 // because the user either just clicked that button or because the user
249 // should be able to click it again.
250 allowUpdate = true;
251 allowPromotion = true;
252 } else {
253 // Show the update block only if a promotion is not absolutely required.
254 allowUpdate = ![keystoneGlue needsPromotion];
255
256 // Show the promotion block if promotion is a possibility.
257 allowPromotion = [keystoneGlue wantsPromotion];
258 }
259 } else {
260 // There is no glue, or the application is on a read-only filesystem.
261 // Updates and promotions are impossible.
262 allowUpdate = false;
263 allowPromotion = false;
264 }
265
266 [self setAllowsUpdate:allowUpdate allowsPromotion:allowPromotion];
267 }
268
269 - (void)setAllowsUpdate:(bool)update allowsPromotion:(bool)promotion {
270 bool oldUpdate = ![updateBlock_ isHidden];
271 bool oldPromotion = ![promotionBlock_ isHidden];
272
273 if (promotion == oldPromotion && update == oldUpdate) {
274 return;
275 }
276
277 NSRect updateFrame = [updateBlock_ frame];
278 NSRect promotionFrame = [promotionBlock_ frame];
279
280 // This routine assumes no space between the update and promotion blocks.
281 DCHECK_EQ(NSMinY(updateFrame), NSMaxY(promotionFrame));
282
283 bool promotionOnly = !update && promotion;
284 bool oldPromotionOnly = !oldUpdate && oldPromotion;
285 if (promotionOnly != oldPromotionOnly) {
286 // The window is transitioning from having a promotion block and no update
287 // block to any other state, or the other way around. Move the promotion
288 // frame up so that its top edge is in the same position as the update
289 // frame's top edge, or move it back down to its original location.
290 promotionFrame.origin.y += (promotionOnly ? 1.0 : -1.0) *
291 NSHeight(updateFrame);
292 }
293
294 CGFloat delta = 0.0;
295
296 if (update != oldUpdate) {
297 [updateBlock_ setHidden:!update];
298 delta += (update ? 1.0 : -1.0) * NSHeight(updateFrame);
299 }
300
301 if (promotion != oldPromotion) {
302 [promotionBlock_ setHidden:!promotion];
303 delta += (promotion ? 1.0 : -1.0) * NSHeight(promotionFrame);
304 }
305
306 NSRect legalFrame = [legalBlock_ frame];
307
308 bool updateOrPromotion = update || promotion;
309 bool oldUpdateOrPromotion = oldUpdate || oldPromotion;
310 if (updateOrPromotion != oldUpdateOrPromotion) {
311 // The window is transitioning from having an update or promotion block or
312 // both to not having either, or the other way around. Adjust delta to
313 // account for the space between the legal block and the update or
314 // promotion block. When the update and promotion blocks are not visible,
315 // this extra spacing is not used.
316 delta += (updateOrPromotion ? 1.0 : -1.0) *
317 (NSMinY(legalFrame) - NSMaxY(updateFrame));
318 }
319
320 // The promotion frame may have changed even if delta is 0, so always reset
321 // its frame.
322 promotionFrame.origin.y += delta;
323 [promotionBlock_ setFrame:promotionFrame];
324
325 if (delta) {
326 updateFrame.origin.y += delta;
327 [updateBlock_ setFrame:updateFrame];
328
329 legalFrame.origin.y += delta;
330 [legalBlock_ setFrame:legalFrame];
331
332 NSRect backgroundFrame = [backgroundView_ frame];
333 backgroundFrame.origin.y += delta;
334 [backgroundView_ setFrame:backgroundFrame];
335
336 // GTMUILocalizerAndLayoutTweaker resizes the window without any
337 // opportunity for animation. In order to animate, disable window
338 // updates, save the current frame, let GTMUILocalizerAndLayoutTweaker do
339 // its thing, save the desired frame, restore the original frame, and then
340 // animate.
341 NSWindow* window = [self window];
342 [window disableScreenUpdatesUntilFlush];
343
344 NSRect oldFrame = [window frame];
345
346 // GTMUILocalizerAndLayoutTweaker applies its delta to the window's
347 // current size (like oldFrame.size), but oldFrame isn't trustworthy if
348 // an animation is in progress. Set the window's frame to
349 // intermediateFrame, which is a frame of the size that an existing
350 // animation is animating to, so that GTM can apply the delta to the right
351 // size.
352 NSRect intermediateFrame = oldFrame;
353 intermediateFrame.origin.y -= intermediateFrame.size.height - windowHeight_;
354 intermediateFrame.size.height = windowHeight_;
355 [window setFrame:intermediateFrame display:NO];
356
357 NSSize windowDelta = NSMakeSize(0.0, delta);
358 [GTMUILocalizerAndLayoutTweaker
359 resizeWindowWithoutAutoResizingSubViews:window
360 delta:windowDelta];
361 [window setFrameTopLeftPoint:NSMakePoint(NSMinX(intermediateFrame),
362 NSMaxY(intermediateFrame))];
363 NSRect newFrame = [window frame];
364
365 windowHeight_ += delta;
366
367 if (![[self window] isVisible]) {
368 // Don't animate if the window isn't on screen yet.
369 [window setFrame:newFrame display:NO];
370 } else {
371 [window setFrame:oldFrame display:NO];
372 [window setFrame:newFrame display:YES animate:YES];
373 }
374 }
375 }
376
207 - (void)setUpdateThrobberMessage:(NSString*)message { 377 - (void)setUpdateThrobberMessage:(NSString*)message {
208 [updateStatusIndicator_ setHidden:YES]; 378 [updateStatusIndicator_ setHidden:YES];
209 379
210 [spinner_ setHidden:NO]; 380 [spinner_ setHidden:NO];
211 [spinner_ startAnimation:self]; 381 [spinner_ startAnimation:self];
212 382
213 [updateText_ setStringValue:message]; 383 [updateText_ setStringValue:message];
214 } 384 }
215 385
216 - (void)setUpdateImage:(int)imageID message:(NSString*)message { 386 - (void)setUpdateImage:(int)imageID message:(NSString*)message {
(...skipping 14 matching lines...) Expand all
231 401
232 // Immediately, kAutoupdateStatusNotification will be posted, and 402 // Immediately, kAutoupdateStatusNotification will be posted, and
233 // -updateStatus: will be called with status kAutoupdateChecking. 403 // -updateStatus: will be called with status kAutoupdateChecking.
234 // 404 //
235 // Upon completion, kAutoupdateStatusNotification will be posted, and 405 // Upon completion, kAutoupdateStatusNotification will be posted, and
236 // -updateStatus: will be called with a status indicating the result of the 406 // -updateStatus: will be called with a status indicating the result of the
237 // check. 407 // check.
238 } 408 }
239 409
240 - (IBAction)updateNow:(id)sender { 410 - (IBAction)updateNow:(id)sender {
241 updateTriggered_ = YES;
242
243 [[KeystoneGlue defaultKeystoneGlue] installUpdate]; 411 [[KeystoneGlue defaultKeystoneGlue] installUpdate];
244 412
245 // Immediately, kAutoupdateStatusNotification will be posted, and 413 // Immediately, kAutoupdateStatusNotification will be posted, and
246 // -updateStatus: will be called with status kAutoupdateInstalling. 414 // -updateStatus: will be called with status kAutoupdateInstalling.
247 // 415 //
248 // Upon completion, kAutoupdateStatusNotification will be posted, and 416 // Upon completion, kAutoupdateStatusNotification will be posted, and
249 // -updateStatus: will be called with a status indicating the result of the 417 // -updateStatus: will be called with a status indicating the result of the
250 // installation attempt. 418 // installation attempt.
251 } 419 }
252 420
421 - (IBAction)promoteUpdater:(id)sender {
422 [[KeystoneGlue defaultKeystoneGlue] promoteTicket];
423
424 // Immediately, kAutoupdateStatusNotification will be posted, and
425 // -updateStatus: will be called with status kAutoupdatePromoting.
426 //
427 // Upon completion, kAutoupdateStatusNotification will be posted, and
428 // -updateStatus: will be called with a status indicating a result of the
429 // installation attempt.
430 //
431 // If the promotion was successful, KeystoneGlue will re-register the ticket
432 // and -updateStatus: will be called again indicating first that
433 // registration is in progress and subsequently that it has completed.
434 }
435
253 - (void)updateStatus:(NSNotification*)notification { 436 - (void)updateStatus:(NSNotification*)notification {
254 recentShownInstallFailedStatus = NO; 437 recentShownUserActionFailedStatus = NO;
255 438
256 NSDictionary* dictionary = [notification userInfo]; 439 NSDictionary* dictionary = [notification userInfo];
257 AutoupdateStatus status = static_cast<AutoupdateStatus>( 440 AutoupdateStatus status = static_cast<AutoupdateStatus>(
258 [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]); 441 [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
259 442
260 // Don't assume |version| is a real string. It may be nil. 443 // Don't assume |version| is a real string. It may be nil.
261 NSString* version = [dictionary objectForKey:kAutoupdateStatusVersion]; 444 NSString* version = [dictionary objectForKey:kAutoupdateStatusVersion];
262 445
446 bool updateMessage = true;
263 bool throbber = false; 447 bool throbber = false;
264 int imageID = 0; 448 int imageID = 0;
265 NSString* message; 449 NSString* message;
450 bool enableUpdateButton = false;
451 bool enablePromoteButton = true;
266 452
267 switch (status) { 453 switch (status) {
454 case kAutoupdateRegistering:
455 // When registering, use the "checking" message. The check will be
456 // launched if appropriate immediately after registration.
457 throbber = true;
458 message = l10n_util::GetNSStringWithFixup(IDS_UPGRADE_CHECK_STARTED);
459 enablePromoteButton = false;
460
461 break;
462
463 case kAutoupdateRegistered:
464 // Once registered, the ability to update and promote is known.
465 [self adjustUpdateUIVisibility];
466
467 if (![updateBlock_ isHidden]) {
468 // If registration completes while the window is visible, go straight
469 // into an update check. Return immediately, this routine will be
470 // re-entered shortly with kAutoupdateChecking.
471 [self checkForUpdate];
472 return;
473 }
474
475 // Nothing actually failed, but updates aren't possible. The throbber
476 // and message are hidden, but they'll be reset to these dummy values
477 // just to get the throbber to stop spinning if it's running.
478 imageID = IDR_UPDATE_FAIL;
479 message = l10n_util::GetNSStringFWithFixup(IDS_UPGRADE_ERROR,
480 IntToString16(status));
481
482 break;
483
268 case kAutoupdateChecking: 484 case kAutoupdateChecking:
269 throbber = true; 485 throbber = true;
270 message = l10n_util::GetNSStringWithFixup(IDS_UPGRADE_CHECK_STARTED); 486 message = l10n_util::GetNSStringWithFixup(IDS_UPGRADE_CHECK_STARTED);
487 enablePromoteButton = false;
271 488
272 break; 489 break;
273 490
274 case kAutoupdateCurrent: 491 case kAutoupdateCurrent:
275 imageID = IDR_UPDATE_UPTODATE; 492 imageID = IDR_UPDATE_UPTODATE;
276 message = l10n_util::GetNSStringFWithFixup( 493 message = l10n_util::GetNSStringFWithFixup(
277 IDS_UPGRADE_ALREADY_UP_TO_DATE, 494 IDS_UPGRADE_ALREADY_UP_TO_DATE,
278 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), 495 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
279 base::SysNSStringToUTF16(version)); 496 base::SysNSStringToUTF16(version));
280 497
281 break; 498 break;
282 499
283 case kAutoupdateAvailable: 500 case kAutoupdateAvailable:
284 imageID = IDR_UPDATE_AVAILABLE; 501 imageID = IDR_UPDATE_AVAILABLE;
285 message = l10n_util::GetNSStringFWithFixup( 502 message = l10n_util::GetNSStringFWithFixup(
286 IDS_UPGRADE_AVAILABLE, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 503 IDS_UPGRADE_AVAILABLE, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
287 [updateNowButton_ setEnabled:YES]; 504 enableUpdateButton = true;
288 505
289 break; 506 break;
290 507
291 case kAutoupdateInstalling: 508 case kAutoupdateInstalling:
292 // Don't let anyone click "Update Now" twice.
293 [updateNowButton_ setEnabled:NO];
294
295 throbber = true; 509 throbber = true;
296 message = l10n_util::GetNSStringWithFixup(IDS_UPGRADE_STARTED); 510 message = l10n_util::GetNSStringWithFixup(IDS_UPGRADE_STARTED);
511 enablePromoteButton = false;
297 512
298 break; 513 break;
299 514
300 case kAutoupdateInstalled: 515 case kAutoupdateInstalled:
301 { 516 {
302 imageID = IDR_UPDATE_UPTODATE; 517 imageID = IDR_UPDATE_UPTODATE;
303 string16 productName = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 518 string16 productName = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
304 if (version) { 519 if (version) {
305 message = l10n_util::GetNSStringFWithFixup( 520 message = l10n_util::GetNSStringFWithFixup(
306 IDS_UPGRADE_SUCCESSFUL, 521 IDS_UPGRADE_SUCCESSFUL,
307 productName, 522 productName,
308 base::SysNSStringToUTF16(version)); 523 base::SysNSStringToUTF16(version));
309 } else { 524 } else {
310 message = l10n_util::GetNSStringFWithFixup( 525 message = l10n_util::GetNSStringFWithFixup(
311 IDS_UPGRADE_SUCCESSFUL_NOVERSION, productName); 526 IDS_UPGRADE_SUCCESSFUL_NOVERSION, productName);
312 } 527 }
313 528
314 // TODO(mark): Turn the button in the dialog into a restart button 529 // TODO(mark): Turn the button in the dialog into a restart button
315 // instead of springing this sheet or dialog. 530 // instead of springing this sheet or dialog.
316 NSWindow* window = [self window]; 531 NSWindow* window = [self window];
317 NSWindow* restartDialogParent = [window isVisible] ? window : nil; 532 NSWindow* restartDialogParent = [window isVisible] ? window : nil;
318 restart_browser::RequestRestart(restartDialogParent); 533 restart_browser::RequestRestart(restartDialogParent);
319 } 534 }
320 535
321 break; 536 break;
322 537
323 case kAutoupdateInstallFailed: 538 case kAutoupdatePromoting:
324 recentShownInstallFailedStatus = YES; 539 #if 1
540 // TODO(mark): See the TODO in -adjustUpdateUIVisibility for an
541 // explanation of why nothing can be done here at the moment. When
542 // KSRegistration handles promotion asynchronously, this dummy block can
543 // be replaced with the #else block. For now, just leave the messaging
544 // alone. http://b/2290009.
545 updateMessage = false;
546 #else
547 // The visibility may be changing.
548 [self adjustUpdateUIVisibility];
325 549
326 // Allow another chance. 550 // This is not a terminal state, and kAutoupdatePromoted or
327 [updateNowButton_ setEnabled:YES]; 551 // kAutoupdatePromoteFailed will follow. Use the throbber and
552 // "checking" message so that it looks like something's happening.
553 throbber = true;
554 message = l10n_util::GetNSStringWithFixup(IDS_UPGRADE_CHECK_STARTED);
555 #endif
328 556
329 // Fall through. 557 enablePromoteButton = false;
558
559 break;
560
561 case kAutoupdatePromoted:
562 // The visibility may be changing.
563 [self adjustUpdateUIVisibility];
564
565 if (![updateBlock_ isHidden]) {
566 // If promotion completes while the window is visible, go straight
567 // into an update check. Return immediately, this routine will be
568 // re-entered shortly with kAutoupdateChecking.
569 [self checkForUpdate];
570 return;
571 }
572
573 // Nothing actually failed, but updates aren't possible. The throbber
574 // and message are hidden, but they'll be reset to these dummy values
575 // just to get the throbber to stop spinning if it's running.
576 imageID = IDR_UPDATE_FAIL;
577 message = l10n_util::GetNSStringFWithFixup(IDS_UPGRADE_ERROR,
578 IntToString16(status));
579
580 break;
581
582 case kAutoupdateRegisterFailed:
583 imageID = IDR_UPDATE_FAIL;
584 message = l10n_util::GetNSStringFWithFixup(IDS_UPGRADE_ERROR,
585 IntToString16(status));
586 enablePromoteButton = false;
587
588 break;
330 589
331 case kAutoupdateCheckFailed: 590 case kAutoupdateCheckFailed:
332 imageID = IDR_UPDATE_FAIL; 591 imageID = IDR_UPDATE_FAIL;
333 message = l10n_util::GetNSStringFWithFixup(IDS_UPGRADE_ERROR, 592 message = l10n_util::GetNSStringFWithFixup(IDS_UPGRADE_ERROR,
334 IntToString16(status)); 593 IntToString16(status));
594
595 break;
596
597 case kAutoupdateInstallFailed:
598 recentShownUserActionFailedStatus = YES;
599
600 imageID = IDR_UPDATE_FAIL;
601 message = l10n_util::GetNSStringFWithFixup(IDS_UPGRADE_ERROR,
602 IntToString16(status));
603
604 // Allow another chance.
605 enableUpdateButton = true;
606
607 break;
608
609 case kAutoupdatePromoteFailed:
610 recentShownUserActionFailedStatus = YES;
611
612 imageID = IDR_UPDATE_FAIL;
613 message = l10n_util::GetNSStringFWithFixup(IDS_UPGRADE_ERROR,
614 IntToString16(status));
335 615
336 break; 616 break;
337 617
338 default: 618 default:
339 NOTREACHED(); 619 NOTREACHED();
620
340 return; 621 return;
341 } 622 }
342 623
343 if (throbber) { 624 if (updateMessage) {
344 [self setUpdateThrobberMessage:message]; 625 if (throbber) {
345 } else { 626 [self setUpdateThrobberMessage:message];
346 DCHECK_NE(imageID, 0); 627 } else {
347 [self setUpdateImage:imageID message:message]; 628 DCHECK_NE(imageID, 0);
629 [self setUpdateImage:imageID message:message];
630 }
348 } 631 }
632
633 // Note that these buttons may be hidden depending on what
634 // -adjustUpdateUIVisibility did. Their enabled/disabled status doesn't
635 // necessarily have anything to do with their visibility.
636 [updateNowButton_ setEnabled:enableUpdateButton];
637 [promoteButton_ setEnabled:enablePromoteButton];
349 } 638 }
350 639
351 - (BOOL)textView:(NSTextView *)aTextView 640 - (BOOL)textView:(NSTextView *)aTextView
352 clickedOnLink:(id)link 641 clickedOnLink:(id)link
353 atIndex:(NSUInteger)charIndex { 642 atIndex:(NSUInteger)charIndex {
354 // We always create a new window, so there's no need to try to re-use 643 // We always create a new window, so there's no need to try to re-use
355 // an existing one just to pass in the NEW_WINDOW disposition. 644 // an existing one just to pass in the NEW_WINDOW disposition.
356 Browser* browser = Browser::Create(profile_); 645 Browser* browser = Browser::Create(profile_);
357 if (browser) { 646 if (browser) {
358 browser->OpenURL(GURL([link UTF8String]), GURL(), NEW_WINDOW, 647 browser->OpenURL(GURL([link UTF8String]), GURL(), NEW_WINDOW,
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 NSRange string_range = NSMakeRange(0, [legal_block length]); 775 NSRange string_range = NSMakeRange(0, [legal_block length]);
487 [legal_block addAttribute:NSFontAttributeName 776 [legal_block addAttribute:NSFontAttributeName
488 value:[NSFont labelFontOfSize:11] 777 value:[NSFont labelFontOfSize:11]
489 range:string_range]; 778 range:string_range];
490 779
491 [legal_block endEditing]; 780 [legal_block endEditing];
492 return legal_block; 781 return legal_block;
493 } 782 }
494 783
495 @end // @implementation AboutWindowController 784 @end // @implementation AboutWindowController
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/about_window_controller.h ('k') | chrome/browser/cocoa/about_window_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698