blob: 29960f974c05bb5889a783a786326a21107b956b [file] [log] [blame]
xiaoyinhf39e3dd2016-06-18 04:50:231// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/eol_notification.h"
6
Evan Stade70e2ed42018-11-08 06:23:057#include "ash/public/cpp/notification_utils.h"
Sebastien Marchandf1349f52019-01-25 03:16:418#include "base/bind.h"
Regan Hsu62dc18f2019-10-03 20:30:449#include "base/i18n/time_formatting.h"
10#include "base/time/default_clock.h"
Evan Stade82ba4b62019-07-11 01:58:0111#include "chrome/app/vector_icons/vector_icons.h"
xiaoyinhf39e3dd2016-06-18 04:50:2312#include "chrome/browser/browser_process.h"
Hans Wennborg63344452019-10-15 10:15:2113#include "chrome/browser/browser_process_platform_part.h"
Sarah Hu4ad394b2017-11-27 19:03:0014#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
Evan Stadecc63b182017-09-26 16:05:1215#include "chrome/browser/notifications/notification_display_service.h"
16#include "chrome/browser/notifications/notification_display_service_factory.h"
xiaoyinhf39e3dd2016-06-18 04:50:2317#include "chrome/browser/ui/browser_navigator.h"
18#include "chrome/browser/ui/browser_navigator_params.h"
19#include "chrome/common/pref_names.h"
20#include "chrome/common/url_constants.h"
21#include "chrome/grit/generated_resources.h"
22#include "chromeos/dbus/dbus_thread_manager.h"
xiaoyinhf39e3dd2016-06-18 04:50:2323#include "components/prefs/pref_service.h"
dpapad943ef182018-01-20 02:58:2024#include "components/strings/grit/components_strings.h"
Regan Hsu62dc18f2019-10-03 20:30:4425#include "components/vector_icons/vector_icons.h"
xiaoyinhf39e3dd2016-06-18 04:50:2326#include "ui/base/l10n/l10n_util.h"
Vladislav Kaznacheeve9805222019-05-28 19:44:4027#include "ui/chromeos/devicetype_utils.h"
xiaoyinhaa17d8342016-06-30 22:56:0228#include "ui/gfx/color_palette.h"
29#include "ui/gfx/paint_vector_icon.h"
xiaoyinhf39e3dd2016-06-18 04:50:2330
Tetsui Ohkuboe8f95e82017-08-23 06:10:4731using l10n_util::GetStringUTF16;
xiaoyinhf39e3dd2016-06-18 04:50:2332
33namespace chromeos {
34namespace {
35
Evan Stadecc63b182017-09-26 16:05:1236const char kEolNotificationId[] = "chrome://product_eol";
xiaoyinhf39e3dd2016-06-18 04:50:2337
Regan Hsu62dc18f2019-10-03 20:30:4438constexpr int kFirstWarningDaysInAdvance = 180;
39constexpr int kSecondWarningDaysInAdvance = 90;
Evan Stadecc63b182017-09-26 16:05:1240
Regan Hsu62dc18f2019-10-03 20:30:4441base::Time FirstWarningDate(base::Time eol_date) {
42 return eol_date - base::TimeDelta::FromDays(kFirstWarningDaysInAdvance);
43}
Evan Stadecf27dae12017-11-07 23:57:5144
Regan Hsu62dc18f2019-10-03 20:30:4445base::Time SecondWarningDate(const base::Time& eol_date) {
46 return eol_date - base::TimeDelta::FromDays(kSecondWarningDaysInAdvance);
47}
Evan Stadecf27dae12017-11-07 23:57:5148
xiaoyinhf39e3dd2016-06-18 04:50:2349} // namespace
50
Sarah Hu4ad394b2017-11-27 19:03:0051// static
52bool EolNotification::ShouldShowEolNotification() {
Sarah Hu4ad394b2017-11-27 19:03:0053 // Do not show end of life notification if this device is managed by
54 // enterprise user.
55 if (g_browser_process->platform_part()
56 ->browser_policy_connector_chromeos()
57 ->IsEnterpriseManaged()) {
58 return false;
59 }
60
61 return true;
62}
63
xiaoyinhf39e3dd2016-06-18 04:50:2364EolNotification::EolNotification(Profile* profile)
Regan Hsu62dc18f2019-10-03 20:30:4465 : clock_(base::DefaultClock::GetInstance()), profile_(profile) {}
xiaoyinhf39e3dd2016-06-18 04:50:2366
67EolNotification::~EolNotification() {}
68
Regan Hsu62dc18f2019-10-03 20:30:4469void EolNotification::CheckEolInfo() {
xiaoyinhf39e3dd2016-06-18 04:50:2370 UpdateEngineClient* update_engine_client =
71 DBusThreadManager::Get()->GetUpdateEngineClient();
72
Regan Hsu62dc18f2019-10-03 20:30:4473 // Request the Eol Info.
74 update_engine_client->GetEolInfo(base::BindOnce(
75 &EolNotification::OnEolInfo, weak_ptr_factory_.GetWeakPtr()));
xiaoyinhf39e3dd2016-06-18 04:50:2376}
77
Regan Hsu62dc18f2019-10-03 20:30:4478void EolNotification::OnEolInfo(UpdateEngineClient::EolInfo eol_info) {
79 // Do not show warning Eol notification if invalid |eol_info.eol_date|.
80 if (eol_info.eol_date.is_null())
xiaoyinhf39e3dd2016-06-18 04:50:2381 return;
82
Regan Hsu62dc18f2019-10-03 20:30:4483 const base::Time now = clock_->Now();
84 const base::Time eol_date = eol_info.eol_date;
85 const base::Time prev_eol_date =
86 profile_->GetPrefs()->GetTime(prefs::kEndOfLifeDate);
87
88 profile_->GetPrefs()->SetTime(prefs::kEndOfLifeDate, eol_date);
89
90 if (!now.is_null() && eol_date != prev_eol_date && now < eol_date) {
91 // Reset showed warning prefs if the Eol date changed.
92 profile_->GetPrefs()->SetBoolean(prefs::kFirstEolWarningDismissed, false);
93 profile_->GetPrefs()->SetBoolean(prefs::kSecondEolWarningDismissed, false);
xiaoyinhf39e3dd2016-06-18 04:50:2394 profile_->GetPrefs()->SetBoolean(prefs::kEolNotificationDismissed, false);
95 }
96
Regan Hsu62dc18f2019-10-03 20:30:4497 if (eol_date <= now) {
98 dismiss_pref_ = prefs::kEolNotificationDismissed;
99 } else if (SecondWarningDate(eol_date) <= now) {
100 dismiss_pref_ = prefs::kSecondEolWarningDismissed;
101 } else if (FirstWarningDate(eol_date) <= now) {
102 dismiss_pref_ = prefs::kFirstEolWarningDismissed;
103 } else {
104 // |now| < FirstWarningDate() so don't show anything.
105 dismiss_pref_ = base::nullopt;
106 return;
107 }
108
109 // Do not show if notification has already been dismissed or is out of range.
110 if (!dismiss_pref_ || profile_->GetPrefs()->GetBoolean(*dismiss_pref_))
xiaoyinhf39e3dd2016-06-18 04:50:23111 return;
112
Regan Hsu62dc18f2019-10-03 20:30:44113 CreateNotification(eol_date, now);
xiaoyinhf39e3dd2016-06-18 04:50:23114}
115
Regan Hsu62dc18f2019-10-03 20:30:44116void EolNotification::CreateNotification(base::Time eol_date, base::Time now) {
117 CHECK(!eol_date.is_null());
118 CHECK(!now.is_null());
119
xiaoyinhf39e3dd2016-06-18 04:50:23120 message_center::RichNotificationData data;
Regan Hsu62dc18f2019-10-03 20:30:44121 std::unique_ptr<message_center::Notification> notification;
Evan Stadecf27dae12017-11-07 23:57:51122
123 DCHECK_EQ(BUTTON_MORE_INFO, data.buttons.size());
dpapad943ef182018-01-20 02:58:20124 data.buttons.emplace_back(GetStringUTF16(IDS_LEARN_MORE));
Evan Stadecf27dae12017-11-07 23:57:51125
Regan Hsu62dc18f2019-10-03 20:30:44126 if (now < eol_date) {
127 // Notifies user that updates will stop occurring at a month and year.
128 notification = ash::CreateSystemNotification(
129 message_center::NOTIFICATION_TYPE_SIMPLE, kEolNotificationId,
Regan Hsud502ad612021-01-15 15:48:10130 l10n_util::GetStringFUTF16(
131 IDS_PENDING_EOL_NOTIFICATION_TITLE,
132 TimeFormatMonthAndYear(eol_date,
133 /*time_zone=*/icu::TimeZone::getGMT())),
Regan Hsu62dc18f2019-10-03 20:30:44134 l10n_util::GetStringFUTF16(IDS_PENDING_EOL_NOTIFICATION_MESSAGE,
135 ui::GetChromeOSDeviceName()),
Jan Wilken Dörrief27844b2021-03-11 23:18:48136 std::u16string() /* display_source */, GURL(kEolNotificationId),
Regan Hsu62dc18f2019-10-03 20:30:44137 message_center::NotifierId(
138 message_center::NotifierType::SYSTEM_COMPONENT, kEolNotificationId),
139 data,
140 base::MakeRefCounted<message_center::ThunkNotificationDelegate>(
141 weak_ptr_factory_.GetWeakPtr()),
142 vector_icons::kBusinessIcon,
143 message_center::SystemNotificationWarningLevel::NORMAL);
144 } else {
145 DCHECK_EQ(BUTTON_DISMISS, data.buttons.size());
146 data.buttons.emplace_back(GetStringUTF16(IDS_EOL_DISMISS_BUTTON));
Regan Hsu8de051a2019-09-03 17:17:16147
Regan Hsu62dc18f2019-10-03 20:30:44148 // Notifies user that updates will no longer occur after this final update.
149 notification = ash::CreateSystemNotification(
150 message_center::NOTIFICATION_TYPE_SIMPLE, kEolNotificationId,
151 GetStringUTF16(IDS_EOL_NOTIFICATION_TITLE),
152 l10n_util::GetStringFUTF16(IDS_EOL_NOTIFICATION_EOL,
153 ui::GetChromeOSDeviceName()),
Jan Wilken Dörrief27844b2021-03-11 23:18:48154 std::u16string() /* display_source */, GURL(kEolNotificationId),
Regan Hsu62dc18f2019-10-03 20:30:44155 message_center::NotifierId(
156 message_center::NotifierType::SYSTEM_COMPONENT, kEolNotificationId),
157 data,
158 base::MakeRefCounted<message_center::ThunkNotificationDelegate>(
159 weak_ptr_factory_.GetWeakPtr()),
160 kNotificationEndOfSupportIcon,
161 message_center::SystemNotificationWarningLevel::NORMAL);
162 }
Evan Stadecc63b182017-09-26 16:05:12163
Evan Stadecc63b182017-09-26 16:05:12164 NotificationDisplayServiceFactory::GetForProfile(profile_)->Display(
Lei Zhang03c6b782019-03-21 05:22:24165 NotificationHandler::Type::TRANSIENT, *notification,
166 /*metadata=*/nullptr);
xiaoyinhf39e3dd2016-06-18 04:50:23167}
168
Regan Hsu62dc18f2019-10-03 20:30:44169void EolNotification::Close(bool by_user) {
170 // Only the final Eol notification has an explicit dismiss button, and
171 // is only dismissible by that button. The first and second warning
172 // buttons do not have an explicit dismiss button.
173 if (!by_user || !dismiss_pref_ ||
174 dismiss_pref_ == prefs::kEolNotificationDismissed) {
175 return;
176 }
177
178 profile_->GetPrefs()->SetBoolean(*dismiss_pref_, true);
179}
180
181void EolNotification::Click(const base::Optional<int>& button_index,
Jan Wilken Dörrief27844b2021-03-11 23:18:48182 const base::Optional<std::u16string>& reply) {
Regan Hsu62dc18f2019-10-03 20:30:44183 if (!button_index)
184 return;
185
186 switch (*button_index) {
187 case BUTTON_MORE_INFO: {
Regan Hsuf5b31152020-08-07 02:56:55188 const GURL url = dismiss_pref_ == prefs::kEolNotificationDismissed
189 ? GURL(chrome::kEolNotificationURL)
190 : GURL(chrome::kAutoUpdatePolicyURL);
Regan Hsu62dc18f2019-10-03 20:30:44191 // show eol link
Regan Hsuf5b31152020-08-07 02:56:55192 NavigateParams params(profile_, url, ui::PAGE_TRANSITION_LINK);
Regan Hsu62dc18f2019-10-03 20:30:44193 params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
194 params.window_action = NavigateParams::SHOW_WINDOW;
195 Navigate(&params);
196 break;
197 }
198 case BUTTON_DISMISS:
199 CHECK(dismiss_pref_);
200 // set dismiss pref.
201 profile_->GetPrefs()->SetBoolean(*dismiss_pref_, true);
202 break;
203 }
204
205 if (dismiss_pref_ && (*dismiss_pref_ != prefs::kEolNotificationDismissed))
206 profile_->GetPrefs()->SetBoolean(*dismiss_pref_, true);
207
208 NotificationDisplayServiceFactory::GetForProfile(profile_)->Close(
209 NotificationHandler::Type::TRANSIENT, kEolNotificationId);
210}
211
xiaoyinhf39e3dd2016-06-18 04:50:23212} // namespace chromeos