blob: 93b96091cf8b83062080f0c14f93939fd14956e4 [file] [log] [blame]
// Copyright 2014 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/toolbar/app_menu_icon_controller.h"
#include "base/check_op.h"
#include "build/build_config.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/ui/global_error/global_error.h"
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/upgrade_detector/upgrade_detector.h"
#include "chrome/common/channel_info.h"
#include "components/version_info/channel.h"
#include "ui/gfx/paint_vector_icon.h"
namespace {
#if !BUILDFLAG(IS_CHROMEOS)
// Maps an upgrade level to a severity level. When |show_very_low_upgrade_level|
// is true, VERY_LOW through HIGH all return Severity::LOW. Otherwise, VERY_LOW
// is ignored and LOW through HIGH return their respective Severity level, with
// GRACE treated the same as HIGH.
AppMenuIconController::Severity SeverityFromUpgradeLevel(
bool show_very_low_upgrade_level,
UpgradeDetector::UpgradeNotificationAnnoyanceLevel level) {
if (show_very_low_upgrade_level) {
// Anything between kNone and kCritical is LOW for unstable desktop Chrome.
switch (level) {
case UpgradeDetector::UPGRADE_ANNOYANCE_NONE:
break;
case UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW:
case UpgradeDetector::UPGRADE_ANNOYANCE_LOW:
case UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED:
case UpgradeDetector::UPGRADE_ANNOYANCE_GRACE:
case UpgradeDetector::UPGRADE_ANNOYANCE_HIGH:
return AppMenuIconController::Severity::LOW;
case UpgradeDetector::UPGRADE_ANNOYANCE_CRITICAL:
return AppMenuIconController::Severity::HIGH;
}
} else {
switch (level) {
case UpgradeDetector::UPGRADE_ANNOYANCE_NONE:
break;
case UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW:
// kVeryLow is meaningless for stable channels.
return AppMenuIconController::Severity::NONE;
case UpgradeDetector::UPGRADE_ANNOYANCE_LOW:
return AppMenuIconController::Severity::LOW;
case UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED:
return AppMenuIconController::Severity::MEDIUM;
case UpgradeDetector::UPGRADE_ANNOYANCE_GRACE:
case UpgradeDetector::UPGRADE_ANNOYANCE_HIGH:
case UpgradeDetector::UPGRADE_ANNOYANCE_CRITICAL:
return AppMenuIconController::Severity::HIGH;
}
}
DCHECK_EQ(level, UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
return AppMenuIconController::Severity::NONE;
}
// Returns the app menu icon severity for a Global Error.
AppMenuIconController::Severity SeverityFromError(GlobalError* error) {
CHECK(error);
switch (error->GetSeverity()) {
case GlobalError::SEVERITY_LOW:
return AppMenuIconController::Severity::LOW;
case GlobalError::SEVERITY_MEDIUM:
return AppMenuIconController::Severity::MEDIUM;
case GlobalError::SEVERITY_HIGH:
return AppMenuIconController::Severity::HIGH;
}
NOTREACHED();
}
#endif // !BUILDFLAG(IS_CHROMEOS)
// Return true if the browser is updating on the dev or canary channels.
bool IsUnstableChannel() {
// Unbranded (Chromium) builds are on the UNKNOWN channel, so check explicitly
// for the Google Chrome channels that are considered "unstable". This ensures
// that Chromium builds get the default behavior.
const version_info::Channel channel = chrome::GetChannel();
return channel == version_info::Channel::DEV ||
channel == version_info::Channel::CANARY;
}
} // namespace
AppMenuIconController::AppMenuIconController(Profile* profile,
Delegate* delegate)
: AppMenuIconController(UpgradeDetector::GetInstance(), profile, delegate) {
}
AppMenuIconController::AppMenuIconController(UpgradeDetector* upgrade_detector,
Profile* profile,
Delegate* delegate)
: is_unstable_channel_(IsUnstableChannel()),
upgrade_detector_(upgrade_detector),
profile_(profile),
delegate_(delegate) {
DCHECK(profile_);
DCHECK(delegate_);
global_error_observation_.Observe(
GlobalErrorServiceFactory::GetForProfile(profile_));
upgrade_detector_->AddObserver(this);
}
AppMenuIconController::~AppMenuIconController() {
upgrade_detector_->RemoveObserver(this);
}
void AppMenuIconController::UpdateDelegate() {
delegate_->UpdateTypeAndSeverity(GetTypeAndSeverity());
}
AppMenuIconController::TypeAndSeverity
AppMenuIconController::GetTypeAndSeverity() const {
#if !BUILDFLAG(IS_CHROMEOS)
if (browser_defaults::kShowUpgradeMenuItem &&
upgrade_detector_->notify_upgrade()) {
UpgradeDetector::UpgradeNotificationAnnoyanceLevel level =
upgrade_detector_->upgrade_notification_stage();
// The severity may be NONE even if the detector has been notified of an
// update. This can happen for beta and stable channels once the VERY_LOW
// annoyance level is reached.
auto severity = SeverityFromUpgradeLevel(is_unstable_channel_, level);
if (severity != Severity::NONE) {
return {IconType::UPGRADE_NOTIFICATION, severity};
}
}
// If you change the severity here, make sure to also change the menu icon
// and the bubble icon.
if (auto* error = GlobalErrorServiceFactory::GetForProfile(profile_)
->GetHighestSeverityGlobalErrorWithAppMenuItem()) {
return {IconType::GLOBAL_ERROR, SeverityFromError(error)};
}
#endif
return {IconType::NONE, Severity::NONE};
}
void AppMenuIconController::OnGlobalErrorsChanged() {
UpdateDelegate();
}
void AppMenuIconController::OnUpgradeRecommended() {
UpdateDelegate();
}