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