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/google/google_util.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_commands.h"
22 #include "chrome/browser/ui/browser_finder.h"
23 #include "chrome/browser/ui/chrome_pages.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 "content/public/browser/browser_thread.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/web_ui.h"
30 #include "content/public/browser/web_ui_data_source.h"
31 #include "content/public/common/content_client.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 "ui/base/resource/resource_bundle.h"
37 #include "v8/include/v8.h"
38 #include "webkit/common/user_agent/user_agent_util.h"
40 #if defined(OS_MACOSX)
41 #include "chrome/browser/mac/obsolete_system.h"
44 #if defined(OS_CHROMEOS)
45 #include "base/files/file_util_proxy.h"
46 #include "base/i18n/time_formatting.h"
47 #include "base/prefs/pref_service.h"
48 #include "base/sys_info.h"
49 #include "chrome/browser/chromeos/login/user_manager.h"
50 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
51 #include "chrome/browser/chromeos/settings/cros_settings.h"
52 #include "chrome/browser/profiles/profile.h"
53 #include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
54 #include "chromeos/chromeos_switches.h"
55 #include "chromeos/dbus/dbus_thread_manager.h"
56 #include "chromeos/dbus/power_manager_client.h"
57 #include "content/public/browser/browser_thread.h"
60 using base::ListValue
;
61 using content::BrowserThread
;
65 // Returns the browser version as a string.
66 base::string16
BuildBrowserVersionString() {
67 chrome::VersionInfo version_info
;
68 DCHECK(version_info
.is_valid());
70 std::string browser_version
= version_info
.Version();
71 std::string version_modifier
=
72 chrome::VersionInfo::GetVersionStringModifier();
73 if (!version_modifier
.empty())
74 browser_version
+= " " + version_modifier
;
76 #if !defined(GOOGLE_CHROME_BUILD)
77 browser_version
+= " (";
78 browser_version
+= version_info
.LastChange();
79 browser_version
+= ")";
82 return base::UTF8ToUTF16(browser_version
);
85 #if defined(OS_CHROMEOS)
87 // Returns message that informs user that for update it's better to
88 // connect to a network of one of the allowed types.
89 base::string16
GetAllowedConnectionTypesMessage() {
90 if (help_utils_chromeos::IsUpdateOverCellularAllowed()) {
91 return l10n_util::GetStringUTF16(IDS_UPGRADE_NETWORK_LIST_CELLULAR_ALLOWED
);
93 return l10n_util::GetStringUTF16(
94 IDS_UPGRADE_NETWORK_LIST_CELLULAR_DISALLOWED
);
98 // Returns true if the device is enterprise managed, false otherwise.
99 bool IsEnterpriseManaged() {
100 policy::BrowserPolicyConnectorChromeOS
* connector
=
101 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
102 return connector
->IsEnterpriseManaged();
105 // Returns true if current user can change channel, false otherwise.
106 bool CanChangeChannel() {
108 chromeos::CrosSettings::Get()->GetBoolean(chromeos::kReleaseChannelDelegated
,
111 // On a managed machine we delegate this setting to the users of the same
112 // domain only if the policy value is "domain".
113 if (IsEnterpriseManaged()) {
116 // Get the currently logged in user and strip the domain part only.
117 std::string domain
= "";
118 std::string user
= chromeos::UserManager::Get()->GetLoggedInUser()->email();
119 size_t at_pos
= user
.find('@');
120 if (at_pos
!= std::string::npos
&& at_pos
+ 1 < user
.length())
121 domain
= user
.substr(user
.find('@') + 1);
122 policy::BrowserPolicyConnectorChromeOS
* connector
=
123 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
124 return domain
== connector
->GetEnterpriseDomain();
125 } else if (chromeos::UserManager::Get()->IsCurrentUserOwner()) {
126 // On non managed machines we have local owner who is the only one to change
127 // anything. Ensure that ReleaseChannelDelegated is false.
133 #endif // defined(OS_CHROMEOS)
137 HelpHandler::HelpHandler()
138 : version_updater_(VersionUpdater::Create()),
139 weak_factory_(this) {
142 HelpHandler::~HelpHandler() {
145 void HelpHandler::GetLocalizedValues(content::WebUIDataSource
* source
) {
146 struct L10nResources
{
151 static L10nResources resources
[] = {
152 { "helpTitle", IDS_HELP_TITLE
},
153 { "aboutTitle", IDS_ABOUT_TAB_TITLE
},
154 #if defined(OS_CHROMEOS)
155 { "aboutProductTitle", IDS_PRODUCT_OS_NAME
},
157 { "aboutProductTitle", IDS_PRODUCT_NAME
},
159 { "aboutProductDescription", IDS_ABOUT_PRODUCT_DESCRIPTION
},
160 { "relaunch", IDS_RELAUNCH_BUTTON
},
161 #if defined(OS_CHROMEOS)
162 { "relaunchAndPowerwash", IDS_RELAUNCH_AND_POWERWASH_BUTTON
},
164 { "productName", IDS_PRODUCT_NAME
},
165 { "updateCheckStarted", IDS_UPGRADE_CHECK_STARTED
},
166 { "upToDate", IDS_UPGRADE_UP_TO_DATE
},
167 { "updating", IDS_UPGRADE_UPDATING
},
168 #if defined(OS_CHROMEOS)
169 { "updatingChannelSwitch", IDS_UPGRADE_UPDATING_CHANNEL_SWITCH
},
171 { "updateAlmostDone", IDS_UPGRADE_SUCCESSFUL_RELAUNCH
},
172 #if defined(OS_CHROMEOS)
173 { "successfulChannelSwitch", IDS_UPGRADE_SUCCESSFUL_CHANNEL_SWITCH
},
175 { "getHelpWithChrome", IDS_GET_HELP_USING_CHROME
},
176 { "reportAnIssue", IDS_REPORT_AN_ISSUE
},
177 #if defined(OS_CHROMEOS)
178 { "platform", IDS_PLATFORM_LABEL
},
179 { "firmware", IDS_ABOUT_PAGE_FIRMWARE
},
180 { "showMoreInfo", IDS_SHOW_MORE_INFO
},
181 { "hideMoreInfo", IDS_HIDE_MORE_INFO
},
182 { "channel", IDS_ABOUT_PAGE_CHANNEL
},
183 { "stable", IDS_ABOUT_PAGE_CHANNEL_STABLE
},
184 { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA
},
185 { "dev", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT
},
186 { "channel-changed", IDS_ABOUT_PAGE_CHANNEL_CHANGED
},
187 { "currentChannelStable", IDS_ABOUT_PAGE_CURRENT_CHANNEL_STABLE
},
188 { "currentChannelBeta", IDS_ABOUT_PAGE_CURRENT_CHANNEL_BETA
},
189 { "currentChannelDev", IDS_ABOUT_PAGE_CURRENT_CHANNEL_DEV
},
190 { "currentChannel", IDS_ABOUT_PAGE_CURRENT_CHANNEL
},
191 { "channelChangeButton", IDS_ABOUT_PAGE_CHANNEL_CHANGE_BUTTON
},
192 { "channelChangeDisallowedMessage",
193 IDS_ABOUT_PAGE_CHANNEL_CHANGE_DISALLOWED_MESSAGE
},
194 { "channelChangePageTitle", IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_TITLE
},
195 { "channelChangePagePowerwashTitle",
196 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_TITLE
},
197 { "channelChangePagePowerwashMessage",
198 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_MESSAGE
},
199 { "channelChangePageDelayedChangeTitle",
200 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_DELAYED_CHANGE_TITLE
},
201 { "channelChangePageUnstableTitle",
202 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_UNSTABLE_TITLE
},
203 { "channelChangePagePowerwashButton",
204 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_POWERWASH_BUTTON
},
205 { "channelChangePageChangeButton",
206 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_CHANGE_BUTTON
},
207 { "channelChangePageCancelButton",
208 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_CANCEL_BUTTON
},
209 { "webkit", IDS_WEBKIT
},
210 { "userAgent", IDS_ABOUT_VERSION_USER_AGENT
},
211 { "commandLine", IDS_ABOUT_VERSION_COMMAND_LINE
},
212 { "buildDate", IDS_ABOUT_VERSION_BUILD_DATE
},
214 #if defined(OS_MACOSX)
215 { "promote", IDS_ABOUT_CHROME_PROMOTE_UPDATER
},
216 { "learnMore", IDS_LEARN_MORE
},
220 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(resources
); ++i
) {
221 source
->AddString(resources
[i
].name
,
222 l10n_util::GetStringUTF16(resources
[i
].ids
));
225 #if defined(OS_MACOSX)
226 source
->AddString("updateObsoleteSystem",
227 ObsoleteSystemMac::LocalizedObsoleteSystemString());
228 source
->AddString("updateObsoleteSystemURL",
229 chrome::kMac32BitDeprecationURL
);
234 l10n_util::GetStringFUTF16(IDS_ABOUT_PRODUCT_VERSION
,
235 BuildBrowserVersionString()));
237 base::Time::Exploded exploded_time
;
238 base::Time::Now().LocalExplode(&exploded_time
);
241 l10n_util::GetStringFUTF16(IDS_ABOUT_VERSION_COPYRIGHT
,
242 base::IntToString16(exploded_time
.year
)));
244 base::string16 license
= l10n_util::GetStringFUTF16(
245 IDS_ABOUT_VERSION_LICENSE
,
246 base::ASCIIToUTF16(chrome::kChromiumProjectURL
),
247 base::ASCIIToUTF16(chrome::kChromeUICreditsURL
));
248 source
->AddString("productLicense", license
);
250 #if defined(OS_CHROMEOS)
251 base::string16 os_license
= l10n_util::GetStringFUTF16(
252 IDS_ABOUT_CROS_VERSION_LICENSE
,
253 base::ASCIIToUTF16(chrome::kChromeUIOSCreditsURL
));
254 source
->AddString("productOsLicense", os_license
);
256 base::string16 product_name
= l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME
);
258 "channelChangePageDelayedChangeMessage",
259 l10n_util::GetStringFUTF16(
260 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_DELAYED_CHANGE_MESSAGE
,
263 "channelChangePageUnstableMessage",
264 l10n_util::GetStringFUTF16(
265 IDS_ABOUT_PAGE_CHANNEL_CHANGE_PAGE_UNSTABLE_MESSAGE
,
268 if (CommandLine::ForCurrentProcess()->
269 HasSwitch(chromeos::switches::kDisableNewChannelSwitcherUI
)) {
270 source
->AddBoolean("disableNewChannelSwitcherUI", true);
274 base::string16 tos
= l10n_util::GetStringFUTF16(
275 IDS_ABOUT_TERMS_OF_SERVICE
, base::UTF8ToUTF16(chrome::kChromeUITermsURL
));
276 source
->AddString("productTOS", tos
);
278 source
->AddString("webkitVersion", webkit_glue::GetWebKitVersion());
280 source
->AddString("jsEngine", "V8");
281 source
->AddString("jsEngineVersion", v8::V8::GetVersion());
283 source
->AddString("userAgentInfo", content::GetUserAgent(GURL()));
285 CommandLine::StringType command_line
=
286 CommandLine::ForCurrentProcess()->GetCommandLineString();
287 source
->AddString("commandLineInfo", command_line
);
290 void HelpHandler::RegisterMessages() {
291 registrar_
.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED
,
292 content::NotificationService::AllSources());
294 web_ui()->RegisterMessageCallback("onPageLoaded",
295 base::Bind(&HelpHandler::OnPageLoaded
, base::Unretained(this)));
296 web_ui()->RegisterMessageCallback("relaunchNow",
297 base::Bind(&HelpHandler::RelaunchNow
, base::Unretained(this)));
298 web_ui()->RegisterMessageCallback("openFeedbackDialog",
299 base::Bind(&HelpHandler::OpenFeedbackDialog
, base::Unretained(this)));
300 web_ui()->RegisterMessageCallback("openHelpPage",
301 base::Bind(&HelpHandler::OpenHelpPage
, base::Unretained(this)));
302 #if defined(OS_CHROMEOS)
303 web_ui()->RegisterMessageCallback("setChannel",
304 base::Bind(&HelpHandler::SetChannel
, base::Unretained(this)));
305 web_ui()->RegisterMessageCallback("relaunchAndPowerwash",
306 base::Bind(&HelpHandler::RelaunchAndPowerwash
, base::Unretained(this)));
308 #if defined(OS_MACOSX)
309 web_ui()->RegisterMessageCallback("promoteUpdater",
310 base::Bind(&HelpHandler::PromoteUpdater
, base::Unretained(this)));
314 void HelpHandler::Observe(int type
, const content::NotificationSource
& source
,
315 const content::NotificationDetails
& details
) {
317 case chrome::NOTIFICATION_UPGRADE_RECOMMENDED
: {
318 // A version update is installed and ready to go. Refresh the UI so the
319 // correct state will be shown.
320 version_updater_
->CheckForUpdate(
321 base::Bind(&HelpHandler::SetUpdateStatus
, base::Unretained(this))
322 #if defined(OS_MACOSX)
323 , base::Bind(&HelpHandler::SetPromotionState
, base::Unretained(this))
333 void HelpHandler::OnPageLoaded(const base::ListValue
* args
) {
334 #if defined(OS_CHROMEOS)
335 // Version information is loaded from a callback
337 chromeos::VersionLoader::VERSION_FULL
,
338 base::Bind(&HelpHandler::OnOSVersion
, base::Unretained(this)),
341 base::Bind(&HelpHandler::OnOSFirmware
, base::Unretained(this)),
344 web_ui()->CallJavascriptFunction(
345 "help.HelpPage.updateEnableReleaseChannel",
346 base::FundamentalValue(CanChangeChannel()));
348 base::Time build_time
= base::SysInfo::GetLsbReleaseTime();
349 base::string16 build_date
= base::TimeFormatFriendlyDate(build_time
);
350 web_ui()->CallJavascriptFunction("help.HelpPage.setBuildDate",
351 base::StringValue(build_date
));
352 #endif // defined(OS_CHROMEOS)
354 version_updater_
->CheckForUpdate(
355 base::Bind(&HelpHandler::SetUpdateStatus
, base::Unretained(this))
356 #if defined(OS_MACOSX)
357 , base::Bind(&HelpHandler::SetPromotionState
, base::Unretained(this))
361 #if defined(OS_MACOSX)
362 web_ui()->CallJavascriptFunction(
363 "help.HelpPage.setObsoleteSystem",
364 base::FundamentalValue(ObsoleteSystemMac::Is32BitObsoleteNowOrSoon() &&
365 ObsoleteSystemMac::Has32BitOnlyCPU()));
366 web_ui()->CallJavascriptFunction(
367 "help.HelpPage.setObsoleteSystemEndOfTheLine",
368 base::FundamentalValue(ObsoleteSystemMac::Is32BitObsoleteNowOrSoon() &&
369 ObsoleteSystemMac::Is32BitEndOfTheLine()));
372 #if defined(OS_CHROMEOS)
373 web_ui()->CallJavascriptFunction(
374 "help.HelpPage.updateIsEnterpriseManaged",
375 base::FundamentalValue(IsEnterpriseManaged()));
376 // First argument to GetChannel() is a flag that indicates whether
377 // current channel should be returned (if true) or target channel
379 version_updater_
->GetChannel(true,
380 base::Bind(&HelpHandler::OnCurrentChannel
, weak_factory_
.GetWeakPtr()));
381 version_updater_
->GetChannel(false,
382 base::Bind(&HelpHandler::OnTargetChannel
, weak_factory_
.GetWeakPtr()));
386 #if defined(OS_MACOSX)
387 void HelpHandler::PromoteUpdater(const base::ListValue
* args
) {
388 version_updater_
->PromoteUpdater();
392 void HelpHandler::RelaunchNow(const base::ListValue
* args
) {
393 DCHECK(args
->empty());
394 version_updater_
->RelaunchBrowser();
397 void HelpHandler::OpenFeedbackDialog(const base::ListValue
* args
) {
398 DCHECK(args
->empty());
399 Browser
* browser
= chrome::FindBrowserWithWebContents(
400 web_ui()->GetWebContents());
401 chrome::OpenFeedbackDialog(browser
);
404 void HelpHandler::OpenHelpPage(const base::ListValue
* args
) {
405 DCHECK(args
->empty());
406 Browser
* browser
= chrome::FindBrowserWithWebContents(
407 web_ui()->GetWebContents());
408 chrome::ShowHelp(browser
, chrome::HELP_SOURCE_WEBUI
);
411 #if defined(OS_CHROMEOS)
413 void HelpHandler::SetChannel(const base::ListValue
* args
) {
414 DCHECK(args
->GetSize() == 2);
416 if (!CanChangeChannel()) {
417 LOG(WARNING
) << "Non-owner tried to change release track.";
421 base::string16 channel
;
422 bool is_powerwash_allowed
;
423 if (!args
->GetString(0, &channel
) ||
424 !args
->GetBoolean(1, &is_powerwash_allowed
)) {
425 LOG(ERROR
) << "Can't parse SetChannel() args";
429 version_updater_
->SetChannel(base::UTF16ToUTF8(channel
),
430 is_powerwash_allowed
);
431 if (chromeos::UserManager::Get()->IsCurrentUserOwner()) {
432 // Check for update after switching release channel.
433 version_updater_
->CheckForUpdate(base::Bind(&HelpHandler::SetUpdateStatus
,
434 base::Unretained(this)));
438 void HelpHandler::RelaunchAndPowerwash(const base::ListValue
* args
) {
439 DCHECK(args
->empty());
441 if (IsEnterpriseManaged())
444 PrefService
* prefs
= g_browser_process
->local_state();
445 prefs
->SetBoolean(prefs::kFactoryResetRequested
, true);
446 prefs
->CommitPendingWrite();
448 // Perform sign out. Current chrome process will then terminate, new one will
449 // be launched (as if it was a restart).
450 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
453 #endif // defined(OS_CHROMEOS)
455 void HelpHandler::SetUpdateStatus(VersionUpdater::Status status
,
456 int progress
, const base::string16
& message
) {
457 // Only UPDATING state should have progress set.
458 DCHECK(status
== VersionUpdater::UPDATING
|| progress
== 0);
460 std::string status_str
;
462 case VersionUpdater::CHECKING
:
463 status_str
= "checking";
465 case VersionUpdater::UPDATING
:
466 status_str
= "updating";
468 case VersionUpdater::NEARLY_UPDATED
:
469 status_str
= "nearly_updated";
471 case VersionUpdater::UPDATED
:
472 status_str
= "updated";
474 case VersionUpdater::FAILED
:
475 case VersionUpdater::FAILED_OFFLINE
:
476 case VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED
:
477 status_str
= "failed";
479 case VersionUpdater::DISABLED
:
480 status_str
= "disabled";
484 web_ui()->CallJavascriptFunction("help.HelpPage.setUpdateStatus",
485 base::StringValue(status_str
),
486 base::StringValue(message
));
488 if (status
== VersionUpdater::UPDATING
) {
489 web_ui()->CallJavascriptFunction("help.HelpPage.setProgress",
490 base::FundamentalValue(progress
));
493 #if defined(OS_CHROMEOS)
494 if (status
== VersionUpdater::FAILED_OFFLINE
||
495 status
== VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED
) {
496 base::string16 types_msg
= GetAllowedConnectionTypesMessage();
497 if (!types_msg
.empty()) {
498 web_ui()->CallJavascriptFunction(
499 "help.HelpPage.setAndShowAllowedConnectionTypesMsg",
500 base::StringValue(types_msg
));
502 web_ui()->CallJavascriptFunction(
503 "help.HelpPage.showAllowedConnectionTypesMsg",
504 base::FundamentalValue(false));
507 web_ui()->CallJavascriptFunction(
508 "help.HelpPage.showAllowedConnectionTypesMsg",
509 base::FundamentalValue(false));
511 #endif // defined(OS_CHROMEOS)
514 #if defined(OS_MACOSX)
515 void HelpHandler::SetPromotionState(VersionUpdater::PromotionState state
) {
516 std::string state_str
;
518 case VersionUpdater::PROMOTE_HIDDEN
:
519 state_str
= "hidden";
521 case VersionUpdater::PROMOTE_ENABLED
:
522 state_str
= "enabled";
524 case VersionUpdater::PROMOTE_DISABLED
:
525 state_str
= "disabled";
529 web_ui()->CallJavascriptFunction("help.HelpPage.setPromotionState",
530 base::StringValue(state_str
));
532 #endif // defined(OS_MACOSX)
534 #if defined(OS_CHROMEOS)
535 void HelpHandler::OnOSVersion(const std::string
& version
) {
536 web_ui()->CallJavascriptFunction("help.HelpPage.setOSVersion",
537 base::StringValue(version
));
540 void HelpHandler::OnOSFirmware(const std::string
& firmware
) {
541 web_ui()->CallJavascriptFunction("help.HelpPage.setOSFirmware",
542 base::StringValue(firmware
));
545 void HelpHandler::OnCurrentChannel(const std::string
& channel
) {
546 web_ui()->CallJavascriptFunction(
547 "help.HelpPage.updateCurrentChannel", base::StringValue(channel
));
550 void HelpHandler::OnTargetChannel(const std::string
& channel
) {
551 web_ui()->CallJavascriptFunction(
552 "help.HelpPage.updateTargetChannel", base::StringValue(channel
));
555 #endif // defined(OS_CHROMEOS)