Home | History | Annotate | Download | only in 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.
     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