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

Side by Side Diff: chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm

Issue 10829170: Cocoa: Show OAuth issues in extension install dialog (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: " Created 8 years, 4 months 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) 2012 The Chromium Authors. All rights reserved. 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 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/ui/cocoa/extensions/extension_install_dialog_controller. h" 5 #import "chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller. h"
6 6
7 #include "base/auto_reset.h"
7 #include "base/i18n/rtl.h" 8 #include "base/i18n/rtl.h"
8 #include "base/mac/bundle_locations.h" 9 #include "base/mac/bundle_locations.h"
9 #include "base/mac/mac_util.h" 10 #include "base/mac/mac_util.h"
10 #include "base/memory/scoped_nsobject.h" 11 #include "base/memory/scoped_nsobject.h"
11 #include "base/string_util.h" 12 #include "base/string_util.h"
12 #include "base/sys_string_conversions.h" 13 #include "base/sys_string_conversions.h"
13 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
14 #include "chrome/browser/extensions/bundle_installer.h" 15 #include "chrome/browser/extensions/bundle_installer.h"
15 #include "chrome/browser/extensions/extension_install_dialog.h" 16 #include "chrome/browser/extensions/extension_install_dialog.h"
16 #include "chrome/common/extensions/extension.h" 17 #include "chrome/common/extensions/extension.h"
17 #include "content/public/browser/page_navigator.h" 18 #include "content/public/browser/page_navigator.h"
18 #include "grit/generated_resources.h" 19 #include "grit/generated_resources.h"
19 #include "skia/ext/skia_utils_mac.h" 20 #include "skia/ext/skia_utils_mac.h"
20 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" 21 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
21 #include "ui/base/l10n/l10n_util.h" 22 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/l10n/l10n_util_mac.h" 23 #include "ui/base/l10n/l10n_util_mac.h"
23 24
24 using content::OpenURLParams; 25 using content::OpenURLParams;
25 using content::Referrer; 26 using content::Referrer;
26 using extensions::BundleInstaller; 27 using extensions::BundleInstaller;
27 28
28 @interface ExtensionInstallDialogController () 29 @interface ExtensionInstallDialogController ()
29 - (BOOL)isBundleInstall; 30 - (BOOL)isBundleInstall;
30 - (BOOL)isInlineInstall; 31 - (BOOL)isInlineInstall;
31 - (void)appendRatingStar:(const gfx::ImageSkia*)skiaImage; 32 - (void)appendRatingStar:(const gfx::ImageSkia*)skiaImage;
33 - (void)onOutlineViewRowCountDidChange;
34 - (NSDictionary*)buildItemWithTitle:(NSString*)title
35 isGroupItem:(BOOL)isGroupItem
36 children:(NSArray*)children;
37 - (NSDictionary*)buildIssue:(const IssueAdviceInfoEntry&)issue;
38 - (NSArray*)buildWarnings:(const ExtensionInstallPrompt::Prompt&)prompt;
32 @end 39 @end
33 40
34 namespace { 41 namespace {
35 42
36 // Padding above the warnings separator, we must also subtract this when hiding 43 // Padding above the warnings separator, we must also subtract this when hiding
37 // it. 44 // it.
38 const CGFloat kWarningsSeparatorPadding = 14; 45 const CGFloat kWarningsSeparatorPadding = 14;
39 46
40 // Maximum height we will adjust controls to when trying to accomodate their 47 // Maximum height we will adjust controls to when trying to accomodate their
41 // contents. 48 // contents.
42 const CGFloat kMaxControlHeight = 400; 49 const CGFloat kMaxControlHeight = 400;
43 50
51 NSString* const kTitleKey = @"title";
52 NSString* const kIsGroupItemKey = @"isGroupItem";
53 NSString* const kChildrenKey = @"children";
54 NSString* const kCanExpandKey = @"canExpand";
55
44 // Adjust the |control|'s height so that its content is not clipped. 56 // Adjust the |control|'s height so that its content is not clipped.
45 // This also adds the change in height to the |totalOffset| and shifts the 57 // This also adds the change in height to the |totalOffset| and shifts the
46 // control down by that amount. 58 // control down by that amount.
47 void OffsetControlVerticallyToFitContent(NSControl* control, 59 void OffsetControlVerticallyToFitContent(NSControl* control,
48 CGFloat* totalOffset) { 60 CGFloat* totalOffset) {
49 // Adjust the control's height so that its content is not clipped. 61 // Adjust the control's height so that its content is not clipped.
50 NSRect currentRect = [control frame]; 62 NSRect currentRect = [control frame];
51 NSRect fitRect = currentRect; 63 NSRect fitRect = currentRect;
52 fitRect.size.height = kMaxControlHeight; 64 fitRect.size.height = kMaxControlHeight;
53 CGFloat desiredHeight = [[control cell] cellSizeForBounds:fitRect].height; 65 CGFloat desiredHeight = [[control cell] cellSizeForBounds:fitRect].height;
54 CGFloat offset = desiredHeight - currentRect.size.height; 66 CGFloat offset = desiredHeight - NSHeight(currentRect);
55 67
56 [control setFrameSize:NSMakeSize(currentRect.size.width, 68 [control setFrameSize:NSMakeSize(NSWidth(currentRect),
57 currentRect.size.height + offset)]; 69 NSHeight(currentRect) + offset)];
58 70
59 *totalOffset += offset; 71 *totalOffset += offset;
60 72
61 // Move the control vertically by the new total offset. 73 // Move the control vertically by the new total offset.
62 NSPoint origin = [control frame].origin; 74 NSPoint origin = [control frame].origin;
63 origin.y -= *totalOffset; 75 origin.y -= *totalOffset;
64 [control setFrameOrigin:origin]; 76 [control setFrameOrigin:origin];
65 } 77 }
66 78
79 // Gets the desired height of |outlineView|. Simply using the view's frame
80 // doesn't work if an animation is pending.
81 CGFloat GetDesiredOutlineViewHeight(NSOutlineView* outlineView) {
82 CGFloat height = 0;
83 for (NSInteger i = 0; i < [outlineView numberOfRows]; ++i)
84 height += NSHeight([outlineView rectOfRow:i]);
85 return height;
86 }
87
88 void OffsetOutlineViewVerticallyToFitContent(NSOutlineView* outlineView,
89 CGFloat* totalOffset) {
90 NSScrollView* scrollView = [outlineView enclosingScrollView];
91 NSRect frame = [scrollView frame];
92 CGFloat desiredHeight = GetDesiredOutlineViewHeight(outlineView);
93 CGFloat offset = desiredHeight - NSHeight(frame);
94 frame.size.height += offset;
95
96 *totalOffset += offset;
97
98 // Move the control vertically by the new total offset.
99 frame.origin.y -= *totalOffset;
100 [scrollView setFrame:frame];
101 }
102
67 void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) { 103 void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) {
68 ExtensionInstallDialogController* controller = 104 ExtensionInstallDialogController* controller =
69 static_cast<ExtensionInstallDialogController*>(data); 105 static_cast<ExtensionInstallDialogController*>(data);
70 [controller appendRatingStar:skiaImage]; 106 [controller appendRatingStar:skiaImage];
71 } 107 }
72 108
109 void DrawBulletInFrame(NSRect frame) {
110 NSRect rect;
111 rect.size.width = std::min(NSWidth(frame), NSHeight(frame)) * 0.38;
112 rect.size.height = NSWidth(rect);
113 rect.origin.x = frame.origin.x + (NSWidth(frame) - NSWidth(rect)) / 2.0;
114 rect.origin.y = frame.origin.y + (NSHeight(frame) - NSHeight(rect)) / 2.0;
115 rect = NSIntegralRect(rect);
116
117 [[NSColor colorWithCalibratedWhite:0.0 alpha:0.42] set];
118 [[NSBezierPath bezierPathWithOvalInRect:rect] fill];
119 }
120
73 } 121 }
74 122
75 @implementation ExtensionInstallDialogController 123 @implementation ExtensionInstallDialogController
76 124
77 @synthesize iconView = iconView_; 125 @synthesize iconView = iconView_;
78 @synthesize titleField = titleField_; 126 @synthesize titleField = titleField_;
79 @synthesize itemsField = itemsField_; 127 @synthesize itemsField = itemsField_;
80 @synthesize subtitleField = subtitleField_;
81 @synthesize warningsField = warningsField_;
82 @synthesize cancelButton = cancelButton_; 128 @synthesize cancelButton = cancelButton_;
83 @synthesize okButton = okButton_; 129 @synthesize okButton = okButton_;
130 @synthesize outlineView = outlineView_;
84 @synthesize warningsSeparator = warningsSeparator_; 131 @synthesize warningsSeparator = warningsSeparator_;
85 @synthesize ratingStars = ratingStars_; 132 @synthesize ratingStars = ratingStars_;
86 @synthesize ratingCountField = ratingCountField_; 133 @synthesize ratingCountField = ratingCountField_;
87 @synthesize userCountField = userCountField_; 134 @synthesize userCountField = userCountField_;
88 135
89 - (id)initWithParentWindow:(NSWindow*)window 136 - (id)initWithParentWindow:(NSWindow*)window
90 navigator:(content::PageNavigator*)navigator 137 navigator:(content::PageNavigator*)navigator
91 delegate:(ExtensionInstallPrompt::Delegate*)delegate 138 delegate:(ExtensionInstallPrompt::Delegate*)delegate
92 prompt:(const ExtensionInstallPrompt::Prompt&)prompt { 139 prompt:(const ExtensionInstallPrompt::Prompt&)prompt {
93 NSString* nibpath = nil; 140 NSString* nibpath = nil;
141 warnings_.reset([[self buildWarnings:prompt] retain]);
94 142
95 // We use a different XIB in the case of bundle installs, inline installs or 143 // We use a different XIB in the case of bundle installs, inline installs or
96 // no permission warnings. These are laid out nicely for the data they 144 // no permission warnings. These are laid out nicely for the data they
97 // display. 145 // display.
98 if (prompt.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT) { 146 if (prompt.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT) {
99 nibpath = [base::mac::FrameworkBundle() 147 nibpath = [base::mac::FrameworkBundle()
100 pathForResource:@"ExtensionInstallPromptBundle" 148 pathForResource:@"ExtensionInstallPromptBundle"
101 ofType:@"nib"]; 149 ofType:@"nib"];
102 } else if (prompt.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT) { 150 } else if (prompt.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT) {
103 nibpath = [base::mac::FrameworkBundle() 151 nibpath = [base::mac::FrameworkBundle()
104 pathForResource:@"ExtensionInstallPromptInline" 152 pathForResource:@"ExtensionInstallPromptInline"
105 ofType:@"nib"]; 153 ofType:@"nib"];
106 } else if (prompt.GetPermissionCount() == 0) { 154 } else if (prompt.GetPermissionCount() == 0 &&
155 prompt.GetOAuthIssueCount() == 0) {
107 nibpath = [base::mac::FrameworkBundle() 156 nibpath = [base::mac::FrameworkBundle()
108 pathForResource:@"ExtensionInstallPromptNoWarnings" 157 pathForResource:@"ExtensionInstallPromptNoWarnings"
109 ofType:@"nib"]; 158 ofType:@"nib"];
110 } else { 159 } else {
111 nibpath = [base::mac::FrameworkBundle() 160 nibpath = [base::mac::FrameworkBundle()
112 pathForResource:@"ExtensionInstallPrompt" 161 pathForResource:@"ExtensionInstallPrompt"
113 ofType:@"nib"]; 162 ofType:@"nib"];
114 } 163 }
115 164
116 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { 165 if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], 242 [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame],
194 -buttonDelta.width, 0)]; 243 -buttonDelta.width, 0)];
195 } 244 }
196 buttonDelta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_]; 245 buttonDelta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_];
197 if (buttonDelta.width) { 246 if (buttonDelta.width) {
198 [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], 247 [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame],
199 -buttonDelta.width, 0)]; 248 -buttonDelta.width, 0)];
200 } 249 }
201 250
202 if ([self isBundleInstall]) { 251 if ([self isBundleInstall]) {
203 [subtitleField_ setStringValue:base::SysUTF16ToNSString(
204 prompt_->GetPermissionsHeading())];
205
206 // We display the list of extension names as a simple text string, seperated 252 // We display the list of extension names as a simple text string, seperated
207 // by newlines. 253 // by newlines.
208 BundleInstaller::ItemList items = prompt_->bundle()->GetItemsWithState( 254 BundleInstaller::ItemList items = prompt_->bundle()->GetItemsWithState(
209 BundleInstaller::Item::STATE_PENDING); 255 BundleInstaller::Item::STATE_PENDING);
210 256
211 NSMutableString* joinedItems = [NSMutableString string]; 257 NSMutableString* joinedItems = [NSMutableString string];
212 for (size_t i = 0; i < items.size(); ++i) { 258 for (size_t i = 0; i < items.size(); ++i) {
213 if (i > 0) 259 if (i > 0)
214 [joinedItems appendString:@"\n"]; 260 [joinedItems appendString:@"\n"];
215 [joinedItems appendString:base::SysUTF16ToNSString( 261 [joinedItems appendString:base::SysUTF16ToNSString(
216 items[i].GetNameForDisplay())]; 262 items[i].GetNameForDisplay())];
217 } 263 }
218 [itemsField_ setStringValue:joinedItems]; 264 [itemsField_ setStringValue:joinedItems];
219 265
220 // Adjust the controls to fit the list of extensions. 266 // Adjust the controls to fit the list of extensions.
221 OffsetControlVerticallyToFitContent(itemsField_, &totalOffset); 267 OffsetControlVerticallyToFitContent(itemsField_, &totalOffset);
222 } 268 }
223 269
224 // If there are any warnings, then we have to do some special layout. 270 // If there are any warnings or OAuth issues, then we have to do some special
225 if (prompt_->GetPermissionCount() > 0) { 271 // layout.
226 [subtitleField_ setStringValue:base::SysUTF16ToNSString( 272 if (prompt_->GetPermissionCount() > 0 || prompt_->GetOAuthIssueCount() > 0) {
227 prompt_->GetPermissionsHeading())]; 273 NSSize spacing = [outlineView_ intercellSpacing];
228 274 spacing.width += 2;
229 // We display the permission warnings as a simple text string, separated by 275 spacing.height += 2;
230 // newlines. 276 [outlineView_ setIntercellSpacing:spacing];
231 NSMutableString* joinedWarnings = [NSMutableString string]; 277 [[[[outlineView_ tableColumns] objectAtIndex:0] dataCell] setWraps:YES];
232 for (size_t i = 0; i < prompt_->GetPermissionCount(); ++i) { 278 for (id item in warnings_.get()) {
233 if (i > 0) 279 if ([[item objectForKey:kIsGroupItemKey] boolValue])
234 [joinedWarnings appendString:@"\n"]; 280 [outlineView_ expandItem:item expandChildren:NO];
235 [joinedWarnings appendString:base::SysUTF16ToNSString(
236 prompt_->GetPermission(i))];
237 } 281 }
238 [warningsField_ setStringValue:joinedWarnings]; 282 // Adjust the outline view to fit the warnings.
239 283 OffsetOutlineViewVerticallyToFitContent(outlineView_, &totalOffset);
240 // In the store version of the dialog the icon extends past the one-line
241 // version of the permission field. Therefore when increasing the window
242 // size for multi-line permissions we don't have to add the full offset,
243 // only the part that extends past the icon.
244 CGFloat warningsGrowthSlack = 0;
245 if (![self isBundleInstall] &&
246 [warningsField_ frame].origin.y > [iconView_ frame].origin.y) {
247 warningsGrowthSlack =
248 [warningsField_ frame].origin.y - [iconView_ frame].origin.y;
249 }
250
251 // Adjust the controls to fit the permission warnings.
252 OffsetControlVerticallyToFitContent(subtitleField_, &totalOffset);
253 OffsetControlVerticallyToFitContent(warningsField_, &totalOffset);
254
255 totalOffset = MAX(totalOffset - warningsGrowthSlack, 0);
256 } else if ([self isInlineInstall] || [self isBundleInstall]) { 284 } else if ([self isInlineInstall] || [self isBundleInstall]) {
257 // Inline and bundle installs that don't have a permissions section need to 285 // Inline and bundle installs that don't have a permissions section need to
258 // hide controls related to that and shrink the window by the space they 286 // hide controls related to that and shrink the window by the space they
259 // take up. 287 // take up.
260 NSRect hiddenRect = NSUnionRect([warningsSeparator_ frame], 288 NSRect hiddenRect = NSUnionRect([warningsSeparator_ frame],
261 [subtitleField_ frame]); 289 [[outlineView_ enclosingScrollView] frame]);
262 hiddenRect = NSUnionRect(hiddenRect, [warningsField_ frame]);
263 [warningsSeparator_ setHidden:YES]; 290 [warningsSeparator_ setHidden:YES];
264 [subtitleField_ setHidden:YES]; 291 [[outlineView_ enclosingScrollView] setHidden:YES];
265 [warningsField_ setHidden:YES]; 292 totalOffset -= NSHeight(hiddenRect) + kWarningsSeparatorPadding;
266 totalOffset -= hiddenRect.size.height + kWarningsSeparatorPadding;
267 } 293 }
268 294
269 // If necessary, adjust the window size. 295 // If necessary, adjust the window size.
270 if (totalOffset) { 296 if (totalOffset) {
271 NSRect currentRect = [[self window] frame]; 297 NSRect currentRect = [[self window] frame];
272 [[self window] setFrame:NSMakeRect(currentRect.origin.x, 298 [[self window] setFrame:NSMakeRect(currentRect.origin.x,
273 currentRect.origin.y - totalOffset, 299 currentRect.origin.y - totalOffset,
274 currentRect.size.width, 300 NSWidth(currentRect),
275 currentRect.size.height + totalOffset) 301 NSHeight(currentRect) + totalOffset)
276 display:NO]; 302 display:NO];
277 } 303 }
278 } 304 }
279 305
280 - (void)didEndSheet:(NSWindow*)sheet 306 - (void)didEndSheet:(NSWindow*)sheet
281 returnCode:(int)returnCode 307 returnCode:(int)returnCode
282 contextInfo:(void*)contextInfo { 308 contextInfo:(void*)contextInfo {
283 [sheet close]; 309 [sheet close];
284 } 310 }
285 311
(...skipping 20 matching lines...) Expand all
306 CGFloat maxStarRight = 0; 332 CGFloat maxStarRight = 0;
307 if ([[ratingStars_ subviews] count]) { 333 if ([[ratingStars_ subviews] count]) {
308 maxStarRight = NSMaxX([[[ratingStars_ subviews] lastObject] frame]); 334 maxStarRight = NSMaxX([[[ratingStars_ subviews] lastObject] frame]);
309 } 335 }
310 NSRect starBounds = NSMakeRect(maxStarRight, 0, 336 NSRect starBounds = NSMakeRect(maxStarRight, 0,
311 skiaImage->width(), skiaImage->height()); 337 skiaImage->width(), skiaImage->height());
312 [view setFrame:starBounds]; 338 [view setFrame:starBounds];
313 [ratingStars_ addSubview:view]; 339 [ratingStars_ addSubview:view];
314 } 340 }
315 341
342 - (void)onOutlineViewRowCountDidChange {
343 // Force the outline view to update.
344 [outlineView_ reloadData];
345
346 CGFloat totalOffset = 0.0;
347 OffsetOutlineViewVerticallyToFitContent(outlineView_, &totalOffset);
348 if (totalOffset) {
349 NSRect currentRect = [[self window] frame];
350 currentRect.origin.y -= totalOffset;
351 currentRect.size.height += totalOffset;
352 [[self window] setFrame:currentRect
353 display:YES];
354 }
355 }
356
357 - (id)outlineView:(NSOutlineView*)outlineView
358 child:(NSInteger)index
359 ofItem:(id)item {
360 if (!item)
361 return [warnings_ objectAtIndex:index];
362 if ([item isKindOfClass:[NSDictionary class]])
363 return [[item objectForKey:kChildrenKey] objectAtIndex:index];
364 NOTREACHED();
365 return nil;
366 }
367
368 - (BOOL)outlineView:(NSOutlineView*)outlineView
369 isItemExpandable:(id)item {
370 return [self outlineView:outlineView numberOfChildrenOfItem:item] > 0;
371 }
372
373 - (NSInteger)outlineView:(NSOutlineView*)outlineView
374 numberOfChildrenOfItem:(id)item {
375 if (!item)
376 return [warnings_ count];
377 if ([item isKindOfClass:[NSDictionary class]])
378 return [[item objectForKey:kChildrenKey] count];
379 NOTREACHED();
380 return 0;
381 }
382
383 - (id)outlineView:(NSOutlineView*)outlineView
384 objectValueForTableColumn:(NSTableColumn *)tableColumn
385 byItem:(id)item {
386 return [item objectForKey:kTitleKey];
387 }
388
389 - (BOOL)outlineView:(NSOutlineView *)outlineView
390 shouldExpandItem:(id)item {
391 return [[item objectForKey:kCanExpandKey] boolValue];
392 }
393
394 - (void)outlineViewItemDidExpand:sender {
395 // Call via run loop to avoid animation glitches.
396 [self performSelector:@selector(onOutlineViewRowCountDidChange)
397 withObject:nil
398 afterDelay:0];
399 }
400
401 - (void)outlineViewItemDidCollapse:sender {
402 // Call via run loop to avoid animation glitches.
403 [self performSelector:@selector(onOutlineViewRowCountDidChange)
404 withObject:nil
405 afterDelay:0];
406 }
407
408 - (CGFloat)outlineView:(NSOutlineView *)outlineView
409 heightOfRowByItem:(id)item {
410 // Prevent reentrancy due to the frameOfCellAtColumn:row: call below.
411 if (isComputingRowHeight_)
412 return 1;
413 AutoReset<BOOL> reset(&isComputingRowHeight_, YES);
414
415 NSCell* cell = [[[outlineView_ tableColumns] objectAtIndex:0] dataCell];
416 [cell setStringValue:[item objectForKey:kTitleKey]];
417 NSRect bounds = NSZeroRect;
418 NSInteger row = [outlineView_ rowForItem:item];
419 bounds.size.width = NSWidth([outlineView_ frameOfCellAtColumn:0 row:row]);
420 bounds.size.height = kMaxControlHeight;
421
422 return [cell cellSizeForBounds:bounds].height;
423 }
424
425 - (BOOL)outlineView:(NSOutlineView*)outlineView
426 shouldShowOutlineCellForItem:(id)item {
427 // The top most group header items are always expanded so hide their
428 // disclosure trianggles.
429 return ![[item objectForKey:kIsGroupItemKey] boolValue];
430 }
431
432 - (void)outlineView:(NSOutlineView*)outlineView
433 willDisplayCell:(id)cell
434 forTableColumn:(NSTableColumn *)tableColumn
435 item:(id)item {
436 if ([[item objectForKey:kIsGroupItemKey] boolValue])
437 [cell setFont:[NSFont boldSystemFontOfSize:11.0]];
438 else
439 [cell setFont:[NSFont systemFontOfSize:11.0]];
440 }
441
442 - (void)outlineView:(NSOutlineView *)outlineView
443 willDisplayOutlineCell:(id)cell
444 forTableColumn:(NSTableColumn *)tableColumn
445 item:(id)item {
446 // Replace disclosure triangles with bullet lists for leaf nodes.
447 if (![[item objectForKey:kCanExpandKey] boolValue]) {
448 [cell setImagePosition:NSNoImage];
449 DrawBulletInFrame([outlineView_ frameOfOutlineCellAtRow:
450 [outlineView_ rowForItem:item]]);
451 } else {
452 // Reset image to default value.
453 [cell setImagePosition:NSImageOverlaps];
454 }
455 }
456
457 - (BOOL)outlineView:(NSOutlineView *)outlineView
458 shouldSelectItem:(id)item {
459 return false;
460 }
461
462 - (NSDictionary*)buildItemWithTitle:(NSString*)title
463 isGroupItem:(BOOL)isGroupItem
464 children:(NSArray*)children {
465 BOOL canExpand = YES;
466 if (!children) {
467 // Add a dummy child even though this is a leaf node. This will cause
468 // the outline view to show a disclosure triangle for this item.
469 // This is later overriden in willDisplayOutlineCell: to draw a bullet
470 // instead. (The bullet could be placed in the title instead but then
471 // the bullet wouldn't line up with disclosure triangles of sibling nodes.)
472 children = [NSArray arrayWithObject:[NSDictionary dictionary]];
473 canExpand = NO;
474 }
475
476 return [NSDictionary dictionaryWithObjectsAndKeys:
477 title, kTitleKey,
478 [NSNumber numberWithBool:isGroupItem], kIsGroupItemKey,
479 children, kChildrenKey,
480 [NSNumber numberWithBool:canExpand], kCanExpandKey,
481 nil];
482 }
483
484 - (NSDictionary*)buildIssue:(const IssueAdviceInfoEntry&)issue {
485 if (issue.details.empty()) {
486 return [self buildItemWithTitle:SysUTF16ToNSString(issue.description)
487 isGroupItem:NO
488 children:nil];
489 }
490
491 NSMutableArray* details = [NSMutableArray array];
492 for (size_t j = 0; j < issue.details.size(); ++j) {
493 [details addObject:
494 [self buildItemWithTitle:SysUTF16ToNSString(issue.details[j])
495 isGroupItem:NO
496 children:nil]];
497 }
498 return [self buildItemWithTitle:SysUTF16ToNSString(issue.description)
499 isGroupItem:NO
500 children:details];
501 }
502
503 - (NSArray*)buildWarnings:(const ExtensionInstallPrompt::Prompt&)prompt {
504 NSMutableArray* warnings = [NSMutableArray array];
505
506 if (prompt.GetPermissionCount() > 0) {
507 NSMutableArray* children = [NSMutableArray array];
508 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) {
509 [children addObject:
510 [self buildItemWithTitle:SysUTF16ToNSString(prompt.GetPermission(i))
511 isGroupItem:NO
512 children:nil]];
513 }
514 [warnings addObject:[self
515 buildItemWithTitle:SysUTF16ToNSString(prompt.GetPermissionsHeading())
516 isGroupItem:YES
517 children:children]];
518 }
519
520 if (prompt.GetOAuthIssueCount() > 0) {
521 NSMutableArray* children = [NSMutableArray array];
522 for (size_t i = 0; i < prompt.GetOAuthIssueCount(); ++i)
523 [children addObject:[self buildIssue:prompt.GetOAuthIssue(i)]];
524 [warnings addObject:
525 [self buildItemWithTitle:SysUTF16ToNSString(prompt.GetOAuthHeading())
526 isGroupItem:YES
527 children:children]];
528 }
529
530 return warnings;
531 }
532
533
316 @end // ExtensionInstallDialogController 534 @end // ExtensionInstallDialogController
317 535
318 void ShowExtensionInstallDialogImpl( 536 void ShowExtensionInstallDialogImpl(
319 gfx::NativeWindow parent, 537 gfx::NativeWindow parent,
320 content::PageNavigator* navigator, 538 content::PageNavigator* navigator,
321 ExtensionInstallPrompt::Delegate* delegate, 539 ExtensionInstallPrompt::Delegate* delegate,
322 const ExtensionInstallPrompt::Prompt& prompt) { 540 const ExtensionInstallPrompt::Prompt& prompt) {
323 ExtensionInstallDialogController* controller = 541 ExtensionInstallDialogController* controller =
324 [[ExtensionInstallDialogController alloc] 542 [[ExtensionInstallDialogController alloc]
325 initWithParentWindow:parent 543 initWithParentWindow:parent
326 navigator:navigator 544 navigator:navigator
327 delegate:delegate 545 delegate:delegate
328 prompt:prompt]; 546 prompt:prompt];
329 547
330 // TODO(mihaip): Switch this to be tab-modal (http://crbug.com/95455) 548 // TODO(mihaip): Switch this to be tab-modal (http://crbug.com/95455)
331 [controller runAsModalSheet]; 549 [controller runAsModalSheet];
332 } 550 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698