blob: f6f82f334a7da4b9f03ae555d9b284b4b4f7bdca [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller_platform_impl_desktop.h"
#include "base/functional/bind.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.h"
#include "chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.h"
#include "ui/views/widget/widget.h"
namespace {
// Returns the last active tabbed browser.
Browser* FindLastActiveTabbedBrowser() {
for (Browser* browser : BrowserList::GetInstance()->OrderedByActivation()) {
if (browser->is_type_normal()) {
return browser;
}
}
return nullptr;
}
} // namespace
RelaunchNotificationControllerPlatformImpl::
RelaunchNotificationControllerPlatformImpl() = default;
RelaunchNotificationControllerPlatformImpl::
~RelaunchNotificationControllerPlatformImpl() {
DCHECK(!widget_);
if (on_visible_)
BrowserList::RemoveObserver(this);
CHECK(!WidgetObserver::IsInObserverList());
CHECK(!BrowserListObserver::IsInObserverList());
}
void RelaunchNotificationControllerPlatformImpl::NotifyRelaunchRecommended(
base::Time detection_time,
bool /*past_deadline*/) {
// Nothing to do if the bubble is visible.
if (widget_)
return;
// Show the bubble in the most recently active browser.
Browser* browser = FindLastActiveTabbedBrowser();
if (!browser)
return;
widget_ = RelaunchRecommendedBubbleView::ShowBubble(
browser, detection_time, base::BindRepeating(&chrome::AttemptRelaunch));
// Monitor the widget so that |widget_| can be cleared on close.
widget_->AddObserver(this);
}
void RelaunchNotificationControllerPlatformImpl::NotifyRelaunchRequired(
base::Time deadline,
base::OnceCallback<base::Time()> on_visible) {
// Nothing to do if the dialog is visible.
if (widget_)
return;
// Show the dialog in the active tabbed browser window.
Browser* browser = chrome::FindBrowserWithActiveWindow();
if (browser && browser->is_type_normal()) {
DCHECK(!on_visible_);
ShowRequiredNotification(browser, deadline);
return;
}
// If the instance is not already waiting for one to become active from a
// previous call, start observing now.
if (!on_visible_)
BrowserList::AddObserver(this);
// Hold on to the callback until an active tabbed browser is found.
on_visible_ = std::move(on_visible);
last_relaunch_deadline_ = deadline;
}
void RelaunchNotificationControllerPlatformImpl::CloseRelaunchNotification() {
if (widget_)
widget_->Close();
if (on_visible_) {
BrowserList::RemoveObserver(this);
on_visible_.Reset();
last_relaunch_deadline_ = base::Time();
}
has_shown_ = false;
}
void RelaunchNotificationControllerPlatformImpl::SetDeadline(
base::Time deadline) {
// Nothing to do if the dialog hasn't been shown yet (because no tabbed
// browser has become active) or if the user has seen and dismissed the
// dialog.
if (widget_)
RelaunchRequiredDialogView::FromWidget(widget_)->SetDeadline(deadline);
// Hold on to the new deadline if the instance is waiting for a Browser to
// become active.
if (on_visible_)
last_relaunch_deadline_ = deadline;
}
bool RelaunchNotificationControllerPlatformImpl::IsRequiredNotificationShown()
const {
return widget_ != nullptr;
}
void RelaunchNotificationControllerPlatformImpl::OnWidgetDestroying(
views::Widget* widget) {
DCHECK_EQ(widget, widget_);
widget->RemoveObserver(this);
widget_ = nullptr;
}
void RelaunchNotificationControllerPlatformImpl::OnBrowserSetLastActive(
Browser* browser) {
// Ignore non-tabbed browsers.
if (!browser->is_type_normal())
return;
BrowserList::RemoveObserver(this);
base::Time new_deadline =
has_shown_ ? last_relaunch_deadline_ : std::move(on_visible_).Run();
DCHECK(!new_deadline.is_null());
on_visible_.Reset();
last_relaunch_deadline_ = base::Time();
ShowRequiredNotification(browser, new_deadline);
}
void RelaunchNotificationControllerPlatformImpl::ShowRequiredNotification(
Browser* browser,
base::Time deadline) {
widget_ = RelaunchRequiredDialogView::Show(
browser, deadline, base::BindRepeating(&chrome::AttemptRelaunch));
has_shown_ = true;
// Monitor the widget so that |widget_| can be cleared on close/destruction.
widget_->AddObserver(this);
}