1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/webui/help/help_handler.h"
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/values.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/browser_commands.h"
21 #include "chrome/browser/ui/browser_finder.h"
22 #include "chrome/browser/ui/chrome_pages.h"
23 #include "chrome/common/chrome_content_client.h"
24 #include "chrome/common/chrome_version_info.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/url_constants.h"
27 #include "components/google/core/browser/google_util.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/web_ui.h"
31 #include "content/public/common/user_agent.h"
32 #include "grit/chromium_strings.h"
33 #include "grit/generated_resources.h"
34 #include "grit/google_chrome_strings.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "v8/include/v8.h"
38 #if defined(OS_MACOSX)
39 #include "chrome/browser/mac/obsolete_system.h"
42 #if defined(OS_CHROMEOS)
43 #include "base/files/file_util_proxy.h"
44 #include "base/i18n/time_formatting.h"
45 #include "base/prefs/pref_service.h"
46 #include "base/sys_info.h"
47 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
48 #include "chrome/browser/chromeos/settings/cros_settings.h"
49 #include "chrome/browser/profiles/profile.h"
50 #include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
51 #include "chromeos/chromeos_switches.h"
52 #include "chromeos/dbus/dbus_thread_manager.h"
53 #include "chromeos/dbus/power_manager_client.h"
54 #include "components/user_manager/user_manager.h"
57 using base::ListValue;
58 using content::BrowserThread;
62 #if defined(OS_CHROMEOS)
64 // Returns message that informs user that for update it's better to
65 // connect to a network of one of the allowed types.
66 base::string16 GetAllowedConnectionTypesMessage() {
67 if (help_utils_chromeos::IsUpdateOverCellularAllowed()) {
68 return l10n_util::GetStringUTF16(IDS_UPGRADE_NETWORK_LIST_CELLULAR_ALLOWED);
70 return l10n_util::GetStringUTF16(
71 IDS_UPGRADE_NETWORK_LIST_CELLULAR_DISALLOWED);
75 // Returns true if the device is enterprise managed, false otherwise.
76 bool IsEnterpriseManaged() {
77 policy::BrowserPolicyConnectorChromeOS* connector =
78 g_browser_process->platform_part()->browser_policy_connector_chromeos();
79 return connector->IsEnterpriseManaged();
82 // Returns true if current user can change channel, false otherwise.
83 bool CanChangeChannel() {
85 chromeos::CrosSettings::Get()->GetBoolean(chromeos::kReleaseChannelDelegated,
88 // On a managed machine we delegate this setting to the users of the same
89 // domain only if the policy value is "domain".
90 if (IsEnterpriseManaged()) {
93 // Get the currently logged in user and strip the domain part only.
94 std::string domain = "";
96 user_manager::UserManager::Get()->GetLoggedInUser()->email();
97 size_t at_pos = user.find('@');
98 if (at_pos != std::string::npos && at_pos + 1 < user.length())
99 domain = user.substr(user.find('@') + 1);
100 policy::BrowserPolicyConnectorChromeOS* connector =
101 g_browser_process->platform_part()->browser_policy_connector_chromeos();
102 return domain == connector->GetEnterpriseDomain();
103 } else if (user_manager::UserManager::Get()->IsCurrentUserOwner()) {
104 // On non managed machines we have local owner who is the only one to change
105 // anything. Ensure that ReleaseChannelDelegated is false.
111 #endif // defined(OS_CHROMEOS)
115 HelpHandler::HelpHandler()
116 : version_updater_(VersionUpdater::Create()),
117 weak_factory_(this) {
120 HelpHandler::~HelpHandler() {
123 void HelpHandler::GetLocalizedValues(base::DictionaryValue* localized_strings) {
124 struct L10nResources {
129 static L10nResources resources[] = {
130 { "aboutTitle", IDS_ABOUT_TITLE },
131 #if defined(OS_CHROMEOS)
132 { "aboutProductTitle", IDS_PRODUCT_OS_NAME },
134 { "aboutProductTitle", IDS_PRODUCT_NAME },
136 { "aboutProductDescription", IDS_ABOUT_PRODUCT_DESCRIPTION },
137 { "relaunch", IDS_RELAUNCH_BUTTON },
138 #if defined(OS_CHROMEOS)
139 { "relaunchAndPowerwash", IDS_RELAUNCH_AND_POWERWASH_BUTTON },
141 { "productName", IDS_PRODUCT_NAME },
142 { "updateCheckStarted", IDS_UPGRADE_CHECK_STARTED },
143 { "upToDate", IDS_UPGRADE_UP_TO_DATE },
144 { "updating", IDS_UPGRADE_UPDATING },
145 #if defined(OS_CHROMEOS)
146 { "updatingChannelSwitch", IDS_UPGRADE_UPDATING_CHANNEL_SWITCH },
148 { "updateAlmostDone", IDS_UPGRADE_SUCCESSFUL_RELAUNCH },
149 #if defined(OS_CHROMEOS)
150 { "successfulChannelSwitch", IDS_UPGRADE_SUCCESSFUL_CHANNEL_SWITCH },
152 { "getHelpWithChrome", IDS_GET_HELP_USING_CHROME },
153 { "reportAnIssue", IDS_REPORT_AN_ISSUE },
154 #if defined(OS_CHROMEOS)
155 { "platform", IDS_PLATFORM_LABEL },
156 { "firmware", IDS_ABOUT_PAGE_FIRMWARE },
157 { "showMoreInfo", IDS_SHOW_MORE_INFO },
158 { "hideMoreInfo", IDS_HIDE_MORE_INFO },
159 { "channel", IDS_ABOUT_PAGE_CHANNEL },
160 { "stable", IDS_ABOUT_PAGE_CHANNEL_STABLE },
161 { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA },
162 { "dev", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT },
163 { "channel-changed", IDS_ABOUT_PAGE_CHANNEL_CHANGED },
164 { "currentChannelStable", IDS_ABOUT_PAGE_CURRENT_CHANNEL_STABLE },
165 { "currentChannelBeta", IDS_ABOUT_PAGE_CURRENT_CHANNEL_BETA },
166 { "currentChannelDev", IDS_ABOUT_PAGE_CURRENT_CHANNEL_DEV },
167 { "currentChannel", IDS_ABOUT_PAGE_CURRENT_CHANNEL },
168 { "channelChangeButton", IDS_ABOUT_PAGE_CHANNEL_CHANGE_BUTTON },
169 { "channelChangeDisallowedMessage",
170 IDS_ABOUT_PAGE_CHANNEL_CHANGE_DISALLOWED_MESSAGE },
171 { "channelChangePageTitle", IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_TITLE },
172 { "channelChangePagePowerwashTitle",
173 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_TITLE },
174 { "channelChangePagePowerwashMessage",
175 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_MESSAGE },
176 { "channelChangePageDelayedChangeTitle",
177 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_DELAYED_CHANGE_TITLE },
178 { "channelChangePageUnstableTitle",
179 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_UNSTABLE_TITLE },
180 { "channelChangePagePowerwashButton",
181 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_BUTTON },
182 { "channelChangePageChangeButton",
183 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_CHANGE_BUTTON },
184 { "channelChangePageCancelButton",
185 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_CANCEL_BUTTON },
186 { "webkit", IDS_WEBKIT },
187 { "userAgent", IDS_ABOUT_VERSION_USER_AGENT },
188 { "commandLine", IDS_ABOUT_VERSION_COMMAND_LINE },
189 { "buildDate", IDS_ABOUT_VERSION_BUILD_DATE },
191 #if defined(OS_MACOSX)
192 { "promote", IDS_ABOUT_CHROME_PROMOTE_UPDATER },
193 { "learnMore", IDS_LEARN_MORE },
197 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resources); ++i) {
198 localized_strings->SetString(resources[i].name,
199 l10n_util::GetStringUTF16(resources[i].ids));
202 #if defined(OS_MACOSX)
203 localized_strings->SetString(
204 "updateObsoleteSystem",
205 ObsoleteSystemMac::LocalizedObsoleteSystemString());
206 localized_strings->SetString(
207 "updateObsoleteSystemURL",
208 chrome::kMac32BitDeprecationURL);
211 localized_strings->SetString(
213 l10n_util::GetStringFUTF16(IDS_ABOUT_PRODUCT_VERSION,
214 BuildBrowserVersionString()));
216 base::Time::Exploded exploded_time;
217 base::Time::Now().LocalExplode(&exploded_time);
218 localized_strings->SetString(
220 l10n_util::GetStringFUTF16(IDS_ABOUT_VERSION_COPYRIGHT,
221 base::IntToString16(exploded_time.year)));
223 base::string16 license = l10n_util::GetStringFUTF16(
224 IDS_ABOUT_VERSION_LICENSE,
225 base::ASCIIToUTF16(chrome::kChromiumProjectURL),
226 base::ASCIIToUTF16(chrome::kChromeUICreditsURL));
227 localized_strings->SetString("productLicense", license);
229 #if defined(OS_CHROMEOS)
230 base::string16 os_license = l10n_util::GetStringFUTF16(
231 IDS_ABOUT_CROS_VERSION_LICENSE,
232 base::ASCIIToUTF16(chrome::kChromeUIOSCreditsURL));
233 localized_strings->SetString("productOsLicense", os_license);
235 base::string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME);
236 localized_strings->SetString(
237 "channelChangePageDelayedChangeMessage",
238 l10n_util::GetStringFUTF16(
239 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_DELAYED_CHANGE_MESSAGE,
241 localized_strings->SetString(
242 "channelChangePageUnstableMessage",
243 l10n_util::GetStringFUTF16(
244 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_UNSTABLE_MESSAGE,
247 if (CommandLine::ForCurrentProcess()->
248 HasSwitch(chromeos::switches::kDisableNewChannelSwitcherUI)) {
249 localized_strings->SetBoolean("disableNewChannelSwitcherUI", true);
253 base::string16 tos = l10n_util::GetStringFUTF16(
254 IDS_ABOUT_TERMS_OF_SERVICE, base::UTF8ToUTF16(chrome::kChromeUITermsURL));
255 localized_strings->SetString("productTOS", tos);
257 localized_strings->SetString("webkitVersion", content::GetWebKitVersion());
259 localized_strings->SetString("jsEngine", "V8");
260 localized_strings->SetString("jsEngineVersion", v8::V8::GetVersion());
262 localized_strings->SetString("userAgentInfo", GetUserAgent());
264 CommandLine::StringType command_line =
265 CommandLine::ForCurrentProcess()->GetCommandLineString();
266 localized_strings->SetString("commandLineInfo", command_line);
269 void HelpHandler::RegisterMessages() {
270 registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
271 content::NotificationService::AllSources());
273 web_ui()->RegisterMessageCallback("onPageLoaded",
274 base::Bind(&HelpHandler::OnPageLoaded, base::Unretained(this)));
275 web_ui()->RegisterMessageCallback("relaunchNow",
276 base::Bind(&HelpHandler::RelaunchNow, base::Unretained(this)));
277 web_ui()->RegisterMessageCallback("openFeedbackDialog",
278 base::Bind(&HelpHandler::OpenFeedbackDialog, base::Unretained(this)));
279 web_ui()->RegisterMessageCallback("openHelpPage",
280 base::Bind(&HelpHandler::OpenHelpPage, base::Unretained(this)));
281 #if defined(OS_CHROMEOS)
282 web_ui()->RegisterMessageCallback("setChannel",
283 base::Bind(&HelpHandler::SetChannel, base::Unretained(this)));
284 web_ui()->RegisterMessageCallback("relaunchAndPowerwash",
285 base::Bind(&HelpHandler::RelaunchAndPowerwash, base::Unretained(this)));
287 #if defined(OS_MACOSX)
288 web_ui()->RegisterMessageCallback("promoteUpdater",
289 base::Bind(&HelpHandler::PromoteUpdater, base::Unretained(this)));
293 void HelpHandler::Observe(int type, const content::NotificationSource& source,
294 const content::NotificationDetails& details) {
296 case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: {
297 // A version update is installed and ready to go. Refresh the UI so the
298 // correct state will be shown.
299 version_updater_->CheckForUpdate(
300 base::Bind(&HelpHandler::SetUpdateStatus, base::Unretained(this))
301 #if defined(OS_MACOSX)
302 , base::Bind(&HelpHandler::SetPromotionState, base::Unretained(this))
313 base::string16 HelpHandler::BuildBrowserVersionString() {
314 chrome::VersionInfo version_info;
315 DCHECK(version_info.is_valid());
317 std::string browser_version = version_info.Version();
318 std::string version_modifier =
319 chrome::VersionInfo::GetVersionStringModifier();
320 if (!version_modifier.empty())
321 browser_version += " " + version_modifier;
323 #if !defined(GOOGLE_CHROME_BUILD)
324 browser_version += " (";
325 browser_version += version_info.LastChange();
326 browser_version += ")";
329 #if defined(ARCH_CPU_64_BITS)
330 browser_version += " (64-bit)";
333 return base::UTF8ToUTF16(browser_version);
336 void HelpHandler::OnPageLoaded(const base::ListValue* args) {
337 #if defined(OS_CHROMEOS)
338 // Version information is loaded from a callback
340 chromeos::VersionLoader::VERSION_FULL,
341 base::Bind(&HelpHandler::OnOSVersion, base::Unretained(this)),
344 base::Bind(&HelpHandler::OnOSFirmware, base::Unretained(this)),
347 web_ui()->CallJavascriptFunction(
348 "help.HelpPage.updateEnableReleaseChannel",
349 base::FundamentalValue(CanChangeChannel()));
351 base::Time build_time = base::SysInfo::GetLsbReleaseTime();
352 base::string16 build_date = base::TimeFormatFriendlyDate(build_time);
353 web_ui()->CallJavascriptFunction("help.HelpPage.setBuildDate",
354 base::StringValue(build_date));
355 #endif // defined(OS_CHROMEOS)
357 version_updater_->CheckForUpdate(
358 base::Bind(&HelpHandler::SetUpdateStatus, base::Unretained(this))
359 #if defined(OS_MACOSX)
360 , base::Bind(&HelpHandler::SetPromotionState, base::Unretained(this))
364 #if defined(OS_MACOSX)
365 web_ui()->CallJavascriptFunction(
366 "help.HelpPage.setObsoleteSystem",
367 base::FundamentalValue(ObsoleteSystemMac::Is32BitObsoleteNowOrSoon() &&
368 ObsoleteSystemMac::Has32BitOnlyCPU()));
369 web_ui()->CallJavascriptFunction(
370 "help.HelpPage.setObsoleteSystemEndOfTheLine",
371 base::FundamentalValue(ObsoleteSystemMac::Is32BitObsoleteNowOrSoon() &&
372 ObsoleteSystemMac::Is32BitEndOfTheLine()));
375 #if defined(OS_CHROMEOS)
376 web_ui()->CallJavascriptFunction(
377 "help.HelpPage.updateIsEnterpriseManaged",
378 base::FundamentalValue(IsEnterpriseManaged()));
379 // First argument to GetChannel() is a flag that indicates whether
380 // current channel should be returned (if true) or target channel
382 version_updater_->GetChannel(true,
383 base::Bind(&HelpHandler::OnCurrentChannel, weak_factory_.GetWeakPtr()));
384 version_updater_->GetChannel(false,
385 base::Bind(&HelpHandler::OnTargetChannel, weak_factory_.GetWeakPtr()));
389 #if defined(OS_MACOSX)
390 void HelpHandler::PromoteUpdater(const base::ListValue* args) {
391 version_updater_->PromoteUpdater();
395 void HelpHandler::RelaunchNow(const base::ListValue* args) {
396 DCHECK(args->empty());
397 version_updater_->RelaunchBrowser();
400 void HelpHandler::OpenFeedbackDialog(const base::ListValue* args) {
401 DCHECK(args->empty());
402 Browser* browser = chrome::FindBrowserWithWebContents(
403 web_ui()->GetWebContents());
404 chrome::OpenFeedbackDialog(browser);
407 void HelpHandler::OpenHelpPage(const base::ListValue* args) {
408 DCHECK(args->empty());
409 Browser* browser = chrome::FindBrowserWithWebContents(
410 web_ui()->GetWebContents());
411 chrome::ShowHelp(browser, chrome::HELP_SOURCE_WEBUI);
414 #if defined(OS_CHROMEOS)
416 void HelpHandler::SetChannel(const base::ListValue* args) {
417 DCHECK(args->GetSize() == 2);
419 if (!CanChangeChannel()) {
420 LOG(WARNING) << "Non-owner tried to change release track.";
424 base::string16 channel;
425 bool is_powerwash_allowed;
426 if (!args->GetString(0, &channel) ||
427 !args->GetBoolean(1, &is_powerwash_allowed)) {
428 LOG(ERROR) << "Can't parse SetChannel() args";
432 version_updater_->SetChannel(base::UTF16ToUTF8(channel),
433 is_powerwash_allowed);
434 if (user_manager::UserManager::Get()->IsCurrentUserOwner()) {
435 // Check for update after switching release channel.
436 version_updater_->CheckForUpdate(base::Bind(&HelpHandler::SetUpdateStatus,
437 base::Unretained(this)));
441 void HelpHandler::RelaunchAndPowerwash(const base::ListValue* args) {
442 DCHECK(args->empty());
444 if (IsEnterpriseManaged())
447 PrefService* prefs = g_browser_process->local_state();
448 prefs->SetBoolean(prefs::kFactoryResetRequested, true);
449 prefs->CommitPendingWrite();
451 // Perform sign out. Current chrome process will then terminate, new one will
452 // be launched (as if it was a restart).
453 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
456 #endif // defined(OS_CHROMEOS)
458 void HelpHandler::SetUpdateStatus(VersionUpdater::Status status,
459 int progress, const base::string16& message) {
460 // Only UPDATING state should have progress set.
461 DCHECK(status == VersionUpdater::UPDATING || progress == 0);
463 std::string status_str;
465 case VersionUpdater::CHECKING:
466 status_str = "checking";
468 case VersionUpdater::UPDATING:
469 status_str = "updating";
471 case VersionUpdater::NEARLY_UPDATED:
472 status_str = "nearly_updated";
474 case VersionUpdater::UPDATED:
475 status_str = "updated";
477 case VersionUpdater::FAILED:
478 case VersionUpdater::FAILED_OFFLINE:
479 case VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED:
480 status_str = "failed";
482 case VersionUpdater::DISABLED:
483 status_str = "disabled";
487 web_ui()->CallJavascriptFunction("help.HelpPage.setUpdateStatus",
488 base::StringValue(status_str),
489 base::StringValue(message));
491 if (status == VersionUpdater::UPDATING) {
492 web_ui()->CallJavascriptFunction("help.HelpPage.setProgress",
493 base::FundamentalValue(progress));
496 #if defined(OS_CHROMEOS)
497 if (status == VersionUpdater::FAILED_OFFLINE ||
498 status == VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED) {
499 base::string16 types_msg = GetAllowedConnectionTypesMessage();
500 if (!types_msg.empty()) {
501 web_ui()->CallJavascriptFunction(
502 "help.HelpPage.setAndShowAllowedConnectionTypesMsg",
503 base::StringValue(types_msg));
505 web_ui()->CallJavascriptFunction(
506 "help.HelpPage.showAllowedConnectionTypesMsg",
507 base::FundamentalValue(false));
510 web_ui()->CallJavascriptFunction(
511 "help.HelpPage.showAllowedConnectionTypesMsg",
512 base::FundamentalValue(false));
514 #endif // defined(OS_CHROMEOS)
517 #if defined(OS_MACOSX)
518 void HelpHandler::SetPromotionState(VersionUpdater::PromotionState state) {
519 std::string state_str;
521 case VersionUpdater::PROMOTE_HIDDEN:
522 state_str = "hidden";
524 case VersionUpdater::PROMOTE_ENABLED:
525 state_str = "enabled";
527 case VersionUpdater::PROMOTE_DISABLED:
528 state_str = "disabled";
532 web_ui()->CallJavascriptFunction("help.HelpPage.setPromotionState",
533 base::StringValue(state_str));
535 #endif // defined(OS_MACOSX)
537 #if defined(OS_CHROMEOS)
538 void HelpHandler::OnOSVersion(const std::string& version) {
539 web_ui()->CallJavascriptFunction("help.HelpPage.setOSVersion",
540 base::StringValue(version));
543 void HelpHandler::OnOSFirmware(const std::string& firmware) {
544 web_ui()->CallJavascriptFunction("help.HelpPage.setOSFirmware",
545 base::StringValue(firmware));
548 void HelpHandler::OnCurrentChannel(const std::string& channel) {
549 web_ui()->CallJavascriptFunction(
550 "help.HelpPage.updateCurrentChannel", base::StringValue(channel));
553 void HelpHandler::OnTargetChannel(const std::string& channel) {
554 web_ui()->CallJavascriptFunction(
555 "help.HelpPage.updateTargetChannel", base::StringValue(channel));
558 #endif // defined(OS_CHROMEOS)