blob: 36ede9b41d90de03dd51fa68d67b41f1a5ada1a5 [file] [log] [blame]
// Copyright 2021 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_DOWNLOAD_BUBBLE_DOWNLOAD_DISPLAY_CONTROLLER_H_
#define CHROME_BROWSER_DOWNLOAD_BUBBLE_DOWNLOAD_DISPLAY_CONTROLLER_H_
#include "base/power_monitor/power_observer.h"
#include "base/timer/timer.h"
#include "chrome/browser/download/bubble/download_icon_state.h"
#include "chrome/browser/download/offline_item_model.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_observer.h"
#include "components/download/content/public/all_download_item_notifier.h"
#include "components/offline_items_collection/core/offline_content_aggregator.h"
#include "components/offline_items_collection/core/offline_content_provider.h"
class DownloadBubbleUIController;
namespace base {
class TimeDelta;
class OneShotTimer;
} // namespace base
class DownloadDisplay;
// Used to control the DownloadToolbar Button, through the DownloadDisplay
// interface. Supports both regular Download and Offline items. When in the
// future OfflineItems include regular Download on Desktop platforms,
// we can remove AllDownloadItemNotifier::Observer.
// TODO(chlily): Consolidate this with DownloadBubbleUIController.
class DownloadDisplayController : public FullscreenObserver,
public base::PowerSuspendObserver {
public:
DownloadDisplayController(DownloadDisplay* display,
Browser* browser,
DownloadBubbleUIController* bubble_controller);
DownloadDisplayController(const DownloadDisplayController&) = delete;
DownloadDisplayController& operator=(const DownloadDisplayController&) =
delete;
~DownloadDisplayController() override;
// Information extracted from iterating over all models, to avoid having to do
// so multiple times.
struct AllDownloadUIModelsInfo {
// Number of models that would be returned to display.
size_t all_models_size = 0;
// The last time that a download was completed. Will be null if no downloads
// were completed.
base::Time last_completed_time;
// Whether there are any downloads actively doing deep scanning.
bool has_deep_scanning = false;
// Whether any downloads are unactioned.
bool has_unactioned = false;
// From the button UI's perspective, whether the download is considered in
// progress. Consider dangerous downloads as completed, because we don't
// want to encourage users to interact with them.
int in_progress_count = 0;
// Count of in-progress downloads (by the above definition) that are paused.
int paused_count = 0;
};
struct ProgressInfo {
bool progress_certain = true;
int progress_percentage = 0;
int download_count = 0;
};
struct IconInfo {
download::DownloadIconState icon_state =
download::DownloadIconState::kComplete;
bool is_active = false;
};
// Returns a ProgressInfo where |download_count| is the number of currently
// active downloads. If we know the final size of all downloads,
// |progress_certain| is true. |progress_percentage| is the percentage
// complete of all in-progress downloads. Forwards to the
// DownloadBubbleUpdateService.
ProgressInfo GetProgress();
// Returns an IconInfo that contains current state of the icon.
IconInfo GetIconInfo();
// Returns whether the display is showing details.
bool IsDisplayShowingDetails();
// Notifies the controller that the button is pressed. Called by `display_`.
void OnButtonPressed();
// Handles the button pressed event. Called by the profile level controller.
void HandleButtonPressed();
// Common methods for new downloads or new offline items.
// These methods are virtual so that they can be overridden for fake
// controllers in testing.
// Called from bubble controller when new item(s) are added.
// |show_animation| specifies whether a small animated arrow should be shown.
virtual void OnNewItem(bool show_animation);
// Called from bubble controller when an item is updated, with |is_done|
// indicating if it was marked done, and with |may_show_details| indicating
// whether the partial view can be shown. (Whether the partial view is
// actually shown may depend on the state of the other downloads.)
virtual void OnUpdatedItem(bool is_done, bool may_show_details);
// Called from bubble controller when an item is deleted.
virtual void OnRemovedItem(const ContentId& id);
// Asks `display_` to hide the toolbar button. Does nothing if the toolbar
// button is already hidden.
void HideToolbarButton();
// Asks `display_` to hide the toolbar button details. Does nothing if the
// details are already hidden.
void HideBubble();
// Start listening to full screen changes. This is separate from the
// constructor as the exclusive access manager is constructed after
// BrowserWindow.
void ListenToFullScreenChanges();
// FullScreenObserver
void OnFullscreenStateChanged() override;
// PowerSuspendObserver
void OnResume() override;
// Returns the DownloadDisplay. Should always return a valid display.
DownloadDisplay* download_display_for_testing() { return display_; }
private:
friend class DownloadDisplayControllerTest;
// Gets info about all models to display, then updates the toolbar button
// state accordingly. Returns the info about all models.
const AllDownloadUIModelsInfo& UpdateButtonStateFromAllModelsInfo();
// Stops and restarts `icon_disappearance_timer_`. The toolbar button will
// be hidden after the `interval`.
void ScheduleToolbarDisappearance(base::TimeDelta interval);
// Stops and restarts `icon_inactive_timer_`. The toolbar button will
// be changed to inactive state after the `interval`.
void ScheduleToolbarInactive(base::TimeDelta interval);
// Asks `display_` to show the toolbar button. Does nothing if the toolbar
// button is already showing.
void ShowToolbarButton();
// Updates the icon state of the `display_`.
void UpdateToolbarButtonState(const AllDownloadUIModelsInfo& info);
// Asks `display_` to make the download icon inactive.
void UpdateDownloadIconToInactive();
// Decides whether the toolbar button should be shown when it is created.
virtual void MaybeShowButtonWhenCreated();
// Whether the last download complete time is less than `interval` ago.
bool HasRecentCompleteDownload(base::TimeDelta interval,
base::Time last_complete_time);
base::Time GetLastCompleteTime(
base::Time last_completed_time_from_current_models) const;
// The pointer is created in ToolbarView and owned by ToolbarView.
raw_ptr<DownloadDisplay> const display_;
raw_ptr<Browser> browser_;
base::ScopedObservation<FullscreenController, FullscreenObserver>
observation_{this};
base::OneShotTimer icon_disappearance_timer_;
base::OneShotTimer icon_inactive_timer_;
IconInfo icon_info_;
bool fullscreen_notification_shown_ = false;
bool details_shown_while_fullscreen_ = false;
// DownloadDisplayController and DownloadBubbleUIController have the same
// lifetime. Both are owned, constructed together, and destructed together by
// DownloadToolbarButtonView. If one is valid, so is the other.
raw_ptr<DownloadBubbleUIController> bubble_controller_;
base::WeakPtrFactory<DownloadDisplayController> weak_factory_{this};
};
#endif // CHROME_BROWSER_DOWNLOAD_BUBBLE_DOWNLOAD_DISPLAY_CONTROLLER_H_