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/time/time.h"
     26 #include "base/timer/timer.h"
     27 #include "chrome/browser/download/download_item_model.h"
     28 #include "chrome/browser/icon_manager.h"
     29 #include "chrome/common/cancelable_task_tracker.h"
     30 #include "content/public/browser/download_item.h"
     31 #include "content/public/browser/download_manager.h"
     32 #include "ui/base/animation/animation_delegate.h"
     33 #include "ui/gfx/font.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 }
     45 
     46 namespace ui {
     47 class SlideAnimation;
     48 }
     49 
     50 namespace views {
     51 class Label;
     52 class LabelButton;
     53 }
     54 
     55 class DownloadItemView : public views::ButtonListener,
     56                          public views::View,
     57                          public views::ContextMenuController,
     58                          public content::DownloadItem::Observer,
     59                          public ui::AnimationDelegate {
     60  public:
     61   DownloadItemView(content::DownloadItem* download,
     62                    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() 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                               string16* tooltip) const OVERRIDE;
     93   virtual void GetAccessibleState(ui::AccessibleViewState* 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   // ui::AnimationDelegate implementation.
    109   virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
    110 
    111  protected:
    112   // Overridden from views::View:
    113   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
    114 
    115  private:
    116   enum State {
    117     NORMAL = 0,
    118     HOT,
    119     PUSHED
    120   };
    121 
    122   enum Mode {
    123     NORMAL_MODE = 0,        // Showing download item.
    124     DANGEROUS_MODE,         // Displaying the dangerous download warning.
    125     MALICIOUS_MODE          // Displaying the malicious download warning.
    126   };
    127 
    128   // The image set associated with the part containing the icon and text.
    129   struct BodyImageSet {
    130     gfx::ImageSkia* top_left;
    131     gfx::ImageSkia* left;
    132     gfx::ImageSkia* bottom_left;
    133     gfx::ImageSkia* top;
    134     gfx::ImageSkia* center;
    135     gfx::ImageSkia* bottom;
    136     gfx::ImageSkia* top_right;
    137     gfx::ImageSkia* right;
    138     gfx::ImageSkia* bottom_right;
    139   };
    140 
    141   // The image set associated with the drop-down button on the right.
    142   struct DropDownImageSet {
    143     gfx::ImageSkia* top;
    144     gfx::ImageSkia* center;
    145     gfx::ImageSkia* bottom;
    146   };
    147 
    148   void OpenDownload();
    149 
    150   // Submit the downloaded file to the safebrowsing download feedback service.
    151   // If true is returned, the DownloadItem and |this| have been deleted.  If
    152   // false is returned, nothing has changed.
    153   bool BeginDownloadFeedback();
    154 
    155   void LoadIcon();
    156   void LoadIconIfItemPathChanged();
    157 
    158   // Update the button colors based on the current theme.
    159   void UpdateColorsFromTheme();
    160 
    161   // Shows the context menu at the specified location. |point| is in the view's
    162   // coordinate system.
    163   void ShowContextMenuImpl(const gfx::Point& point,
    164                            ui::MenuSourceType source_type);
    165 
    166   // Common code for handling pointer events (i.e. mouse or gesture).
    167   void HandlePressEvent(const ui::LocatedEvent& event, bool active_event);
    168   void HandleClickEvent(const ui::LocatedEvent& event, bool active_event);
    169 
    170   // Convenience method to paint the 3 vertical images (bottom, middle, top)
    171   // that form the background.
    172   void PaintImages(gfx::Canvas* canvas,
    173                     const gfx::ImageSkia* top_image,
    174                     const gfx::ImageSkia* center_image,
    175                     const gfx::ImageSkia* bottom_image,
    176                     int x,
    177                     int y,
    178                     int height,
    179                     int width);
    180 
    181   // Sets the state and triggers a repaint.
    182   void SetState(State body_state, State drop_down_state);
    183 
    184   // Whether we are in the dangerous mode.
    185   bool IsShowingWarningDialog() const {
    186     return mode_ == DANGEROUS_MODE || mode_ == MALICIOUS_MODE;
    187   }
    188 
    189   // Reverts from dangerous mode to normal download mode.
    190   void ClearWarningDialog();
    191 
    192   // Start displaying the dangerous download warning or the malicious download
    193   // warning.
    194   void ShowWarningDialog();
    195 
    196   // Sets |size| with the size of the Save and Discard buttons (they have the
    197   // same size).
    198   gfx::Size GetButtonSize();
    199 
    200   // Sizes the dangerous download label to a minimum width available using 2
    201   // lines.  The size is computed only the first time this method is invoked
    202   // and simply returned on subsequent calls.
    203   void SizeLabelToMinWidth();
    204 
    205   // Reenables the item after it has been disabled when a user clicked it to
    206   // open the downloaded file.
    207   void Reenable();
    208 
    209   // Releases drop down button after showing a context menu.
    210   void ReleaseDropDown();
    211 
    212   // Given |x|, returns whether |x| is within the x coordinate range of
    213   // the drop-down button or not.
    214   bool InDropDownButtonXCoordinateRange(int x);
    215 
    216   // Update the accessible name to reflect the current state of the control,
    217   // so that screenreaders can access the filename, status text, and
    218   // dangerous download warning message (if any).
    219   void UpdateAccessibleName();
    220 
    221   // Update the location of the drop down button.
    222   void UpdateDropDownButtonPosition();
    223 
    224   // Show/Hide/Reset |animation| based on the state transition specified by
    225   // |from| and |to|.
    226   void AnimateStateTransition(State from, State to,
    227                               ui::SlideAnimation* animation);
    228 
    229   // The different images used for the background.
    230   BodyImageSet normal_body_image_set_;
    231   BodyImageSet hot_body_image_set_;
    232   BodyImageSet pushed_body_image_set_;
    233   BodyImageSet dangerous_mode_body_image_set_;
    234   BodyImageSet malicious_mode_body_image_set_;
    235   DropDownImageSet normal_drop_down_image_set_;
    236   DropDownImageSet hot_drop_down_image_set_;
    237   DropDownImageSet pushed_drop_down_image_set_;
    238 
    239   // The warning icon showns for dangerous downloads.
    240   const gfx::ImageSkia* warning_icon_;
    241 
    242   // The download shelf that owns us.
    243   DownloadShelfView* shelf_;
    244 
    245   // Elements of our particular download
    246   string16 status_text_;
    247 
    248   // The font used to print the file name and status.
    249   gfx::Font font_;
    250 
    251   // The tooltip.  Only displayed when not showing a warning dialog.
    252   string16 tooltip_text_;
    253 
    254   // The current state (normal, hot or pushed) of the body and drop-down.
    255   State body_state_;
    256   State drop_down_state_;
    257 
    258   // Mode of the download item view.
    259   Mode mode_;
    260 
    261   // In degrees, for downloads with no known total size.
    262   int progress_angle_;
    263 
    264   // The left and right x coordinates of the drop-down button.
    265   int drop_down_x_left_;
    266   int drop_down_x_right_;
    267 
    268   // Used when we are showing the menu to show the drop-down as pressed.
    269   bool drop_down_pressed_;
    270 
    271   // The height of the box formed by the background images and its labels.
    272   int box_height_;
    273 
    274   // The y coordinate of the box formed by the background images and its labels.
    275   int box_y_;
    276 
    277   // Whether we are dragging the download button.
    278   bool dragging_;
    279 
    280   // Whether we are tracking a possible drag.
    281   bool starting_drag_;
    282 
    283   // Position that a possible drag started at.
    284   gfx::Point drag_start_point_;
    285 
    286   // For canceling an in progress icon request.
    287   CancelableTaskTracker cancelable_task_tracker_;
    288 
    289   // A model class to control the status text we display.
    290   DownloadItemModel model_;
    291 
    292   // Hover animations for our body and drop buttons.
    293   scoped_ptr<ui::SlideAnimation> body_hover_animation_;
    294   scoped_ptr<ui::SlideAnimation> drop_hover_animation_;
    295 
    296   // Animation for download complete.
    297   scoped_ptr<ui::SlideAnimation> complete_animation_;
    298 
    299   // Progress animation
    300   base::RepeatingTimer<DownloadItemView> progress_timer_;
    301 
    302   // Dangerous mode buttons.
    303   views::LabelButton* save_button_;
    304   views::LabelButton* discard_button_;
    305 
    306   // Dangerous mode label.
    307   views::Label* dangerous_download_label_;
    308 
    309   // Whether the dangerous mode label has been sized yet.
    310   bool dangerous_download_label_sized_;
    311 
    312   // The size of the buttons.  Cached so animation works when hidden.
    313   gfx::Size cached_button_size_;
    314 
    315   // Whether we are currently disabled as part of opening the downloaded file.
    316   bool disabled_while_opening_;
    317 
    318   // The time at which this view was created.
    319   base::Time creation_time_;
    320 
    321   // Method factory used to delay reenabling of the item when opening the
    322   // downloaded file.
    323   base::WeakPtrFactory<DownloadItemView> weak_ptr_factory_;
    324 
    325   // The currently running download context menu.
    326   scoped_ptr<DownloadShelfContextMenuView> context_menu_;
    327 
    328   // The name of this view as reported to assistive technology.
    329   string16 accessible_name_;
    330 
    331   // The icon loaded in the download shelf is based on the file path of the
    332   // item.  Store the path used, so that we can detect a change in the path
    333   // and reload the icon.
    334   base::FilePath last_download_item_path_;
    335 
    336   DISALLOW_COPY_AND_ASSIGN(DownloadItemView);
    337 };
    338 
    339 #endif  // CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H__
    340