• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 class DownloadShelfView;
39 class DownloadShelfContextMenuView;
40 
41 namespace gfx {
42 class Image;
43 class ImageSkia;
44 class SlideAnimation;
45 }
46 
47 namespace views {
48 class Label;
49 class LabelButton;
50 }
51 
52 class 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.
download()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.
IsShowingWarningDialog()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