download_item_view.h revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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. 4// 5// A ChromeView that implements one download on the Download shelf. 6// Each DownloadItemView contains an application icon, a text label 7// indicating the download's file name, a text label indicating the 8// download's status (such as the number of bytes downloaded so far) 9// and a button for canceling an in progress download, or opening 10// the completed download. 11// 12// The DownloadItemView lives in the Browser, and has a corresponding 13// DownloadController that receives / writes data which lives in the 14// Renderer. 15 16#ifndef CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H__ 17#define CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H__ 18 19#include <string> 20 21#include "base/basictypes.h" 22#include "base/memory/scoped_ptr.h" 23#include "base/memory/weak_ptr.h" 24#include "base/strings/string_util.h" 25#include "base/task/cancelable_task_tracker.h" 26#include "base/time/time.h" 27#include "base/timer/timer.h" 28#include "chrome/browser/download/download_item_model.h" 29#include "chrome/browser/icon_manager.h" 30#include "content/public/browser/download_item.h" 31#include "content/public/browser/download_manager.h" 32#include "ui/gfx/animation/animation_delegate.h" 33#include "ui/gfx/font_list.h" 34#include "ui/views/context_menu_controller.h" 35#include "ui/views/controls/button/button.h" 36#include "ui/views/view.h" 37 38class DownloadShelfView; 39class DownloadShelfContextMenuView; 40 41namespace extensions { 42class ExperienceSamplingEvent; 43} 44 45namespace gfx { 46class Image; 47class ImageSkia; 48class SlideAnimation; 49} 50 51namespace views { 52class Label; 53class LabelButton; 54} 55 56class DownloadItemView : public views::ButtonListener, 57 public views::View, 58 public views::ContextMenuController, 59 public content::DownloadItem::Observer, 60 public gfx::AnimationDelegate { 61 public: 62 DownloadItemView(content::DownloadItem* download, DownloadShelfView* parent); 63 virtual ~DownloadItemView(); 64 65 // Timer callback for handling animations 66 void UpdateDownloadProgress(); 67 void StartDownloadProgress(); 68 void StopDownloadProgress(); 69 70 // IconManager::Client interface. 71 void OnExtractIconComplete(gfx::Image* icon); 72 73 // Returns the DownloadItem model object belonging to this item. 74 content::DownloadItem* download() { return model_.download(); } 75 76 // DownloadItem::Observer methods 77 virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE; 78 virtual void OnDownloadOpened(content::DownloadItem* download) OVERRIDE; 79 virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE; 80 81 // Overridden from views::View: 82 virtual void Layout() OVERRIDE; 83 virtual gfx::Size GetPreferredSize() const OVERRIDE; 84 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 85 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; 86 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; 87 virtual void OnMouseCaptureLost() OVERRIDE; 88 virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE; 89 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; 90 virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE; 91 virtual bool GetTooltipText(const gfx::Point& p, 92 base::string16* tooltip) const OVERRIDE; 93 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; 94 virtual void OnThemeChanged() OVERRIDE; 95 96 // Overridden from ui::EventHandler: 97 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; 98 99 // Overridden from views::ContextMenuController. 100 virtual void ShowContextMenuForView(View* source, 101 const gfx::Point& point, 102 ui::MenuSourceType source_type) OVERRIDE; 103 104 // ButtonListener implementation. 105 virtual void ButtonPressed(views::Button* sender, 106 const ui::Event& event) OVERRIDE; 107 108 // gfx::AnimationDelegate implementation. 109 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; 110 111 protected: 112 // Overridden from views::View: 113 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 114 virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE; 115 virtual void OnFocus() OVERRIDE; 116 virtual void OnBlur() OVERRIDE; 117 118 private: 119 enum State { 120 NORMAL = 0, 121 HOT, 122 PUSHED 123 }; 124 125 enum Mode { 126 NORMAL_MODE = 0, // Showing download item. 127 DANGEROUS_MODE, // Displaying the dangerous download warning. 128 MALICIOUS_MODE // Displaying the malicious download warning. 129 }; 130 131 // The image set associated with the part containing the icon and text. 132 struct BodyImageSet { 133 gfx::ImageSkia* top_left; 134 gfx::ImageSkia* left; 135 gfx::ImageSkia* bottom_left; 136 gfx::ImageSkia* top; 137 gfx::ImageSkia* center; 138 gfx::ImageSkia* bottom; 139 gfx::ImageSkia* top_right; 140 gfx::ImageSkia* right; 141 gfx::ImageSkia* bottom_right; 142 }; 143 144 // The image set associated with the drop-down button on the right. 145 struct DropDownImageSet { 146 gfx::ImageSkia* top; 147 gfx::ImageSkia* center; 148 gfx::ImageSkia* bottom; 149 }; 150 151 void OpenDownload(); 152 153 // Submits the downloaded file to the safebrowsing download feedback service. 154 // Returns whether submission was successful. On successful submission, 155 // |this| and the DownloadItem will have been deleted. 156 bool SubmitDownloadToFeedbackService(); 157 158 // If the user has |enabled| uploading, calls SubmitDownloadToFeedbackService. 159 // Otherwise, it simply removes the DownloadItem without uploading. 160 void PossiblySubmitDownloadToFeedbackService(bool enabled); 161 162 void LoadIcon(); 163 void LoadIconIfItemPathChanged(); 164 165 // Update the button colors based on the current theme. 166 void UpdateColorsFromTheme(); 167 168 // Shows the context menu at the specified location. |point| is in the view's 169 // coordinate system. 170 void ShowContextMenuImpl(const gfx::Point& point, 171 ui::MenuSourceType source_type); 172 173 // Common code for handling pointer events (i.e. mouse or gesture). 174 void HandlePressEvent(const ui::LocatedEvent& event, bool active_event); 175 void HandleClickEvent(const ui::LocatedEvent& event, bool active_event); 176 177 // Convenience method to paint the 3 vertical images (bottom, middle, top) 178 // that form the background. 179 void PaintImages(gfx::Canvas* canvas, 180 const gfx::ImageSkia* top_image, 181 const gfx::ImageSkia* center_image, 182 const gfx::ImageSkia* bottom_image, 183 int x, 184 int y, 185 int height, 186 int width); 187 188 // Sets the state and triggers a repaint. 189 void SetState(State body_state, State drop_down_state); 190 191 // Whether we are in the dangerous mode. 192 bool IsShowingWarningDialog() const { 193 return mode_ == DANGEROUS_MODE || mode_ == MALICIOUS_MODE; 194 } 195 196 // Reverts from dangerous mode to normal download mode. 197 void ClearWarningDialog(); 198 199 // Start displaying the dangerous download warning or the malicious download 200 // warning. 201 void ShowWarningDialog(); 202 203 // Sets |size| with the size of the Save and Discard buttons (they have the 204 // same size). 205 gfx::Size GetButtonSize() const; 206 207 // Sizes the dangerous download label to a minimum width available using 2 208 // lines. The size is computed only the first time this method is invoked 209 // and simply returned on subsequent calls. 210 void SizeLabelToMinWidth(); 211 212 // Reenables the item after it has been disabled when a user clicked it to 213 // open the downloaded file. 214 void Reenable(); 215 216 // Releases drop down button after showing a context menu. 217 void ReleaseDropDown(); 218 219 // Given |x|, returns whether |x| is within the x coordinate range of 220 // the drop-down button or not. 221 bool InDropDownButtonXCoordinateRange(int x); 222 223 // Update the accessible name to reflect the current state of the control, 224 // so that screenreaders can access the filename, status text, and 225 // dangerous download warning message (if any). 226 void UpdateAccessibleName(); 227 228 // Update the location of the drop down button. 229 void UpdateDropDownButtonPosition(); 230 231 // Show/Hide/Reset |animation| based on the state transition specified by 232 // |from| and |to|. 233 void AnimateStateTransition(State from, State to, 234 gfx::SlideAnimation* animation); 235 236 // The different images used for the background. 237 BodyImageSet normal_body_image_set_; 238 BodyImageSet hot_body_image_set_; 239 BodyImageSet pushed_body_image_set_; 240 BodyImageSet dangerous_mode_body_image_set_; 241 BodyImageSet malicious_mode_body_image_set_; 242 DropDownImageSet normal_drop_down_image_set_; 243 DropDownImageSet hot_drop_down_image_set_; 244 DropDownImageSet pushed_drop_down_image_set_; 245 246 // The warning icon showns for dangerous downloads. 247 const gfx::ImageSkia* warning_icon_; 248 249 // The download shelf that owns us. 250 DownloadShelfView* shelf_; 251 252 // Elements of our particular download 253 base::string16 status_text_; 254 255 // The font list used to print the file name and status. 256 gfx::FontList font_list_; 257 258 // The tooltip. Only displayed when not showing a warning dialog. 259 base::string16 tooltip_text_; 260 261 // The current state (normal, hot or pushed) of the body and drop-down. 262 State body_state_; 263 State drop_down_state_; 264 265 // Mode of the download item view. 266 Mode mode_; 267 268 // In degrees, for downloads with no known total size. 269 int progress_angle_; 270 271 // The left and right x coordinates of the drop-down button. 272 int drop_down_x_left_; 273 int drop_down_x_right_; 274 275 // Used when we are showing the menu to show the drop-down as pressed. 276 bool drop_down_pressed_; 277 278 // The height of the box formed by the background images and its labels. 279 int box_height_; 280 281 // The y coordinate of the box formed by the background images and its labels. 282 int box_y_; 283 284 // Whether we are dragging the download button. 285 bool dragging_; 286 287 // Whether we are tracking a possible drag. 288 bool starting_drag_; 289 290 // Position that a possible drag started at. 291 gfx::Point drag_start_point_; 292 293 // For canceling an in progress icon request. 294 base::CancelableTaskTracker cancelable_task_tracker_; 295 296 // A model class to control the status text we display. 297 DownloadItemModel model_; 298 299 // Hover animations for our body and drop buttons. 300 scoped_ptr<gfx::SlideAnimation> body_hover_animation_; 301 scoped_ptr<gfx::SlideAnimation> drop_hover_animation_; 302 303 // Animation for download complete. 304 scoped_ptr<gfx::SlideAnimation> complete_animation_; 305 306 // Progress animation 307 base::RepeatingTimer<DownloadItemView> progress_timer_; 308 309 // Dangerous mode buttons. 310 views::LabelButton* save_button_; 311 views::LabelButton* discard_button_; 312 313 // Dangerous mode label. 314 views::Label* dangerous_download_label_; 315 316 // Whether the dangerous mode label has been sized yet. 317 bool dangerous_download_label_sized_; 318 319 // The size of the buttons. Cached so animation works when hidden. 320 mutable gfx::Size cached_button_size_; 321 322 // Whether we are currently disabled as part of opening the downloaded file. 323 bool disabled_while_opening_; 324 325 // The time at which this view was created. 326 base::Time creation_time_; 327 328 // The time at which a dangerous download warning was displayed. 329 base::Time time_download_warning_shown_; 330 331 // The currently running download context menu. 332 scoped_ptr<DownloadShelfContextMenuView> context_menu_; 333 334 // The name of this view as reported to assistive technology. 335 base::string16 accessible_name_; 336 337 // The icon loaded in the download shelf is based on the file path of the 338 // item. Store the path used, so that we can detect a change in the path 339 // and reload the icon. 340 base::FilePath last_download_item_path_; 341 342 // ExperienceSampling: This tracks dangerous/malicious downloads warning UI 343 // and the user's decisions about it. 344 scoped_ptr<extensions::ExperienceSamplingEvent> sampling_event_; 345 346 // Method factory used to delay reenabling of the item when opening the 347 // downloaded file. 348 base::WeakPtrFactory<DownloadItemView> weak_ptr_factory_; 349 350 DISALLOW_COPY_AND_ASSIGN(DownloadItemView); 351}; 352 353#endif // CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H__ 354