| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // A view that implements one download on the Download shelf. |
| // Each DownloadItemView contains an application icon, a text label |
| // indicating the download's file name, a text label indicating the |
| // download's status (such as the number of bytes downloaded so far) |
| // and a button for canceling an in progress download, or opening |
| // the completed download. |
| // |
| // The DownloadItemView lives in the Browser, and has a corresponding |
| // DownloadController that receives / writes data which lives in the |
| // Renderer. |
| |
| #ifndef CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H_ |
| #define CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H_ |
| |
| #include <memory> |
| #include <string> |
| |
| #include "base/callback_forward.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/optional.h" |
| #include "base/strings/string_util.h" |
| #include "base/task/cancelable_task_tracker.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/download/download_commands.h" |
| #include "chrome/browser/download/download_ui_model.h" |
| #include "chrome/browser/icon_manager.h" |
| #include "chrome/browser/ui/tab_modal_confirm_dialog.h" |
| #include "components/download/public/common/download_item.h" |
| #include "content/public/browser/download_manager.h" |
| #include "ui/gfx/font_list.h" |
| #include "ui/views/animation/animation_delegate_views.h" |
| #include "ui/views/context_menu_controller.h" |
| #include "ui/views/controls/button/button.h" |
| |
| class DownloadShelfView; |
| class DownloadShelfContextMenuView; |
| |
| namespace gfx { |
| class Image; |
| class ImageSkia; |
| class SlideAnimation; |
| } |
| |
| namespace views { |
| class ImageButton; |
| class Label; |
| class MdTextButton; |
| class StyledLabel; |
| } |
| |
| // Represents a single download item on the download shelf. Encompasses an icon, |
| // text, malicious download warnings, etc. |
| class DownloadItemView : public views::View, |
| public views::ButtonListener, |
| public views::ContextMenuController, |
| public DownloadUIModel::Observer, |
| public views::AnimationDelegateViews { |
| public: |
| enum class Mode; |
| |
| DownloadItemView(DownloadUIModel::DownloadUIModelPtr download, |
| DownloadShelfView* parent, |
| views::View* accessible_alert); |
| ~DownloadItemView() override; |
| |
| // views::View: |
| void Layout() override; |
| bool OnMouseDragged(const ui::MouseEvent& event) override; |
| void OnMouseCaptureLost() override; |
| base::string16 GetTooltipText(const gfx::Point& p) const override; |
| void GetAccessibleNodeData(ui::AXNodeData* node_data) override; |
| |
| // views::ButtonListener: |
| void ButtonPressed(views::Button* sender, const ui::Event& event) override; |
| |
| // views::ContextMenuController: |
| void ShowContextMenuForViewImpl(View* source, |
| const gfx::Point& point, |
| ui::MenuSourceType source_type) override; |
| |
| // DownloadUIModel::Observer: |
| void OnDownloadUpdated() override; |
| void OnDownloadOpened() override; |
| void OnDownloadDestroyed() override; |
| |
| // views::AnimationDelegateViews: |
| void AnimationProgressed(const gfx::Animation* animation) override; |
| |
| // Returns the DownloadUIModel object belonging to this item. |
| DownloadUIModel* model() { return model_.get(); } |
| const DownloadUIModel* model() const { return model_.get(); } |
| |
| // Submits download to download feedback service if the user has approved and |
| // the download is suitable for submission, then apply |download_command|. |
| // If user hasn't seen SBER opt-in text before, show SBER opt-in dialog first. |
| void MaybeSubmitDownloadToFeedbackService( |
| DownloadCommands::Command download_command); |
| |
| protected: |
| // views::View: |
| gfx::Size CalculatePreferredSize() const override; |
| void OnPaint(gfx::Canvas* canvas) override; |
| void OnThemeChanged() override; |
| |
| private: |
| enum State { NORMAL = 0, HOT, PUSHED }; |
| |
| static constexpr int kTextWidth = 140; |
| |
| // Padding before the icon and at end of the item. |
| static constexpr int kStartPadding = 12; |
| static constexpr int kEndPadding = 6; |
| |
| // Horizontal padding between progress indicator and filename/status text. |
| static constexpr int kProgressTextPadding = 8; |
| |
| // The space between the Save and Discard buttons when prompting for a |
| // dangerous download. |
| static constexpr int kSaveDiscardButtonPadding = 5; |
| |
| // The space on the right side of the dangerous download label. |
| static constexpr int kLabelPadding = 8; |
| |
| void OpenDownload(); |
| |
| // Submits the downloaded file to the safebrowsing download feedback service. |
| // Returns whether submission was successful. Applies |download_command|, if |
| // submission fails. |
| bool SubmitDownloadToFeedbackService( |
| DownloadCommands::Command download_command); |
| |
| // This function calculates the vertical coordinate to draw the file name text |
| // relative to local bounds. |
| int GetYForFilenameText() const; |
| |
| void DrawIcon(gfx::Canvas* canvas); |
| void LoadIcon(); |
| void LoadIconIfItemPathChanged(); |
| |
| // Update the button colors based on the current theme. |
| void UpdateColorsFromTheme(); |
| |
| void UpdateDropdownButton(); |
| |
| // Shows the context menu at the specified location. |point| is in the view's |
| // coordinate system. |
| void ShowContextMenuImpl(const gfx::Rect& rect, |
| ui::MenuSourceType source_type); |
| |
| // Sets the state and triggers a repaint. |
| void SetDropdownState(State new_state); |
| |
| void SetMode(Mode mode); |
| |
| // Starts showing the normal mode dialog, clearing the existing dialog. |
| void TransitionToNormalMode(); |
| |
| // Starts showing the mixed content dialog, clearing the existing dialog. |
| void TransitionToMixedContentDialog(); |
| |
| // Reverts from mixed content modes to normal download mode. |
| void ClearMixedContentDialog(); |
| |
| // Starts displaying the mixed content download warning. |
| void ShowMixedContentDialog(); |
| |
| // Starts showing the warning dialog, clearing the existing dialog. |
| void TransitionToWarningDialog(); |
| |
| // Reverts from dangerous mode to normal download mode. |
| void ClearWarningDialog(); |
| |
| // Starts displaying the dangerous download warning or the malicious download |
| // warning. |
| void ShowWarningDialog(); |
| |
| // Starts showing the deep scanning dialog, clearing the existing dialog. |
| void TransitionToDeepScanningDialog(); |
| |
| // Reverts from deep scanning mode to normal download mode. |
| void ClearDeepScanningDialog(); |
| |
| // Starts displaying the deep scanning warning. |
| void ShowDeepScanningDialog(); |
| |
| // Returns the current warning icon (should only be called when the view is |
| // actually showing a warning). |
| gfx::ImageSkia GetWarningIcon(); |
| |
| // Sets |size| with the size of the Save and Discard buttons (they have the |
| // same size). |
| gfx::Size GetButtonSize() const; |
| |
| // Returns either: |
| // * 200, if |label| can fit in one line given at most 200 DIP width. |
| // * The minimum width needed to display |label| on two lines. |
| int GetLabelWidth(const views::StyledLabel& label) const; |
| |
| // Reenables the item after it has been disabled when a user clicked it to |
| // open the downloaded file. |
| void Reenable(); |
| |
| // Releases drop down button after showing a context menu. |
| void ReleaseDropdown(); |
| |
| // Timer callback for handling animations |
| void StartDownloadProgress(); |
| void StopDownloadProgress(); |
| |
| // Update the accessible name to reflect the current state of the control, |
| // so that screenreaders can access the filename, status text, and |
| // dangerous download warning message (if any). The name will be presented |
| // when the download item receives focus. |
| void UpdateAccessibleName(); |
| |
| // Update accessible status text. |
| // If |is_last_update| is false, then a timer is used to notify screen readers |
| // to speak the alert text on a regular interval. If |is_last_update| is true, |
| // then the screen reader is notified of the request to speak the alert |
| // immediately, and any running timer is ended. |
| void UpdateAccessibleAlert(const base::string16& alert, bool is_last_update); |
| |
| // Get the accessible alert text for a download that is currently in progress. |
| base::string16 GetInProgressAccessibleAlertText(); |
| |
| // Callback for |accessible_update_timer_|, or can be used to ask a screen |
| // reader to speak the current alert immediately. |
| void AnnounceAccessibleAlert(); |
| |
| void OnExtractIconComplete(IconLoader::IconSize icon_size, gfx::Image icon); |
| |
| // Paint the common download animation progress foreground and background. If |
| // |percent_done| < 0, the total size is indeterminate. |
| // |indeterminate_progress_time| is only used in that case. |
| void PaintDownloadProgress(gfx::Canvas* canvas, |
| const gfx::RectF& bounds, |
| const base::TimeDelta& indeterminate_progress_time, |
| int percent_done) const; |
| |
| // Show/Hide/Reset |animation| based on the state transition specified by |
| // |from| and |to|. |
| void AnimateStateTransition(State from, |
| State to, |
| gfx::SlideAnimation* animation); |
| |
| // Callback for |progress_timer_|. |
| void ProgressTimerFired(); |
| |
| // Returns the status text to show in the notification. |
| base::string16 GetStatusText() const; |
| |
| // Returns the file name to report to user. It might be elided to fit into |
| // the text width. |
| base::string16 ElidedFilename(); |
| |
| // Opens a file while async scanning is still pending. |
| void OpenDownloadDuringAsyncScanning(); |
| |
| // Returns the height/width of the warning icon, in dp. |
| static int GetWarningIconSize(); |
| |
| // Returns the height/width of the error icon, in dp. |
| static int GetErrorIconSize(); |
| |
| // Starts deep scanning for this download item. |
| void ConfirmDeepScanning(); |
| |
| // Bypasses the prompt for deep scanning for this download item. |
| void BypassDeepScanning(); |
| |
| // The download shelf that owns us. |
| DownloadShelfView* shelf_; |
| |
| // The focus ring for this Button. |
| std::unique_ptr<views::FocusRing> focus_ring_; |
| |
| // The font list used to print the file name and warning text. |
| gfx::FontList font_list_; |
| |
| // The font list used to print the status text below the file name. |
| gfx::FontList status_font_list_; |
| |
| // The tooltip. Only displayed when not showing a warning dialog. |
| base::string16 tooltip_text_; |
| |
| // The current state (normal, hot or pushed) of the body and drop-down. |
| State dropdown_state_; |
| |
| // Mode of the download item view. |
| Mode mode_; |
| |
| // When download progress last began animating (pausing and resuming will |
| // update this). Used for downloads of unknown size. |
| base::TimeTicks progress_start_time_; |
| |
| // Keeps the amount of time spent already animating. Used to keep track of |
| // total active time for downloads of unknown size. |
| base::TimeDelta previous_progress_elapsed_; |
| |
| // Whether we are dragging the download button. |
| bool dragging_; |
| |
| // Position that a possible drag started at. |
| base::Optional<gfx::Point> drag_start_point_; |
| |
| // For canceling an in progress icon request. |
| base::CancelableTaskTracker cancelable_task_tracker_; |
| |
| // A model class to control the status text we display. |
| DownloadUIModel::DownloadUIModelPtr model_; |
| |
| // Animation for download complete. |
| std::unique_ptr<gfx::SlideAnimation> complete_animation_; |
| |
| // Progress animation |
| base::RepeatingTimer progress_timer_; |
| |
| // Dangerous mode and mixed content mode buttons. |
| views::MdTextButton* save_button_; |
| views::MdTextButton* discard_button_; |
| |
| // The file name label. |
| views::Label* file_name_label_; |
| |
| // The status text label. |
| views::Label* status_label_; |
| |
| // The "open download" button. This button is visually transparent and fills |
| // the entire bounds of the DownloadItemView, to make the DownloadItemView |
| // itself seem to be clickable while not requiring DownloadItemView itself to |
| // be a button. This is necessary because buttons are not allowed to have |
| // children in macOS Accessibility, and to avoid reimplementing much of the |
| // button logic in DownloadItemView. |
| views::Button* open_button_ = nullptr; |
| |
| // The drop down button. |
| views::ImageButton* dropdown_button_ = nullptr; |
| |
| // Dangerous mode label. Also used by mixed content warning. |
| views::StyledLabel* dangerous_download_label_; |
| |
| // Whether the dangerous mode label has been sized yet. |
| bool dangerous_download_label_sized_; |
| |
| // The time at which this view was created. |
| base::Time creation_time_; |
| |
| // The time at which a dangerous download warning was displayed. |
| base::Time time_download_warning_shown_; |
| |
| // The currently running download context menu. |
| std::unique_ptr<DownloadShelfContextMenuView> context_menu_; |
| |
| // The name of this view as reported to assistive technology. |
| base::string16 accessible_name_; |
| |
| // A hidden view for accessible status alerts, that are spoken by screen |
| // readers when a download changes state. |
| views::View* accessible_alert_; |
| |
| // A timer for accessible alerts that helps reduce the number of similar |
| // messages spoken in a short period of time. |
| base::RepeatingTimer accessible_alert_timer_; |
| |
| // Force the reading of the current alert text the next time it updates. |
| bool announce_accessible_alert_soon_; |
| |
| // The icon loaded in the download shelf is based on the file path of the |
| // item. Store the path used, so that we can detect a change in the path |
| // and reload the icon. |
| base::FilePath last_download_item_path_; |
| |
| // Deep scanning mode label. |
| views::StyledLabel* deep_scanning_label_ = nullptr; |
| |
| // Deep scanning open now button. |
| views::MdTextButton* open_now_button_ = nullptr; |
| |
| // Deep scanning modal dialog confirming choice to "open now". |
| TabModalConfirmDialog* open_now_modal_dialog_; |
| |
| // Icon for the download. |
| gfx::ImageSkia icon_; |
| |
| // Button used to consent to deep scanning. |
| views::MdTextButton* scan_button_ = nullptr; |
| |
| // Method factory used to delay reenabling of the item when opening the |
| // downloaded file. |
| base::WeakPtrFactory<DownloadItemView> weak_ptr_factory_{this}; |
| |
| DISALLOW_COPY_AND_ASSIGN(DownloadItemView); |
| }; |
| |
| #endif // CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H_ |