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

Side by Side Diff: chrome/browser/ui/cocoa/download/download_item_controller.mm

Issue 533883002: [Mac] Re-layout download shelf when danger state of item changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix lifetime issues and add more tests Created 6 years, 3 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
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/download/download_item_controller.h" 5 #import "chrome/browser/ui/cocoa/download/download_item_controller.h"
6 6
7 #include "base/mac/bundle_locations.h" 7 #include "base/mac/bundle_locations.h"
8 #include "base/mac/mac_util.h" 8 #include "base/mac/mac_util.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/strings/string16.h" 10 #include "base/strings/string16.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 content::PageNavigator* navigator) 78 content::PageNavigator* navigator)
79 : DownloadShelfContextMenu(downloadItem, navigator) { } 79 : DownloadShelfContextMenu(downloadItem, navigator) { }
80 80
81 // DownloadShelfContextMenu::GetMenuModel is protected. 81 // DownloadShelfContextMenu::GetMenuModel is protected.
82 using DownloadShelfContextMenu::GetMenuModel; 82 using DownloadShelfContextMenu::GetMenuModel;
83 }; 83 };
84 84
85 @interface DownloadItemController (Private) 85 @interface DownloadItemController (Private)
86 - (void)themeDidChangeNotification:(NSNotification*)aNotification; 86 - (void)themeDidChangeNotification:(NSNotification*)aNotification;
87 - (void)updateTheme:(ui::ThemeProvider*)themeProvider; 87 - (void)updateTheme:(ui::ThemeProvider*)themeProvider;
88 - (void)setState:(DownoadItemState)state; 88 - (void)setState:(DownloadItemState)state;
89 - (void)initExperienceSamplingEvent:(const char*)event;
90 - (void)updateExperienceSamplingEvent:(const char*)event;
89 @end 91 @end
90 92
91 // Implementation of DownloadItemController 93 // Implementation of DownloadItemController
92 94
93 @implementation DownloadItemController 95 @implementation DownloadItemController
94 96
95 - (id)initWithDownload:(DownloadItem*)downloadItem 97 - (id)initWithDownload:(DownloadItem*)downloadItem
96 shelf:(DownloadShelfController*)shelf 98 shelf:(DownloadShelfController*)shelf
97 navigator:(content::PageNavigator*)navigator { 99 navigator:(content::PageNavigator*)navigator {
98 if ((self = [super initWithNibName:@"DownloadItem" 100 if ((self = [super initWithNibName:@"DownloadItem"
(...skipping 12 matching lines...) Expand all
111 state_ = kNormal; 113 state_ = kNormal;
112 creationTime_ = base::Time::Now(); 114 creationTime_ = base::Time::Now();
113 font_list_.reset(new gfx::FontList( 115 font_list_.reset(new gfx::FontList(
114 ui::ResourceBundle::GetSharedInstance().GetFontList( 116 ui::ResourceBundle::GetSharedInstance().GetFontList(
115 ui::ResourceBundle::BaseFont))); 117 ui::ResourceBundle::BaseFont)));
116 } 118 }
117 return self; 119 return self;
118 } 120 }
119 121
120 - (void)dealloc { 122 - (void)dealloc {
121 if (sampling_event_.get()) 123 [self updateExperienceSamplingEvent:ExperienceSamplingEvent::kIgnore];
122 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kIgnore);
123 [[NSNotificationCenter defaultCenter] removeObserver:self]; 124 [[NSNotificationCenter defaultCenter] removeObserver:self];
124 [progressView_ setController:nil]; 125 [progressView_ setController:nil];
125 [[self view] removeFromSuperview]; 126 [[self view] removeFromSuperview];
126 [super dealloc]; 127 [super dealloc];
127 } 128 }
128 129
129 - (void)awakeFromNib { 130 - (void)awakeFromNib {
130 [progressView_ setController:self]; 131 [progressView_ setController:self];
131 132
132 GTMUILocalizerAndLayoutTweaker* localizerAndLayoutTweaker = 133 GTMUILocalizerAndLayoutTweaker* localizerAndLayoutTweaker =
133 [[[GTMUILocalizerAndLayoutTweaker alloc] init] autorelease]; 134 [[[GTMUILocalizerAndLayoutTweaker alloc] init] autorelease];
134 [localizerAndLayoutTweaker applyLocalizer:localizer_ tweakingUI:[self view]]; 135 [localizerAndLayoutTweaker applyLocalizer:localizer_ tweakingUI:[self view]];
135 136
136 [self setStateFromDownload:bridge_->download_model()]; 137 [self setStateFromDownload:bridge_->download_model()];
137 138
138 bridge_->LoadIcon(); 139 bridge_->LoadIcon();
139 [self updateToolTip]; 140 [self updateToolTip];
140 } 141 }
141 142
142 - (void)showDangerousWarning:(DownloadItemModel*)downloadModel { 143 - (void)showDangerousWarning:(DownloadItemModel*)downloadModel {
143 // The transition from safe -> dangerous should only happen once. The code 144 // The transition from safe -> dangerous should only happen once. The code
144 // assumes that the danger type of the download doesn't change once it's set. 145 // assumes that the danger type of the download doesn't change once it's set.
145 if ([self isDangerousMode]) 146 if ([self isDangerousMode])
146 return; 147 return;
147 148
148 [self setState:kDangerous]; 149 [self setState:kDangerous];
149 150
150 // ExperienceSampling: Dangerous or malicious download warning is being shown 151 // ExperienceSampling: Dangerous or malicious download warning is being shown
151 // to the user, so we start a new SamplingEvent and track it. 152 // to the user, so we start a new SamplingEvent and track it.
152 std::string event_name = downloadModel->MightBeMalicious() 153 const char* event_name = downloadModel->MightBeMalicious()
153 ? ExperienceSamplingEvent::kMaliciousDownload 154 ? ExperienceSamplingEvent::kMaliciousDownload
154 : ExperienceSamplingEvent::kDangerousDownload; 155 : ExperienceSamplingEvent::kDangerousDownload;
155 sampling_event_.reset(new ExperienceSamplingEvent( 156 [self updateExperienceSamplingEvent:event_name];
156 event_name,
157 downloadModel->download()->GetURL(),
158 downloadModel->download()->GetReferrerUrl(),
159 downloadModel->download()->GetBrowserContext()));
160 157
161 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 158 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
162 NSImage* alertIcon; 159 NSImage* alertIcon;
163 160
164 NSString* dangerousWarning = base::SysUTF16ToNSString( 161 NSString* dangerousWarning = base::SysUTF16ToNSString(
165 downloadModel->GetWarningText(*font_list_, kTextWidth)); 162 downloadModel->GetWarningText(*font_list_, kTextWidth));
166 DCHECK(dangerousWarning); 163 DCHECK(dangerousWarning);
167 [dangerousDownloadLabel_ setStringValue:dangerousWarning]; 164 [dangerousDownloadLabel_ setStringValue:dangerousWarning];
168 CGFloat labelWidthChange = 165 CGFloat labelWidthChange =
169 [GTMUILocalizerAndLayoutTweaker 166 [GTMUILocalizerAndLayoutTweaker
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 NSPoint frameOrigin = [dangerousButtonTweaker_ frame].origin; 200 NSPoint frameOrigin = [dangerousButtonTweaker_ frame].origin;
204 frameOrigin.x += labelWidthChange; 201 frameOrigin.x += labelWidthChange;
205 [dangerousButtonTweaker_ setFrameOrigin:frameOrigin]; 202 [dangerousButtonTweaker_ setFrameOrigin:frameOrigin];
206 203
207 [dangerousButtonTweaker_ setHidden:NO]; 204 [dangerousButtonTweaker_ setHidden:NO];
208 [maliciousButtonTweaker_ setHidden:YES]; 205 [maliciousButtonTweaker_ setHidden:YES];
209 } 206 }
210 DCHECK(alertIcon); 207 DCHECK(alertIcon);
211 [image_ setImage:alertIcon]; 208 [image_ setImage:alertIcon];
212 209
213 // Grow the parent views
214 WidenView([self view], labelWidthChange + buttonWidthChange);
215 WidenView(dangerousDownloadView_, labelWidthChange + buttonWidthChange); 210 WidenView(dangerousDownloadView_, labelWidthChange + buttonWidthChange);
211 [shelf_ layoutItems];
216 } 212 }
217 213
218 - (void)setStateFromDownload:(DownloadItemModel*)downloadModel { 214 - (void)setStateFromDownload:(DownloadItemModel*)downloadModel {
219 DCHECK_EQ([self download], downloadModel->download()); 215 DCHECK_EQ([self download], downloadModel->download());
220 216
221 // Handle dangerous downloads. 217 // Handle dangerous downloads.
222 if (downloadModel->IsDangerous()) { 218 if (downloadModel->IsDangerous()) {
223 [self showDangerousWarning:downloadModel]; 219 [self showDangerousWarning:downloadModel];
224 return; 220 return;
225 } 221 }
226 222
227 // Set path to draggable download on completion. 223 // Set path to draggable download on completion.
228 if (downloadModel->download()->GetState() == DownloadItem::COMPLETE) 224 if (downloadModel->download()->GetState() == DownloadItem::COMPLETE)
229 [progressView_ setDownload:downloadModel->download()->GetTargetFilePath()]; 225 [progressView_ setDownload:downloadModel->download()->GetTargetFilePath()];
230 226
231 [cell_ setStateFromDownload:downloadModel]; 227 [cell_ setStateFromDownload:downloadModel];
232 } 228 }
233 229
234 - (void)setIcon:(NSImage*)icon { 230 - (void)setIcon:(NSImage*)icon {
235 [cell_ setImage:icon]; 231 [cell_ setImage:icon];
236 } 232 }
237 233
238 - (void)remove { 234 - (void)remove {
239 // We are deleted after this! 235 // We are deleted after this!
236 // If the download is destroyed before DownloadItemController, then we'd end
237 // up here. Reset the bridege_ so that it can clean up after itself before
238 // the DownloadItemController is deallocd.
239 bridge_.reset();
240 [shelf_ remove:self]; 240 [shelf_ remove:self];
241 } 241 }
242 242
243 - (void)updateVisibility:(id)sender { 243 - (void)updateVisibility:(id)sender {
244 if ([[self view] window]) 244 if ([[self view] window])
245 [self updateTheme:[[[self view] window] themeProvider]]; 245 [self updateTheme:[[[self view] window] themeProvider]];
246 246
247 NSView* view = [self view]; 247 NSView* view = [self view];
248 NSRect containerFrame = [[view superview] frame]; 248 NSRect containerFrame = [[view superview] frame];
249 [view setHidden:(NSMaxX([view frame]) > NSWidth(containerFrame))]; 249 [view setHidden:(NSMaxX([view frame]) > NSWidth(containerFrame))];
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 // The state change hide the dangerouse download view and is now showing the 290 // The state change hide the dangerouse download view and is now showing the
291 // download progress view. This means the view is likely to be a different 291 // download progress view. This means the view is likely to be a different
292 // size, so trigger a shelf layout to fix up spacing. 292 // size, so trigger a shelf layout to fix up spacing.
293 [shelf_ layoutItems]; 293 [shelf_ layoutItems];
294 } 294 }
295 295
296 - (BOOL)isDangerousMode { 296 - (BOOL)isDangerousMode {
297 return state_ == kDangerous; 297 return state_ == kDangerous;
298 } 298 }
299 299
300 - (void)setState:(DownoadItemState)state { 300 - (void)setState:(DownloadItemState)state {
301 if (state_ == state) 301 if (state_ == state)
302 return; 302 return;
303 state_ = state; 303 state_ = state;
304 if (state_ == kNormal) { 304 if (state_ == kNormal) {
305 [progressView_ setHidden:NO]; 305 [progressView_ setHidden:NO];
306 [dangerousDownloadView_ setHidden:YES]; 306 [dangerousDownloadView_ setHidden:YES];
307 } else { 307 } else {
308 DCHECK_EQ(kDangerous, state_); 308 DCHECK_EQ(kDangerous, state_);
309 [progressView_ setHidden:YES]; 309 [progressView_ setHidden:YES];
310 [dangerousDownloadView_ setHidden:NO]; 310 [dangerousDownloadView_ setHidden:NO];
(...skipping 11 matching lines...) Expand all
322 // Adapt appearance to the current theme. Called after theme changes and before 322 // Adapt appearance to the current theme. Called after theme changes and before
323 // this is shown for the first time. 323 // this is shown for the first time.
324 - (void)updateTheme:(ui::ThemeProvider*)themeProvider { 324 - (void)updateTheme:(ui::ThemeProvider*)themeProvider {
325 if (!themeProvider) 325 if (!themeProvider)
326 return; 326 return;
327 327
328 NSColor* color = themeProvider->GetNSColor(ThemeProperties::COLOR_TAB_TEXT); 328 NSColor* color = themeProvider->GetNSColor(ThemeProperties::COLOR_TAB_TEXT);
329 [dangerousDownloadLabel_ setTextColor:color]; 329 [dangerousDownloadLabel_ setTextColor:color];
330 } 330 }
331 331
332 - (void)initExperienceSamplingEvent:(const char*)event {
333 sampling_event_.reset(new ExperienceSamplingEvent(
334 event,
335 bridge_->download_model()->download()->GetURL(),
336 bridge_->download_model()->download()->GetReferrerUrl(),
337 bridge_->download_model()->download()->GetBrowserContext()));
338 }
339
340 - (void)updateExperienceSamplingEvent:(const char*)event {
341 if (sampling_event_.get()) {
342 sampling_event_->CreateUserDecisionEvent(event);
343 sampling_event_.reset(NULL);
344 }
345 }
346
332 - (IBAction)saveDownload:(id)sender { 347 - (IBAction)saveDownload:(id)sender {
333 // The user has confirmed a dangerous download. We record how quickly the 348 // The user has confirmed a dangerous download. We record how quickly the
334 // user did this to detect whether we're being clickjacked. 349 // user did this to detect whether we're being clickjacked.
335 UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download", 350 UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download",
336 base::Time::Now() - creationTime_); 351 base::Time::Now() - creationTime_);
337 // ExperienceSampling: User chose to proceed with dangerous download. 352 // ExperienceSampling: User chose to proceed with dangerous download.
338 if (sampling_event_.get()) { 353 [self updateExperienceSamplingEvent:ExperienceSamplingEvent::kProceed];
339 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kProceed);
340 sampling_event_.reset(NULL);
341 }
342 // This will change the state and notify us. 354 // This will change the state and notify us.
343 bridge_->download_model()->download()->ValidateDangerousDownload(); 355 bridge_->download_model()->download()->ValidateDangerousDownload();
344 } 356 }
345 357
346 - (IBAction)discardDownload:(id)sender { 358 - (IBAction)discardDownload:(id)sender {
347 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", 359 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download",
348 base::Time::Now() - creationTime_); 360 base::Time::Now() - creationTime_);
349 DownloadItem* download = bridge_->download_model()->download(); 361 DownloadItem* download = bridge_->download_model()->download();
350 download->Remove(); 362 download->Remove();
351 // WARNING: we are deleted at this point. Don't access 'this'. 363 // WARNING: we are deleted at this point. Don't access 'this'.
352 } 364 }
353 365
354 - (IBAction)dismissMaliciousDownload:(id)sender { 366 - (IBAction)dismissMaliciousDownload:(id)sender {
355 // ExperienceSampling: User dismissed the dangerous download. 367 // ExperienceSampling: User dismissed the dangerous download.
356 if (sampling_event_.get()) { 368 [self updateExperienceSamplingEvent:ExperienceSamplingEvent::kDeny];
357 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kDeny);
358 sampling_event_.reset(NULL);
359 }
360 [self remove]; 369 [self remove];
361 // WARNING: we are deleted at this point. 370 // WARNING: we are deleted at this point.
362 } 371 }
363 372
364 - (IBAction)showContextMenu:(id)sender { 373 - (IBAction)showContextMenu:(id)sender {
365 base::scoped_nsobject<DownloadShelfContextMenuController> menuController( 374 base::scoped_nsobject<DownloadShelfContextMenuController> menuController(
366 [[DownloadShelfContextMenuController alloc] 375 [[DownloadShelfContextMenuController alloc]
367 initWithItemController:self 376 initWithItemController:self
368 withDelegate:nil]); 377 withDelegate:nil]);
369 [NSMenu popUpContextMenu:[menuController menu] 378 [NSMenu popUpContextMenu:[menuController menu]
370 withEvent:[NSApp currentEvent] 379 withEvent:[NSApp currentEvent]
371 forView:[self view]]; 380 forView:[self view]];
372 } 381 }
373 382
374 @end 383 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698