// Copyright 2019 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_UPDATER_WIN_UI_PROGRESS_WND_H_
#define CHROME_UPDATER_WIN_UI_PROGRESS_WND_H_
#include <windows.h>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "chrome/updater/app/app_install_progress.h"
#include "chrome/updater/win/ui/complete_wnd.h"
#include "chrome/updater/win/ui/owner_draw_controls.h"
#include "chrome/updater/win/ui/resources/resources.grh"
#include "url/gurl.h"
namespace base {
class TimeDelta;
} // namespace base
namespace updater::ui {
// Used to communicate between InstallStoppedWnd and ProgressWnd.
inline constexpr unsigned int WM_INSTALL_STOPPED = WM_APP;
class ProgressWndEvents : public CompleteWndEvents {
public:
// Restarts the running browsers.
// If |restart_all_browsers| is true, all known browsers will be restarted.
virtual bool DoRestartBrowser(bool restart_all_browsers,
const std::vector<GURL>& urls) = 0;
// Initiates a reboot and returns whether it was initiated successfully.
virtual bool DoReboot() = 0;
// Indicates that current operation is cancelled.
virtual void DoCancel() = 0;
};
// Implements the "Installation Stopped" window. |InstallStoppedWnd| is
// modal relative to its parent. When the window is closed it sends
// a user message to its parent to notify which button the user has clicked on.
class InstallStoppedWnd : public CAxDialogImpl<InstallStoppedWnd>,
public OwnerDrawTitleBar,
public CustomDlgColors,
public WTL::CMessageFilter {
using Base = CAxDialogImpl<InstallStoppedWnd>;
public:
static constexpr int IDD = IDD_INSTALL_STOPPED;
InstallStoppedWnd(WTL::CMessageLoop* message_loop, HWND parent);
InstallStoppedWnd(const InstallStoppedWnd&) = delete;
InstallStoppedWnd& operator=(const InstallStoppedWnd&) = delete;
~InstallStoppedWnd() override;
// Closes the window, handling transition back to the parent window.
HRESULT CloseWindow();
// Overrides for WTL::CMessageFilter.
BOOL PreTranslateMessage(MSG* msg) override;
BEGIN_MSG_MAP(InstallStoppedWnd)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(IDOK, OnClickButton)
COMMAND_ID_HANDLER(IDCANCEL, OnClickButton)
CHAIN_MSG_MAP(Base)
CHAIN_MSG_MAP(OwnerDrawTitleBar)
CHAIN_MSG_MAP(CustomDlgColors)
END_MSG_MAP()
private:
LRESULT OnInitDialog(UINT msg,
WPARAM wparam,
LPARAM lparam,
BOOL& handled); // NOLINT
LRESULT OnClickButton(WORD notify_code,
WORD id,
HWND wnd_ctl,
BOOL& handled); // NOLINT
LRESULT OnDestroy(UINT msg,
WPARAM wparam,
LPARAM lparam,
BOOL& handled); // NOLINT
SEQUENCE_CHECKER(sequence_checker_);
raw_ptr<WTL::CMessageLoop> message_loop_ = nullptr;
HWND parent_ = nullptr;
WTL::CFont default_font_;
};
// Implements the UI progress window.
class ProgressWnd : public CompleteWnd, public AppInstallProgress {
public:
ProgressWnd(WTL::CMessageLoop* message_loop, HWND parent);
ProgressWnd(const ProgressWnd&) = delete;
ProgressWnd& operator=(const ProgressWnd&) = delete;
~ProgressWnd() override;
void SetEventSink(ProgressWndEvents* ev);
BEGIN_MSG_MAP(ProgressWnd)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_INSTALL_STOPPED, OnInstallStopped)
COMMAND_HANDLER(IDC_BUTTON1, BN_CLICKED, OnClickedButton)
COMMAND_HANDLER(IDC_BUTTON2, BN_CLICKED, OnClickedButton)
COMMAND_HANDLER(IDC_CLOSE, BN_CLICKED, OnClickedButton)
CHAIN_MSG_MAP(CompleteWnd)
END_MSG_MAP()
private:
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, ClickedButton);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, OnInstallStopped);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, MaybeCloseWindow);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, GetBundleCompletionCode);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, DeterminePostInstallUrls);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, OnCheckingForUpdate);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, OnWaitingToDownload);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, OnWaitingRetryDownload);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, OnPause);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, OnComplete);
FRIEND_TEST_ALL_PREFIXES(ProgressWndTest, LaunchCmdLine);
enum class States {
STATE_INIT = 0,
STATE_CHECKING_FOR_UPDATE,
STATE_WAITING_TO_DOWNLOAD,
STATE_DOWNLOADING,
STATE_WAITING_TO_INSTALL,
STATE_INSTALLING,
STATE_PAUSED,
STATE_COMPLETE_SUCCESS,
STATE_COMPLETE_ERROR,
STATE_COMPLETE_RESTART_BROWSER,
STATE_COMPLETE_RESTART_ALL_BROWSERS,
STATE_COMPLETE_REBOOT,
STATE_END,
};
static CompletionCodes GetBundleCompletionCode(
const ObserverCompletionInfo& info);
static std::wstring GetBundleCompletionErrorMessages(
const ObserverCompletionInfo& info);
// Overrides for AppInstallProgress.
// These functions are called on the thread which owns this window.
void OnCheckingForUpdate() override;
void OnUpdateAvailable(const std::string& app_id,
const std::u16string& app_name,
const base::Version& version) override;
void OnWaitingToDownload(const std::string& app_id,
const std::u16string& app_name) override;
void OnDownloading(const std::string& app_id,
const std::u16string& app_name,
const std::optional<base::TimeDelta> time_remaining,
int pos) override;
void OnWaitingRetryDownload(const std::string& app_id,
const std::u16string& app_name,
const base::Time& next_retry_time) override;
void OnWaitingToInstall(const std::string& app_id,
const std::u16string& app_name) override;
void OnInstalling(const std::string& app_id,
const std::u16string& app_name,
const std::optional<base::TimeDelta> time_remaining,
int pos) override;
void OnPause() override;
void OnComplete(const ObserverCompletionInfo& observer_info) override;
LRESULT OnInitDialog(UINT msg,
WPARAM wparam,
LPARAM lparam,
BOOL& handled); // NOLINT
LRESULT OnInstallStopped(UINT msg,
WPARAM wparam,
LPARAM lparam,
BOOL& handled); // NOLINT
LRESULT OnClickedButton(WORD notify_code,
WORD id,
HWND wnd_ctl,
BOOL& handled); // NOLINT
// Returns true if this window is closed.
bool MaybeCloseWindow() override;
HRESULT ChangeControlState();
HRESULT SetMarqueeMode(bool is_marquee);
bool IsInstallStoppedWindowPresent();
void HandleCancelRequest();
// Returns true if the |InstallStoppedWnd| window is closed.
bool CloseInstallStoppedWindow();
void DeterminePostInstallUrls(const ObserverCompletionInfo& info);
SEQUENCE_CHECKER(sequence_checker_);
States cur_state_ = States::STATE_INIT;
std::unique_ptr<InstallStoppedWnd> install_stopped_wnd_;
raw_ptr<ProgressWndEvents> events_sink_ = nullptr;
std::vector<GURL> post_install_urls_;
bool is_canceled_ = false;
struct ControlState {
const int id;
const ControlAttributes attr[static_cast<size_t>(States::STATE_END) + 1];
};
static const ControlState ctls_[];
// The speed by which the progress bar moves in marquee mode.
static constexpr int kMarqueeModeUpdatesMs = 75;
};
} // namespace updater::ui
#endif // CHROME_UPDATER_WIN_UI_PROGRESS_WND_H_