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", &region) &&
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(&current_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