1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_DOWNLOAD_BUBBLE_DOWNLOAD_BUBBLE_ROW_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_DOWNLOAD_BUBBLE_DOWNLOAD_BUBBLE_ROW_VIEW_H_
#include <string_view>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.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/ui/download/download_bubble_row_view_info.h"
#include "chrome/browser/ui/download/download_item_mode.h"
#include "chrome/browser/ui/views/controls/hover_button.h"
#include "chrome/browser/ui/views/download/bubble/download_bubble_row_list_view.h"
#include "components/download/public/common/download_item.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/mojom/menu_source_type.mojom-forward.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/view.h"
namespace ui {
class Event;
}
namespace views {
class ImageView;
class InputEventActivationProtector;
class Label;
class MdTextButton;
class ImageButton;
class ProgressBar;
class FlexLayoutView;
class InkDropContainerView;
} // namespace views
class DownloadShelfContextMenuView;
class DownloadBubbleUIController;
class DownloadBubbleRowView : public views::View,
public views::ContextMenuController,
public views::FocusChangeListener,
public DownloadBubbleRowViewInfoObserver {
METADATA_HEADER(DownloadBubbleRowView, views::View)
public:
DownloadBubbleRowView(
const DownloadBubbleRowViewInfo& info,
base::WeakPtr<DownloadBubbleUIController> bubble_controller,
base::WeakPtr<DownloadBubbleNavigationHandler> navigation_handler,
base::WeakPtr<Browser> browser,
int fixed_width);
DownloadBubbleRowView(const DownloadBubbleRowView&) = delete;
DownloadBubbleRowView& operator=(const DownloadBubbleRowView&) = delete;
~DownloadBubbleRowView() override;
// Overrides views::View:
void AddedToWidget() override;
void RemovedFromWidget() override;
void Layout(PassKey) override;
Views GetChildrenInZOrder() override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
void OnMouseCaptureLost() override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
gfx::Size CalculatePreferredSize(
const views::SizeBounds& /*available_size*/) const override;
void AddLayerToRegion(ui::Layer* layer, views::LayerRegion region) override;
void RemoveLayerFromRegions(ui::Layer* layer) override;
void VisibilityChanged(views::View* starting_from, bool is_visible) override;
// Overrides views::FocusChangeListener
void OnWillChangeFocus(views::View* before, views::View* now) override;
// Update the row and its elements for hover and focus events.
void UpdateRowForHover(bool hovered);
void UpdateRowForFocus(bool visible, bool request_focus_on_last_quick_action);
// Overrides views::ContextMenuController:
void ShowContextMenuForViewImpl(
View* source,
const gfx::Point& point,
ui::mojom::MenuSourceType source_type) override;
// Overrides ui::AcceleratorTarget
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
bool CanHandleAccelerators() const override;
// Returns the transparent button that is activated when the row is clicked.
views::Button* transparent_button() { return transparent_button_; }
std::u16string_view GetSecondaryLabelTextForTesting();
DownloadUIModel* model() { return info_->model(); }
const DownloadBubbleRowViewInfo& info() const { return *info_; }
void SimulateMainButtonClickForTesting(const ui::Event& event);
bool IsQuickActionButtonVisibleForTesting(DownloadCommands::Command command);
views::ImageButton* GetQuickActionButtonForTesting(
DownloadCommands::Command command);
void SetInputProtectorForTesting(
std::unique_ptr<views::InputEventActivationProtector> input_protector);
protected:
// Overrides ui::LayerDelegate:
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override;
private:
void AddMainPageButton(DownloadCommands::Command command,
const std::u16string& button_string);
void AddQuickAction(DownloadCommands::Command command);
std::u16string GetAccessibleNameForQuickAction(
DownloadCommands::Command command);
std::u16string GetAccessibleNameForMainPageButton(
DownloadCommands::Command command);
// Update the DownloadBubbleRowView's members.
void UpdateRow(bool initial_setup);
void UpdateStatusText();
void UpdateButtons();
void UpdateProgressBar();
void UpdateLabels();
void RecordMetricsOnUpdate();
void RecordDownloadDisplayed();
// Load the appropriate |file_icon_| from the IconManager, or a default icon.
// Returns whether we were able to synchronously set |icon_| to an appropriate
// icon for the file path.
bool StartLoadFileIcon();
// Callback invoked when the IconManager's lookup returns.
void OnFileIconLoaded(gfx::Image icon);
// Sets |icon_| to the image in |file_icon_|.
void SetFileIconAsIcon(bool is_default_icon);
// Set the |icon_|, which may be an override (warning or incognito icon),
// default icon, or loaded from the cache or from IconManager::LoadIcon.
void SetIcon();
// Sets |icon_| to |icon|, regardless of what kind of icon it is.
void SetIconFromImage(gfx::Image icon);
void SetIconFromImageModel(const ui::ImageModel& icon);
// Called when the transparent button (covering the whole row) is pressed.
void OnMainButtonPressed(const ui::Event& event);
// Called when the button on the side of the row (the "main page button") or a
// quick action button is pressed.
void OnActionButtonPressed(DownloadCommands::Command command,
const ui::Event& event);
// Registers/unregisters copy accelerator for copy/paste support.
void RegisterAccelerators(views::FocusManager* focus_manager);
void UnregisterAccelerators(views::FocusManager* focus_manager);
// DownloadBubbleRowViewInfoObserver implementation:
void OnInfoChanged() override;
// The icon for the file. We get platform-specific file type icons from
// IconLoader (see below).
raw_ptr<views::ImageView> icon_ = nullptr;
raw_ptr<views::ImageView> subpage_icon_ = nullptr;
raw_ptr<views::FlexLayoutView> subpage_icon_holder_ = nullptr;
// The icon for the filetype, fetched from the platform-specific IconLoader.
// This can differ from the image in |icon_| if |icon_| is not the file type
// icon, e.g. if it is the incognito icon or a warning icon. We cache it here
// in case |icon_| is different, because it is used when drag-and-dropping.
// If the IconLoader does not return a file icon, this stores a default icon.
gfx::Image file_icon_;
// The primary label.
raw_ptr<views::Label> primary_label_ = nullptr;
// The secondary label.
raw_ptr<views::Label> secondary_label_ = nullptr;
// Buttons on the main page.
base::flat_map<DownloadCommands::Command, raw_ptr<views::MdTextButton>>
main_page_buttons_;
// Quick Actions on the main page.
base::flat_map<DownloadCommands::Command, raw_ptr<views::ImageButton>>
quick_actions_;
// Holder for the main button.
raw_ptr<views::FlexLayoutView> main_button_holder_ = nullptr;
// Holder for the quick actions.
raw_ptr<views::FlexLayoutView> quick_action_holder_ = nullptr;
// The progress bar for in-progress downloads.
raw_ptr<views::ProgressBar> progress_bar_ = nullptr;
raw_ptr<views::FlexLayoutView> progress_bar_holder_ = nullptr;
// Device scale factor, used to load icons.
float current_scale_ = 1.0f;
// The model controlling this object's state.
raw_ref<const DownloadBubbleRowViewInfo> info_;
// Reuse the download shelf context menu in the bubble.
std::unique_ptr<DownloadShelfContextMenuView> context_menu_;
// Controller for keeping track of downloads.
base::WeakPtr<DownloadBubbleUIController> bubble_controller_ = nullptr;
base::WeakPtr<DownloadBubbleNavigationHandler> navigation_handler_ = nullptr;
base::WeakPtr<Browser> browser_ = nullptr;
// The last override icon, e.g. an incognito or warning icon. If this is
// null, we should either use the filetype icon or a default icon.
raw_ptr<const gfx::VectorIcon> last_overridden_icon_ = nullptr;
// Whether the currently set |icon_| is the default icon.
bool has_default_icon_ = false;
// Button for transparent button click, inkdrop animations and drag and drop
// events.
raw_ptr<views::Button> transparent_button_ = nullptr;
raw_ptr<views::InkDropContainerView> inkdrop_container_;
// Drag and drop:
// Whether we are dragging the download bubble row.
bool dragging_ = false;
// Position that a possible drag started at.
std::optional<gfx::Point> drag_start_point_;
// Whether the download's completion has already been logged. This is used to
// avoid inaccurate repeated logging.
bool has_download_completion_been_logged_ = false;
// A timer for updating the status text string.
base::RepeatingTimer update_status_text_timer_;
// Tracks tasks requesting file icons.
base::CancelableTaskTracker cancelable_task_tracker_;
// Mitigates the risk of clickjacking by enforcing a delay in click input.
std::unique_ptr<views::InputEventActivationProtector> input_protector_;
// TODO(crbug.com/40233803): The size constraint is not passed down from the
// views tree in the first round of layout, so setting a fixed width to bound
// the view. This is assuming that the row view is loaded inside a bubble. It
// will break if the row view is loaded inside a different parent view.
const int fixed_width_;
base::WeakPtrFactory<DownloadBubbleRowView> weak_factory_{this};
};
#endif // CHROME_BROWSER_UI_VIEWS_DOWNLOAD_BUBBLE_DOWNLOAD_BUBBLE_ROW_VIEW_H_
|