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