1 // 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/ui/webui/settings/about_handler.h"
6
7 #include <stddef.h>
8
9 #include <string>
10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/command_line.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/i18n/message_formatter.h"
17 #include "base/location.h"
18 #include "base/macros.h"
19 #include "base/metrics/user_metrics.h"
20 #include "base/metrics/user_metrics_action.h"
21 #include "base/strings/string16.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/system/sys_info.h"
26 #include "base/task/post_task.h"
27 #include "base/task/thread_pool.h"
28 #include "base/time/time.h"
29 #include "base/values.h"
30 #include "build/branding_buildflags.h"
31 #include "build/build_config.h"
32 #include "chrome/browser/browser_process.h"
33 #include "chrome/browser/browser_process_platform_part.h"
34 #include "chrome/browser/chrome_content_browser_client.h"
35 #include "chrome/browser/obsolete_system/obsolete_system.h"
36 #include "chrome/browser/ui/browser.h"
37 #include "chrome/browser/ui/browser_commands.h"
38 #include "chrome/browser/ui/browser_finder.h"
39 #include "chrome/browser/ui/chrome_pages.h"
40 #include "chrome/browser/upgrade_detector/upgrade_detector.h"
41 #include "chrome/common/channel_info.h"
42 #include "chrome/common/pref_names.h"
43 #include "chrome/common/url_constants.h"
44 #include "chrome/grit/chromium_strings.h"
45 #include "chrome/grit/generated_resources.h"
46 #include "components/google/core/common/google_util.h"
47 #include "components/policy/core/common/policy_namespace.h"
48 #include "components/policy/policy_constants.h"
49 #include "components/strings/grit/components_chromium_strings.h"
50 #include "components/strings/grit/components_strings.h"
51 #include "components/version_info/version_info.h"
52 #include "content/public/browser/browser_thread.h"
53 #include "content/public/browser/web_contents.h"
54 #include "content/public/browser/web_ui.h"
55 #include "content/public/browser/web_ui_data_source.h"
56 #include "ui/base/l10n/l10n_util.h"
57 #include "v8/include/v8-version-string.h"
58
59 #if defined(OS_CHROMEOS)
60 #include "base/i18n/time_formatting.h"
61 #include "chrome/browser/chromeos/arc/arc_util.h"
62 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
63 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
64 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
65 #include "chrome/browser/chromeos/profiles/profile_helper.h"
66 #include "chrome/browser/chromeos/settings/cros_settings.h"
67 #include "chrome/browser/chromeos/tpm_firmware_update.h"
68 #include "chrome/browser/profiles/profile.h"
69 #include "chrome/browser/profiles/profile_manager.h"
70 #include "chrome/browser/ui/webui/chromeos/image_source.h"
71 #include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
72 #include "chrome/browser/ui/webui/help/version_updater_chromeos.h"
73 #include "chromeos/constants/chromeos_features.h"
74 #include "chromeos/constants/chromeos_switches.h"
75 #include "chromeos/dbus/power/power_manager_client.h"
76 #include "chromeos/dbus/update_engine_client.h"
77 #include "chromeos/dbus/util/version_loader.h"
78 #include "chromeos/network/network_state.h"
79 #include "chromeos/network/network_state_handler.h"
80 #include "chromeos/system/statistics_provider.h"
81 #include "components/user_manager/user_manager.h"
82 #include "ui/chromeos/devicetype_utils.h"
83 #endif
84
85 using base::ListValue;
86 using content::BrowserThread;
87
88 namespace {
89
90 #if defined(OS_CHROMEOS)
91
92 // The directory containing the regulatory labels for supported
93 // models/regions, relative to chromeos-assets directory
94 const char kRegulatoryLabelsDirectory[] = "regulatory_labels";
95
96 // File names of the image file and the file containing alt text for the label.
97 const char kRegulatoryLabelImageFilename[] = "label.png";
98 const char kRegulatoryLabelTextFilename[] = "label.txt";
99
100 // Default region code to use if there's no label for the VPD region code.
101 const char kDefaultRegionCode[] = "us";
102
103 struct RegulatoryLabel {
104 const std::string label_text;
105 const std::string image_url;
106 };
107
108 // Returns the link to the safety info for the device (if it exists).
GetSafetyInfoLink()109 std::string GetSafetyInfoLink() {
110 const std::vector<std::string> board =
111 base::SplitString(base::SysInfo::GetLsbReleaseBoard(), "-",
112 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
113 if (board[0] == "nocturne") {
114 return chrome::kChromeUISafetyPixelSlateURL;
115 }
116 if (board[0] == "eve" || board[0] == "atlas") {
117 return chrome::kChromeUISafetyPixelbookURL;
118 }
119
120 return std::string();
121 }
122
123 // Returns message that informs user that for update it's better to
124 // connect to a network of one of the allowed types.
GetAllowedConnectionTypesMessage()125 base::string16 GetAllowedConnectionTypesMessage() {
126 const chromeos::NetworkState* network = chromeos::NetworkHandler::Get()
127 ->network_state_handler()
128 ->DefaultNetwork();
129 const bool mobile_data =
130 network && network->IsConnectedState() && network->IsUsingMobileData();
131
132 if (help_utils_chromeos::IsUpdateOverCellularAllowed(
133 true /* interactive */)) {
134 return mobile_data
135 ? l10n_util::GetStringUTF16(
136 IDS_UPGRADE_NETWORK_LIST_CELLULAR_ALLOWED_NOT_AUTOMATIC)
137 : l10n_util::GetStringUTF16(
138 IDS_UPGRADE_NETWORK_LIST_CELLULAR_ALLOWED);
139 } else {
140 return l10n_util::GetStringUTF16(
141 IDS_UPGRADE_NETWORK_LIST_CELLULAR_DISALLOWED);
142 }
143 }
144
145 // Returns true if the device is enterprise managed, false otherwise.
IsEnterpriseManaged()146 bool IsEnterpriseManaged() {
147 policy::BrowserPolicyConnectorChromeOS* connector =
148 g_browser_process->platform_part()->browser_policy_connector_chromeos();
149 return connector->IsEnterpriseManaged();
150 }
151
152 // Returns true if current user can change channel, false otherwise.
CanChangeChannel(Profile * profile)153 bool CanChangeChannel(Profile* profile) {
154 if (IsEnterpriseManaged()) {
155 bool value = false;
156 // On a managed machine we delegate this setting to the affiliated users
157 // only if the policy value is true.
158 chromeos::CrosSettings::Get()->GetBoolean(
159 chromeos::kReleaseChannelDelegated, &value);
160 if (!value)
161 return false;
162
163 // Get the currently logged-in user and check if it is affiliated.
164 const user_manager::User* user =
165 profile ? chromeos::ProfileHelper::Get()->GetUserByProfile(profile)
166 : nullptr;
167 return user && user->IsAffiliated();
168 }
169
170 // On non-managed machines, only the local owner can change the channel.
171 chromeos::OwnerSettingsServiceChromeOS* service =
172 chromeos::OwnerSettingsServiceChromeOSFactory::GetInstance()
173 ->GetForBrowserContext(profile);
174 return service && service->IsOwner();
175 }
176
177 // Returns the relative path under the chromeos-assets dir
178 // to the directory of regulatory labels for a given region, if found
179 // (e.g. "regulatory_labels/us"). Must be called from the blocking pool.
GetRegulatoryLabelDirForRegion(const std::string & region)180 base::FilePath GetRegulatoryLabelDirForRegion(const std::string& region) {
181 base::FilePath region_path(kRegulatoryLabelsDirectory);
182 const std::string model_subdir =
183 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
184 chromeos::switches::kRegulatoryLabelDir);
185 if (!model_subdir.empty()) {
186 region_path = region_path.AppendASCII(model_subdir);
187 }
188 region_path = region_path.AppendASCII(region);
189
190 // Check if the label image file exists in the full path, e.g.,
191 // "/usr/share/chromeos-assets/regulatory_labels/us/label.png".
192 const base::FilePath image_path =
193 base::FilePath(chrome::kChromeOSAssetPath)
194 .Append(region_path)
195 .AppendASCII(kRegulatoryLabelImageFilename);
196 return base::PathExists(image_path) ? region_path : base::FilePath();
197 }
198
199 // Finds the relative path under the chromeos-assets dir to the region
200 // subdirectory of regulatory labels, using the VPD region code. Also
201 // tries "us" as a fallback region. Must be called from the blocking pool.
FindRegulatoryLabelDir()202 base::FilePath FindRegulatoryLabelDir() {
203 std::string region;
204 base::FilePath region_path;
205 // Use the VPD region code to find the label dir.
206 if (chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
207 "region", ®ion) &&
208 !region.empty()) {
209 region_path = GetRegulatoryLabelDirForRegion(region);
210 }
211
212 // Try the fallback region code if no directory was found.
213 if (region_path.empty() && region != kDefaultRegionCode)
214 region_path = GetRegulatoryLabelDirForRegion(kDefaultRegionCode);
215
216 return region_path;
217 }
218
219 // Reads the file containing the regulatory label text, if found
220 // in the given relative path under the chromeos-assets dir.
221 // Must be called from the blocking pool.
ReadRegulatoryLabelText(const base::FilePath & label_dir_path)222 std::string ReadRegulatoryLabelText(const base::FilePath& label_dir_path) {
223 const base::FilePath text_path =
224 base::FilePath(chrome::kChromeOSAssetPath)
225 .Append(label_dir_path)
226 .AppendASCII(kRegulatoryLabelTextFilename);
227
228 std::string contents;
229 if (base::ReadFileToString(text_path, &contents))
230 return contents;
231 return std::string();
232 }
233
GetVersionInfo()234 std::unique_ptr<base::DictionaryValue> GetVersionInfo() {
235 std::unique_ptr<base::DictionaryValue> version_info(
236 new base::DictionaryValue);
237 version_info->SetString("osVersion",
238 chromeos::version_loader::GetVersion(
239 chromeos::version_loader::VERSION_FULL));
240 version_info->SetString("arcVersion",
241 chromeos::version_loader::GetARCVersion());
242 version_info->SetString("osFirmware",
243 chromeos::version_loader::GetFirmware());
244 return version_info;
245 }
246
247 #endif // defined(OS_CHROMEOS)
248
UpdateStatusToString(VersionUpdater::Status status)249 std::string UpdateStatusToString(VersionUpdater::Status status) {
250 std::string status_str;
251 switch (status) {
252 case VersionUpdater::CHECKING:
253 status_str = "checking";
254 break;
255 case VersionUpdater::UPDATING:
256 status_str = "updating";
257 break;
258 case VersionUpdater::NEARLY_UPDATED:
259 status_str = "nearly_updated";
260 break;
261 case VersionUpdater::UPDATED:
262 status_str = "updated";
263 break;
264 case VersionUpdater::FAILED:
265 case VersionUpdater::FAILED_OFFLINE:
266 case VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED:
267 status_str = "failed";
268 break;
269 case VersionUpdater::DISABLED:
270 status_str = "disabled";
271 break;
272 case VersionUpdater::DISABLED_BY_ADMIN:
273 status_str = "disabled_by_admin";
274 break;
275 case VersionUpdater::NEED_PERMISSION_TO_UPDATE:
276 status_str = "need_permission_to_update";
277 break;
278 }
279
280 return status_str;
281 }
282
283 } // namespace
284
285 namespace settings {
286
AboutHandler()287 AboutHandler::AboutHandler() : apply_changes_from_upgrade_observer_(false) {
288 UpgradeDetector::GetInstance()->AddObserver(this);
289 }
290
~AboutHandler()291 AboutHandler::~AboutHandler() {
292 UpgradeDetector::GetInstance()->RemoveObserver(this);
293 }
294
Create(content::WebUIDataSource * html_source,Profile * profile)295 AboutHandler* AboutHandler::Create(content::WebUIDataSource* html_source,
296 Profile* profile) {
297 html_source->AddString(
298 "aboutBrowserVersion",
299 l10n_util::GetStringFUTF16(
300 IDS_SETTINGS_ABOUT_PAGE_BROWSER_VERSION,
301 base::UTF8ToUTF16(version_info::GetVersionNumber()),
302 l10n_util::GetStringUTF16(version_info::IsOfficialBuild()
303 ? IDS_VERSION_UI_OFFICIAL
304 : IDS_VERSION_UI_UNOFFICIAL),
305 base::UTF8ToUTF16(chrome::GetChannelName()),
306 l10n_util::GetStringUTF16(sizeof(void*) == 8
307 ? IDS_VERSION_UI_64BIT
308 : IDS_VERSION_UI_32BIT)));
309
310 html_source->AddString(
311 "aboutProductCopyright",
312 base::i18n::MessageFormatter::FormatWithNumberedArgs(
313 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_COPYRIGHT),
314 base::Time::Now()));
315
316 base::string16 license = l10n_util::GetStringFUTF16(
317 IDS_VERSION_UI_LICENSE, base::ASCIIToUTF16(chrome::kChromiumProjectURL),
318 base::ASCIIToUTF16(chrome::kChromeUICreditsURL));
319 html_source->AddString("aboutProductLicense", license);
320
321 html_source->AddBoolean("aboutObsoleteNowOrSoon",
322 ObsoleteSystem::IsObsoleteNowOrSoon());
323 html_source->AddBoolean("aboutObsoleteEndOfTheLine",
324 ObsoleteSystem::IsObsoleteNowOrSoon() &&
325 ObsoleteSystem::IsEndOfTheLine());
326 html_source->AddString("aboutObsoleteSystem",
327 ObsoleteSystem::LocalizedObsoleteString());
328 html_source->AddString("aboutObsoleteSystemURL",
329 ObsoleteSystem::GetLinkURL());
330
331 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
332 base::string16 tos = l10n_util::GetStringFUTF16(
333 IDS_ABOUT_TERMS_OF_SERVICE, base::UTF8ToUTF16(chrome::kChromeUITermsURL));
334 html_source->AddString("aboutProductTos", tos);
335 #endif
336
337 #if defined(OS_CHROMEOS)
338 std::string safetyInfoLink = GetSafetyInfoLink();
339 html_source->AddBoolean("shouldShowSafetyInfo", !safetyInfoLink.empty());
340 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
341 html_source->AddString(
342 "aboutProductSafety",
343 l10n_util::GetStringUTF16(IDS_ABOUT_SAFETY_INFORMATION));
344 html_source->AddString("aboutProductSafetyURL",
345 base::UTF8ToUTF16(safetyInfoLink));
346 #endif
347
348 base::string16 os_license = l10n_util::GetStringFUTF16(
349 IDS_ABOUT_CROS_VERSION_LICENSE,
350 base::ASCIIToUTF16(chrome::kChromeUIOSCreditsURL));
351 html_source->AddString("aboutProductOsLicense", os_license);
352 base::string16 os_with_linux_license = l10n_util::GetStringFUTF16(
353 IDS_ABOUT_CROS_WITH_LINUX_VERSION_LICENSE,
354 base::ASCIIToUTF16(chrome::kChromeUIOSCreditsURL),
355 base::ASCIIToUTF16(chrome::kChromeUICrostiniCreditsURL));
356 html_source->AddString("aboutProductOsWithLinuxLicense",
357 os_with_linux_license);
358 html_source->AddBoolean("aboutEnterpriseManaged", IsEnterpriseManaged());
359 html_source->AddBoolean("aboutIsArcEnabled",
360 arc::IsArcPlayStoreEnabledForProfile(profile));
361 html_source->AddBoolean("aboutIsDeveloperMode",
362 base::CommandLine::ForCurrentProcess()->HasSwitch(
363 chromeos::switches::kSystemDevMode));
364
365 html_source->AddString("endOfLifeMessage",
366 l10n_util::GetStringFUTF16(
367 IDS_SETTINGS_ABOUT_PAGE_LAST_UPDATE_MESSAGE,
368 ui::GetChromeOSDeviceName(),
369 base::ASCIIToUTF16(chrome::kEolNotificationURL)));
370 #endif
371
372 return new AboutHandler();
373 }
374
RegisterMessages()375 void AboutHandler::RegisterMessages() {
376 web_ui()->RegisterMessageCallback(
377 "aboutPageReady", base::BindRepeating(&AboutHandler::HandlePageReady,
378 base::Unretained(this)));
379 web_ui()->RegisterMessageCallback(
380 "refreshUpdateStatus",
381 base::BindRepeating(&AboutHandler::HandleRefreshUpdateStatus,
382 base::Unretained(this)));
383 web_ui()->RegisterMessageCallback(
384 "openFeedbackDialog",
385 base::BindRepeating(&AboutHandler::HandleOpenFeedbackDialog,
386 base::Unretained(this)));
387 web_ui()->RegisterMessageCallback(
388 "openHelpPage", base::BindRepeating(&AboutHandler::HandleOpenHelpPage,
389 base::Unretained(this)));
390 #if defined(OS_CHROMEOS)
391 web_ui()->RegisterMessageCallback(
392 "openOsHelpPage", base::BindRepeating(&AboutHandler::HandleOpenOsHelpPage,
393 base::Unretained(this)));
394 web_ui()->RegisterMessageCallback(
395 "setChannel", base::BindRepeating(&AboutHandler::HandleSetChannel,
396 base::Unretained(this)));
397 web_ui()->RegisterMessageCallback(
398 "requestUpdate", base::BindRepeating(&AboutHandler::HandleRequestUpdate,
399 base::Unretained(this)));
400 web_ui()->RegisterMessageCallback(
401 "requestUpdateOverCellular",
402 base::BindRepeating(&AboutHandler::HandleRequestUpdateOverCellular,
403 base::Unretained(this)));
404 web_ui()->RegisterMessageCallback(
405 "getVersionInfo", base::BindRepeating(&AboutHandler::HandleGetVersionInfo,
406 base::Unretained(this)));
407 web_ui()->RegisterMessageCallback(
408 "getRegulatoryInfo",
409 base::BindRepeating(&AboutHandler::HandleGetRegulatoryInfo,
410 base::Unretained(this)));
411 web_ui()->RegisterMessageCallback(
412 "getChannelInfo", base::BindRepeating(&AboutHandler::HandleGetChannelInfo,
413 base::Unretained(this)));
414 web_ui()->RegisterMessageCallback(
415 "canChangeChannel",
416 base::BindRepeating(&AboutHandler::HandleCanChangeChannel,
417 base::Unretained(this)));
418 web_ui()->RegisterMessageCallback(
419 "refreshTPMFirmwareUpdateStatus",
420 base::BindRepeating(&AboutHandler::HandleRefreshTPMFirmwareUpdateStatus,
421 base::Unretained(this)));
422 web_ui()->RegisterMessageCallback(
423 "getEndOfLifeInfo",
424 base::BindRepeating(&AboutHandler::HandleGetEndOfLifeInfo,
425 base::Unretained(this)));
426 web_ui()->RegisterMessageCallback(
427 "getEnabledReleaseNotes",
428 base::BindRepeating(&AboutHandler::HandleGetEnabledReleaseNotes,
429 base::Unretained(this)));
430 web_ui()->RegisterMessageCallback(
431 "launchReleaseNotes",
432 base::BindRepeating(&AboutHandler::HandleLaunchReleaseNotes,
433 base::Unretained(this)));
434 web_ui()->RegisterMessageCallback(
435 "checkInternetConnection",
436 base::BindRepeating(&AboutHandler::HandleCheckInternetConnection,
437 base::Unretained(this)));
438 #endif
439 #if defined(OS_MACOSX)
440 web_ui()->RegisterMessageCallback(
441 "promoteUpdater", base::BindRepeating(&AboutHandler::PromoteUpdater,
442 base::Unretained(this)));
443 #endif
444
445 #if defined(OS_CHROMEOS)
446 // Handler for the product label image, which will be shown if available.
447 content::URLDataSource::Add(Profile::FromWebUI(web_ui()),
448 std::make_unique<chromeos::ImageSource>());
449 #endif
450 }
451
OnJavascriptAllowed()452 void AboutHandler::OnJavascriptAllowed() {
453 apply_changes_from_upgrade_observer_ = true;
454 version_updater_.reset(VersionUpdater::Create(web_ui()->GetWebContents()));
455 policy_registrar_ = std::make_unique<policy::PolicyChangeRegistrar>(
456 g_browser_process->policy_service(),
457 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()));
458 policy_registrar_->Observe(
459 policy::key::kDeviceAutoUpdateDisabled,
460 base::Bind(&AboutHandler::OnDeviceAutoUpdatePolicyChanged,
461 base::Unretained(this)));
462 }
463
OnJavascriptDisallowed()464 void AboutHandler::OnJavascriptDisallowed() {
465 apply_changes_from_upgrade_observer_ = false;
466 version_updater_.reset();
467 policy_registrar_.reset();
468 }
469
OnUpgradeRecommended()470 void AboutHandler::OnUpgradeRecommended() {
471 if (apply_changes_from_upgrade_observer_) {
472 // A version update is installed and ready to go. Refresh the UI so the
473 // correct state will be shown.
474 RequestUpdate();
475 }
476 }
477
OnDeviceAutoUpdatePolicyChanged(const base::Value * previous_policy,const base::Value * current_policy)478 void AboutHandler::OnDeviceAutoUpdatePolicyChanged(
479 const base::Value* previous_policy,
480 const base::Value* current_policy) {
481 bool previous_auto_update_disabled = false;
482 if (previous_policy)
483 CHECK(previous_policy->GetAsBoolean(&previous_auto_update_disabled));
484
485 bool current_auto_update_disabled = false;
486 if (current_policy)
487 CHECK(current_policy->GetAsBoolean(¤t_auto_update_disabled));
488
489 if (current_auto_update_disabled != previous_auto_update_disabled) {
490 // Refresh the update status to refresh the status of the UI.
491 RefreshUpdateStatus();
492 }
493 }
494
HandlePageReady(const base::ListValue * args)495 void AboutHandler::HandlePageReady(const base::ListValue* args) {
496 AllowJavascript();
497 }
498
HandleRefreshUpdateStatus(const base::ListValue * args)499 void AboutHandler::HandleRefreshUpdateStatus(const base::ListValue* args) {
500 RefreshUpdateStatus();
501 }
502
RefreshUpdateStatus()503 void AboutHandler::RefreshUpdateStatus() {
504 // On Chrome OS, do not check for an update automatically.
505 #if defined(OS_CHROMEOS)
506 static_cast<VersionUpdaterCros*>(version_updater_.get())
507 ->GetUpdateStatus(
508 base::Bind(&AboutHandler::SetUpdateStatus, base::Unretained(this)));
509 #else
510 RequestUpdate();
511 #endif
512 }
513
514 #if defined(OS_MACOSX)
PromoteUpdater(const base::ListValue * args)515 void AboutHandler::PromoteUpdater(const base::ListValue* args) {
516 version_updater_->PromoteUpdater();
517 }
518 #endif
519
HandleOpenFeedbackDialog(const base::ListValue * args)520 void AboutHandler::HandleOpenFeedbackDialog(const base::ListValue* args) {
521 DCHECK(args->empty());
522 Browser* browser =
523 chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
524 chrome::OpenFeedbackDialog(browser,
525 chrome::kFeedbackSourceMdSettingsAboutPage);
526 }
527
HandleOpenHelpPage(const base::ListValue * args)528 void AboutHandler::HandleOpenHelpPage(const base::ListValue* args) {
529 DCHECK(args->empty());
530 Browser* browser =
531 chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
532 chrome::ShowHelp(browser, chrome::HELP_SOURCE_WEBUI);
533 }
534
535 #if defined(OS_CHROMEOS)
HandleGetEnabledReleaseNotes(const base::ListValue * args)536 void AboutHandler::HandleGetEnabledReleaseNotes(const base::ListValue* args) {
537 CHECK_EQ(1U, args->GetSize());
538 std::string callback_id;
539 CHECK(args->GetString(0, &callback_id));
540 ResolveJavascriptCallback(base::Value(callback_id),
541 base::Value(base::FeatureList::IsEnabled(
542 chromeos::features::kReleaseNotes)));
543 }
544
HandleCheckInternetConnection(const base::ListValue * args)545 void AboutHandler::HandleCheckInternetConnection(const base::ListValue* args) {
546 CHECK_EQ(1U, args->GetSize());
547 std::string callback_id;
548 CHECK(args->GetString(0, &callback_id));
549
550 chromeos::NetworkStateHandler* network_state_handler =
551 chromeos::NetworkHandler::Get()->network_state_handler();
552 const chromeos::NetworkState* network =
553 network_state_handler->DefaultNetwork();
554 ResolveJavascriptCallback(base::Value(callback_id),
555 base::Value(network && network->IsOnline()));
556 }
557
HandleLaunchReleaseNotes(const base::ListValue * args)558 void AboutHandler::HandleLaunchReleaseNotes(const base::ListValue* args) {
559 DCHECK(args->empty());
560 chromeos::NetworkStateHandler* network_state_handler =
561 chromeos::NetworkHandler::Get()->network_state_handler();
562 const chromeos::NetworkState* network =
563 network_state_handler->DefaultNetwork();
564 if (network && network->IsOnline()) {
565 base::RecordAction(
566 base::UserMetricsAction("ReleaseNotes.LaunchedAboutPage"));
567 chrome::LaunchReleaseNotes(Profile::FromWebUI(web_ui()));
568 }
569 }
570
HandleOpenOsHelpPage(const base::ListValue * args)571 void AboutHandler::HandleOpenOsHelpPage(const base::ListValue* args) {
572 DCHECK(args->empty());
573 Browser* browser =
574 chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
575 chrome::ShowHelp(browser, chrome::HELP_SOURCE_WEBUI_CHROME_OS);
576 }
577
HandleSetChannel(const base::ListValue * args)578 void AboutHandler::HandleSetChannel(const base::ListValue* args) {
579 DCHECK(args->GetSize() == 2);
580
581 if (!CanChangeChannel(Profile::FromWebUI(web_ui()))) {
582 LOG(WARNING) << "Non-owner tried to change release track.";
583 return;
584 }
585
586 base::string16 channel;
587 bool is_powerwash_allowed;
588 if (!args->GetString(0, &channel) ||
589 !args->GetBoolean(1, &is_powerwash_allowed)) {
590 LOG(ERROR) << "Can't parse SetChannel() args";
591 return;
592 }
593
594 version_updater_->SetChannel(base::UTF16ToUTF8(channel),
595 is_powerwash_allowed);
596 if (user_manager::UserManager::Get()->IsCurrentUserOwner()) {
597 // Check for update after switching release channel.
598 version_updater_->CheckForUpdate(
599 base::Bind(&AboutHandler::SetUpdateStatus, base::Unretained(this)),
600 VersionUpdater::PromoteCallback());
601 }
602 }
603
HandleGetVersionInfo(const base::ListValue * args)604 void AboutHandler::HandleGetVersionInfo(const base::ListValue* args) {
605 CHECK_EQ(1U, args->GetSize());
606 std::string callback_id;
607 CHECK(args->GetString(0, &callback_id));
608 base::ThreadPool::PostTaskAndReplyWithResult(
609 FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
610 base::BindOnce(&GetVersionInfo),
611 base::BindOnce(&AboutHandler::OnGetVersionInfoReady,
612 weak_factory_.GetWeakPtr(), callback_id));
613 }
614
OnGetVersionInfoReady(std::string callback_id,std::unique_ptr<base::DictionaryValue> version_info)615 void AboutHandler::OnGetVersionInfoReady(
616 std::string callback_id,
617 std::unique_ptr<base::DictionaryValue> version_info) {
618 ResolveJavascriptCallback(base::Value(callback_id), *version_info);
619 }
620
HandleGetRegulatoryInfo(const base::ListValue * args)621 void AboutHandler::HandleGetRegulatoryInfo(const base::ListValue* args) {
622 CHECK_EQ(1U, args->GetSize());
623 std::string callback_id;
624 CHECK(args->GetString(0, &callback_id));
625
626 base::ThreadPool::PostTaskAndReplyWithResult(
627 FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
628 base::BindOnce(&FindRegulatoryLabelDir),
629 base::BindOnce(&AboutHandler::OnRegulatoryLabelDirFound,
630 weak_factory_.GetWeakPtr(), callback_id));
631 }
632
HandleGetChannelInfo(const base::ListValue * args)633 void AboutHandler::HandleGetChannelInfo(const base::ListValue* args) {
634 CHECK_EQ(1U, args->GetSize());
635 std::string callback_id;
636 CHECK(args->GetString(0, &callback_id));
637 version_updater_->GetChannel(
638 true /* get current channel */,
639 base::Bind(&AboutHandler::OnGetCurrentChannel, weak_factory_.GetWeakPtr(),
640 callback_id));
641 }
642
HandleCanChangeChannel(const base::ListValue * args)643 void AboutHandler::HandleCanChangeChannel(const base::ListValue* args) {
644 CHECK_EQ(1U, args->GetSize());
645 std::string callback_id;
646 CHECK(args->GetString(0, &callback_id));
647 ResolveJavascriptCallback(
648 base::Value(callback_id),
649 base::Value(CanChangeChannel(Profile::FromWebUI(web_ui()))));
650 }
651
OnGetCurrentChannel(std::string callback_id,const std::string & current_channel)652 void AboutHandler::OnGetCurrentChannel(std::string callback_id,
653 const std::string& current_channel) {
654 version_updater_->GetChannel(
655 false /* get target channel */,
656 base::Bind(&AboutHandler::OnGetTargetChannel, weak_factory_.GetWeakPtr(),
657 callback_id, current_channel));
658 }
659
OnGetTargetChannel(std::string callback_id,const std::string & current_channel,const std::string & target_channel)660 void AboutHandler::OnGetTargetChannel(std::string callback_id,
661 const std::string& current_channel,
662 const std::string& target_channel) {
663 std::unique_ptr<base::DictionaryValue> channel_info(
664 new base::DictionaryValue);
665 channel_info->SetString("currentChannel", current_channel);
666 channel_info->SetString("targetChannel", target_channel);
667
668 ResolveJavascriptCallback(base::Value(callback_id), *channel_info);
669 }
670
HandleRequestUpdate(const base::ListValue * args)671 void AboutHandler::HandleRequestUpdate(const base::ListValue* args) {
672 RequestUpdate();
673 }
674
HandleRequestUpdateOverCellular(const base::ListValue * args)675 void AboutHandler::HandleRequestUpdateOverCellular(
676 const base::ListValue* args) {
677 CHECK_EQ(2U, args->GetSize());
678
679 std::string update_version;
680 std::string update_size_string;
681 int64_t update_size;
682
683 CHECK(args->GetString(0, &update_version));
684 CHECK(args->GetString(1, &update_size_string));
685 CHECK(base::StringToInt64(update_size_string, &update_size));
686
687 RequestUpdateOverCellular(update_version, update_size);
688 }
689
RequestUpdateOverCellular(const std::string & update_version,int64_t update_size)690 void AboutHandler::RequestUpdateOverCellular(const std::string& update_version,
691 int64_t update_size) {
692 version_updater_->SetUpdateOverCellularOneTimePermission(
693 base::Bind(&AboutHandler::SetUpdateStatus, base::Unretained(this)),
694 update_version, update_size);
695 }
696
HandleRefreshTPMFirmwareUpdateStatus(const base::ListValue * args)697 void AboutHandler::HandleRefreshTPMFirmwareUpdateStatus(
698 const base::ListValue* args) {
699 chromeos::tpm_firmware_update::GetAvailableUpdateModes(
700 base::Bind(&AboutHandler::RefreshTPMFirmwareUpdateStatus,
701 weak_factory_.GetWeakPtr()),
702 base::TimeDelta());
703 }
704
RefreshTPMFirmwareUpdateStatus(const std::set<chromeos::tpm_firmware_update::Mode> & modes)705 void AboutHandler::RefreshTPMFirmwareUpdateStatus(
706 const std::set<chromeos::tpm_firmware_update::Mode>& modes) {
707 std::unique_ptr<base::DictionaryValue> event(new base::DictionaryValue);
708 event->SetBoolean("updateAvailable", !modes.empty());
709 FireWebUIListener("tpm-firmware-update-status-changed", *event);
710 }
711
HandleGetEndOfLifeInfo(const base::ListValue * args)712 void AboutHandler::HandleGetEndOfLifeInfo(const base::ListValue* args) {
713 CHECK_EQ(1U, args->GetSize());
714 std::string callback_id;
715 CHECK(args->GetString(0, &callback_id));
716 version_updater_->GetEolInfo(base::BindOnce(&AboutHandler::OnGetEndOfLifeInfo,
717 weak_factory_.GetWeakPtr(),
718 callback_id));
719 }
720
OnGetEndOfLifeInfo(std::string callback_id,chromeos::UpdateEngineClient::EolInfo eol_info)721 void AboutHandler::OnGetEndOfLifeInfo(
722 std::string callback_id,
723 chromeos::UpdateEngineClient::EolInfo eol_info) {
724 base::Value response(base::Value::Type::DICTIONARY);
725 if (!eol_info.eol_date.is_null()) {
726 response.SetBoolKey("hasEndOfLife", eol_info.eol_date <= base::Time::Now());
727 int eol_string_id = eol_info.eol_date <= base::Time::Now()
728 ? IDS_SETTINGS_ABOUT_PAGE_END_OF_LIFE_MESSAGE_PAST
729 : IDS_SETTINGS_ABOUT_PAGE_END_OF_LIFE_MESSAGE_FUTURE;
730 response.SetStringKey(
731 "aboutPageEndOfLifeMessage",
732 l10n_util::GetStringFUTF16(
733 eol_string_id, base::TimeFormatMonthAndYear(eol_info.eol_date),
734 base::ASCIIToUTF16(chrome::kEolNotificationURL)));
735 } else {
736 response.SetBoolKey("hasEndOfLife", false);
737 response.SetStringKey("aboutPageEndOfLifeMessage", "");
738 }
739 ResolveJavascriptCallback(base::Value(callback_id), response);
740 }
741
742 #endif // defined(OS_CHROMEOS)
743
RequestUpdate()744 void AboutHandler::RequestUpdate() {
745 version_updater_->CheckForUpdate(
746 base::Bind(&AboutHandler::SetUpdateStatus, base::Unretained(this)),
747 #if defined(OS_MACOSX)
748 base::Bind(&AboutHandler::SetPromotionState, base::Unretained(this)));
749 #else
750 VersionUpdater::PromoteCallback());
751 #endif // OS_MACOSX
752 }
753
SetUpdateStatus(VersionUpdater::Status status,int progress,bool rollback,const std::string & version,int64_t size,const base::string16 & message)754 void AboutHandler::SetUpdateStatus(VersionUpdater::Status status,
755 int progress,
756 bool rollback,
757 const std::string& version,
758 int64_t size,
759 const base::string16& message) {
760 // Only UPDATING state should have progress set.
761 DCHECK(status == VersionUpdater::UPDATING || progress == 0);
762
763 std::unique_ptr<base::DictionaryValue> event(new base::DictionaryValue);
764 event->SetString("status", UpdateStatusToString(status));
765 event->SetString("message", message);
766 event->SetInteger("progress", progress);
767 event->SetBoolean("rollback", rollback);
768 event->SetString("version", version);
769 // DictionaryValue does not support int64_t, so convert to string.
770 event->SetString("size", base::NumberToString(size));
771 #if defined(OS_CHROMEOS)
772 if (status == VersionUpdater::FAILED_OFFLINE ||
773 status == VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED) {
774 base::string16 types_msg = GetAllowedConnectionTypesMessage();
775 if (!types_msg.empty())
776 event->SetString("connectionTypes", types_msg);
777 else
778 event->Set("connectionTypes", std::make_unique<base::Value>());
779 } else {
780 event->Set("connectionTypes", std::make_unique<base::Value>());
781 }
782 #endif // defined(OS_CHROMEOS)
783
784 FireWebUIListener("update-status-changed", *event);
785 }
786
787 #if defined(OS_MACOSX)
SetPromotionState(VersionUpdater::PromotionState state)788 void AboutHandler::SetPromotionState(VersionUpdater::PromotionState state) {
789 // Worth noting: PROMOTE_DISABLED indicates that promotion is possible,
790 // there's just something else going on right now (e.g. checking for update).
791 bool hidden = state == VersionUpdater::PROMOTE_HIDDEN;
792 bool disabled = state == VersionUpdater::PROMOTE_HIDDEN ||
793 state == VersionUpdater::PROMOTE_DISABLED ||
794 state == VersionUpdater::PROMOTED;
795 bool actionable = state == VersionUpdater::PROMOTE_DISABLED ||
796 state == VersionUpdater::PROMOTE_ENABLED;
797
798 base::string16 text = base::string16();
799 if (actionable)
800 text = l10n_util::GetStringUTF16(IDS_ABOUT_CHROME_AUTOUPDATE_ALL);
801 else if (state == VersionUpdater::PROMOTED)
802 text = l10n_util::GetStringUTF16(IDS_ABOUT_CHROME_AUTOUPDATE_ALL_IS_ON);
803
804 base::DictionaryValue promo_state;
805 promo_state.SetBoolean("hidden", hidden);
806 promo_state.SetBoolean("disabled", disabled);
807 promo_state.SetBoolean("actionable", actionable);
808 if (!text.empty())
809 promo_state.SetString("text", text);
810
811 FireWebUIListener("promotion-state-changed", promo_state);
812 }
813 #endif // defined(OS_MACOSX)
814
815 #if defined(OS_CHROMEOS)
OnRegulatoryLabelDirFound(std::string callback_id,const base::FilePath & label_dir_path)816 void AboutHandler::OnRegulatoryLabelDirFound(
817 std::string callback_id,
818 const base::FilePath& label_dir_path) {
819 if (label_dir_path.empty()) {
820 ResolveJavascriptCallback(base::Value(callback_id), base::Value());
821 return;
822 }
823
824 base::ThreadPool::PostTaskAndReplyWithResult(
825 FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
826 base::BindOnce(&ReadRegulatoryLabelText, label_dir_path),
827 base::BindOnce(&AboutHandler::OnRegulatoryLabelTextRead,
828 weak_factory_.GetWeakPtr(), callback_id, label_dir_path));
829 }
830
OnRegulatoryLabelTextRead(std::string callback_id,const base::FilePath & label_dir_path,const std::string & text)831 void AboutHandler::OnRegulatoryLabelTextRead(
832 std::string callback_id,
833 const base::FilePath& label_dir_path,
834 const std::string& text) {
835 std::unique_ptr<base::DictionaryValue> regulatory_info(
836 new base::DictionaryValue);
837 // Remove unnecessary whitespace.
838 regulatory_info->SetString("text", base::CollapseWhitespaceASCII(text, true));
839
840 std::string image_path =
841 label_dir_path.AppendASCII(kRegulatoryLabelImageFilename).MaybeAsASCII();
842 std::string url =
843 std::string("chrome://") + chrome::kChromeOSAssetHost + "/" + image_path;
844 regulatory_info->SetString("url", url);
845
846 ResolveJavascriptCallback(base::Value(callback_id), *regulatory_info);
847 }
848 #endif // defined(OS_CHROMEOS)
849
850 } // namespace settings
851