1 // Copyright 2014 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 cr
.define('help', function() {
6 var Page
= cr
.ui
.pageManager
.Page
;
7 var PageManager
= cr
.ui
.pageManager
.PageManager
;
10 * Encapsulated handling of the About page. Called 'help' internally to avoid
11 * confusion with generic AboutUI (about:memory, about:sandbox, etc.).
14 var id
= loadTimeData
.valueExists('aboutOverlayTabTitle') ?
15 'aboutOverlayTabTitle' : 'aboutTitle';
16 Page
.call(this, 'help', loadTimeData
.getString(id
), 'help-page');
19 cr
.addSingletonGetter(HelpPage
);
21 HelpPage
.prototype = {
22 __proto__
: Page
.prototype,
25 * List of the channel names. Should be ordered in increasing level of
29 channelList_
: ['dev-channel', 'beta-channel', 'stable-channel'],
32 * Name of the channel the device is currently on.
35 currentChannel_
: null,
38 * Name of the channel the device is supposed to be on.
44 * Last status received from the version updater.
50 * Last message received from the version updater.
56 * True if user is allowed to change channels, false otherwise.
59 can_change_channel_
: false,
62 initializePage: function() {
63 Page
.prototype.initializePage
.call(this);
65 $('product-license').innerHTML
= loadTimeData
.getString('productLicense');
67 $('product-os-license').innerHTML
=
68 loadTimeData
.getString('productOsLicense');
71 var productTOS
= $('product-tos');
73 productTOS
.innerHTML
= loadTimeData
.getString('productTOS');
75 $('get-help').onclick = function() {
76 chrome
.send('openHelpPage');
78 <if expr
="_google_chrome">
79 $('report-issue').onclick = function() {
80 chrome
.send('openFeedbackDialog');
84 this.maybeSetOnClick_($('more-info-expander'),
85 this.toggleMoreInfo_
.bind(this));
87 this.maybeSetOnClick_($('promote'), function() {
88 chrome
.send('promoteUpdater');
90 this.maybeSetOnClick_($('relaunch'), function() {
91 chrome
.send('relaunchNow');
94 this.maybeSetOnClick_($('relaunch-and-powerwash'), function() {
95 chrome
.send('relaunchAndPowerwash');
98 this.channelTable_
= {
100 'name': loadTimeData
.getString('stable'),
101 'label': loadTimeData
.getString('currentChannelStable'),
104 'name': loadTimeData
.getString('beta'),
105 'label': loadTimeData
.getString('currentChannelBeta')
108 'name': loadTimeData
.getString('dev'),
109 'label': loadTimeData
.getString('currentChannelDev')
113 this.maybeSetOnClick_($('about-done'), function() {
114 // Event listener for the close button when shown as an overlay.
115 PageManager
.closeOverlay();
119 var channelChanger
= $('channel-changer');
120 if (channelChanger
) {
121 channelChanger
.onchange = function(event
) {
122 self
.setChannel_(event
.target
.value
, false);
127 // Add event listener for the check for and apply updates button.
128 this.maybeSetOnClick_($('request-update'), function() {
129 self
.setUpdateStatus_('checking');
130 $('request-update').disabled
= true;
131 chrome
.send('requestUpdate');
134 $('change-channel').onclick = function() {
135 PageManager
.showPageByName('channel-change-page', false);
138 var channelChangeDisallowedError
= document
.createElement('div');
139 channelChangeDisallowedError
.className
= 'channel-change-error-bubble';
141 var channelChangeDisallowedIcon
= document
.createElement('div');
142 channelChangeDisallowedIcon
.className
=
143 'help-page-icon channel-change-error-icon';
144 channelChangeDisallowedError
.appendChild(channelChangeDisallowedIcon
);
146 var channelChangeDisallowedText
= document
.createElement('div');
147 channelChangeDisallowedText
.className
= 'channel-change-error-text';
148 channelChangeDisallowedText
.textContent
=
149 loadTimeData
.getString('channelChangeDisallowedMessage');
150 channelChangeDisallowedError
.appendChild(channelChangeDisallowedText
);
152 $('channel-change-disallowed-icon').onclick = function() {
153 PageManager
.showBubble(channelChangeDisallowedError
,
154 $('channel-change-disallowed-icon'),
156 cr
.ui
.ArrowLocation
.TOP_END
);
159 // Unhide the regulatory label if/when the image loads.
160 $('regulatory-label').onload = function() {
161 $('regulatory-label-container').hidden
= false;
165 var logo
= $('product-logo');
166 logo
.onclick = function(e
) {
167 logo
.classList
.remove('spin');
168 setTimeout(function() { logo
.classList
.add('spin'); }, 0);
171 // Attempt to update.
172 chrome
.send('onPageLoaded');
176 didClosePage: function() {
177 this.setMoreInfoVisible_(false);
181 * Sets the visible state of the 'More Info' section.
182 * @param {boolean} visible Whether the section should be visible.
185 setMoreInfoVisible_: function(visible
) {
186 var moreInfo
= $('more-info-container');
187 if (!moreInfo
|| visible
== moreInfo
.classList
.contains('visible'))
190 moreInfo
.classList
.toggle('visible', visible
);
191 moreInfo
.style
.height
= visible
? moreInfo
.scrollHeight
+ 'px' : '';
192 moreInfo
.addEventListener('webkitTransitionEnd', function(event
) {
193 $('more-info-expander').textContent
= visible
?
194 loadTimeData
.getString('hideMoreInfo') :
195 loadTimeData
.getString('showMoreInfo');
200 * Toggles the visible state of the 'More Info' section.
203 toggleMoreInfo_: function() {
204 var moreInfo
= $('more-info-container');
205 this.setMoreInfoVisible_(!moreInfo
.classList
.contains('visible'));
209 * Assigns |method| to the onclick property of |el| if |el| exists.
210 * @param {HTMLElement} el The element on which to set the click handler.
211 * @param {Function} method The click handler.
214 maybeSetOnClick_: function(el
, method
) {
220 * @param {string} state The state of the update.
223 setUpdateImage_: function(state
) {
224 $('update-status-icon').className
= 'help-page-icon ' + state
;
228 * @return {boolean} True, if new channel switcher UI is used,
232 isNewChannelSwitcherUI_: function() {
233 return !loadTimeData
.valueExists('disableNewChannelSwitcherUI');
237 * @return {boolean} True if target and current channels are not null and
241 channelsDiffer_: function() {
242 var current
= this.currentChannel_
;
243 var target
= this.targetChannel_
;
244 return (current
!= null && target
!= null && current
!= target
);
248 * @return {boolean} True if target channel is more stable than the current
249 * one, and false otherwise.
252 targetChannelIsMoreStable_: function() {
253 var current
= this.currentChannel_
;
254 var target
= this.targetChannel_
;
255 if (current
== null || target
== null)
257 var currentIndex
= this.channelList_
.indexOf(current
);
258 var targetIndex
= this.channelList_
.indexOf(target
);
259 if (currentIndex
< 0 || targetIndex
< 0)
261 return currentIndex
< targetIndex
;
265 * @param {string} status The status of the update.
266 * @param {string} message Failure message to display.
269 setUpdateStatus_: function(status
, message
) {
270 this.status_
= status
;
271 this.message_
= message
;
277 * Updates UI elements on the page according to current state.
280 updateUI_: function() {
281 var status
= this.status_
;
282 var message
= this.message_
;
283 var channel
= this.targetChannel_
;
285 if (this.channelList_
.indexOf(channel
) >= 0) {
286 $('current-channel').textContent
= loadTimeData
.getStringF(
287 'currentChannel', this.channelTable_
[channel
].label
);
288 this.updateChannelChangePageContainerVisibility_();
295 $('update-status-message') &&
296 $('update-status-message').hidden
) {
297 // Chrome has reached the end of the line on this system. The
298 // update-obsolete-system message is displayed. No other auto-update
299 // status should be displayed.
303 if (status
== 'checking') {
304 this.setUpdateImage_('working');
305 $('update-status-message').innerHTML
=
306 loadTimeData
.getString('updateCheckStarted');
307 } else if (status
== 'updating') {
308 this.setUpdateImage_('working');
309 if (this.channelsDiffer_()) {
310 $('update-status-message').innerHTML
=
311 loadTimeData
.getStringF('updatingChannelSwitch',
312 this.channelTable_
[channel
].label
);
314 $('update-status-message').innerHTML
=
315 loadTimeData
.getStringF('updating');
317 } else if (status
== 'nearly_updated') {
318 this.setUpdateImage_('up-to-date');
319 if (this.channelsDiffer_()) {
320 $('update-status-message').innerHTML
=
321 loadTimeData
.getString('successfulChannelSwitch');
323 $('update-status-message').innerHTML
=
324 loadTimeData
.getString('updateAlmostDone');
326 } else if (status
== 'updated') {
327 this.setUpdateImage_('up-to-date');
328 $('update-status-message').innerHTML
=
329 loadTimeData
.getString('upToDate');
330 } else if (status
== 'failed') {
331 this.setUpdateImage_('failed');
332 $('update-status-message').innerHTML
= message
;
336 $('change-channel').disabled
= !this.can_change_channel_
||
337 status
== 'nearly_updated';
338 $('channel-change-disallowed-icon').hidden
= this.can_change_channel_
;
341 // Following invariant must be established at the end of this function:
342 // { ~$('relaunch_and_powerwash').hidden -> $('relaunch').hidden }
343 var relaunchAndPowerwashHidden
= true;
344 if ($('relaunch-and-powerwash')) {
345 // It's allowed to do powerwash only for customer devices,
346 // when user explicitly decides to update to a more stable
348 relaunchAndPowerwashHidden
=
349 !this.targetChannelIsMoreStable_() || status
!= 'nearly_updated';
350 $('relaunch-and-powerwash').hidden
= relaunchAndPowerwashHidden
;
354 // Only enable the update button if it hasn't been used yet or the
355 // status isn't 'updated'.
356 if (!$('request-update').disabled
|| status
!= 'updated') {
357 // Disable the button if an update is already in progress.
358 $('request-update').disabled
=
359 ['checking', 'updating', 'nearly_updated'].indexOf(status
) > -1;
363 var container
= $('update-status-container');
365 container
.hidden
= status
== 'disabled';
366 $('relaunch').hidden
=
367 (status
!= 'nearly_updated') || !relaunchAndPowerwashHidden
;
370 // Assume the "updated" status is stale if we haven't checked yet.
371 if (status
== 'updated' && !$('request-update').disabled
)
372 container
.hidden
= true;
374 // Hide the request update button if auto-updating is disabled or
375 // a relaunch button is showing.
376 $('request-update').hidden
= status
== 'disabled' ||
377 !$('relaunch').hidden
|| !relaunchAndPowerwashHidden
;
381 $('update-percentage').hidden
= status
!= 'updating';
386 * @param {number} progress The percent completion.
389 setProgress_: function(progress
) {
390 $('update-percentage').innerHTML
= progress
+ '%';
394 * @param {string} message The allowed connection types message.
397 setAllowedConnectionTypesMsg_: function(message
) {
398 $('allowed-connection-types-message').innerText
= message
;
402 * @param {boolean} visible Whether to show the message.
405 showAllowedConnectionTypesMsg_: function(visible
) {
406 $('allowed-connection-types-message').hidden
= !visible
;
410 * @param {string} state The promote state to set.
413 setPromotionState_: function(state
) {
414 if (state
== 'hidden') {
415 $('promote').hidden
= true;
416 } else if (state
== 'enabled') {
417 $('promote').disabled
= false;
418 $('promote').hidden
= false;
419 } else if (state
== 'disabled') {
420 $('promote').disabled
= true;
421 $('promote').hidden
= false;
426 * @param {boolean} obsolete Whether the system is obsolete.
429 setObsoleteSystem_: function(obsolete
) {
430 if (cr
.isMac
&& $('update-obsolete-system-container')) {
431 $('update-obsolete-system-container').hidden
= !obsolete
;
436 * @param {boolean} endOfTheLine Whether the train has rolled into
440 setObsoleteSystemEndOfTheLine_: function(endOfTheLine
) {
442 $('update-obsolete-system-container') &&
443 !$('update-obsolete-system-container').hidden
&&
444 $('update-status-message')) {
445 $('update-status-message').hidden
= endOfTheLine
;
447 this.setUpdateImage_('failed');
453 * @param {string} version Version of Chrome OS.
456 setOSVersion_: function(version
) {
458 console
.error('OS version unsupported on non-CrOS');
460 $('os-version').parentNode
.hidden
= (version
== '');
461 $('os-version').textContent
= version
;
465 * @param {string} firmware Firmware on Chrome OS.
468 setOSFirmware_: function(firmware
) {
470 console
.error('OS firmware unsupported on non-CrOS');
472 $('firmware').parentNode
.hidden
= (firmware
== '');
473 $('firmware').textContent
= firmware
;
477 * Updates page UI according to device owhership policy.
478 * @param {boolean} isEnterpriseManaged True if the device is
479 * enterprise managed.
482 updateIsEnterpriseManaged_: function(isEnterpriseManaged
) {
483 help
.ChannelChangePage
.updateIsEnterpriseManaged(isEnterpriseManaged
);
488 * Updates name of the current channel, i.e. the name of the
489 * channel the device is currently on.
490 * @param {string} channel The name of the current channel.
493 updateCurrentChannel_: function(channel
) {
494 if (this.channelList_
.indexOf(channel
) < 0)
496 this.currentChannel_
= channel
;
497 help
.ChannelChangePage
.updateCurrentChannel(channel
);
502 * Updates name of the target channel, i.e. the name of the
503 * channel the device is supposed to be.
504 * @param {string} channel The name of the target channel.
507 updateTargetChannel_: function(channel
) {
508 if (this.channelList_
.indexOf(channel
) < 0)
510 this.targetChannel_
= channel
;
511 help
.ChannelChangePage
.updateTargetChannel(channel
);
516 * @param {boolean} enabled True if the release channel can be enabled.
519 updateEnableReleaseChannel_: function(enabled
) {
520 this.updateChannelChangerContainerVisibility_(enabled
);
521 this.can_change_channel_
= enabled
;
526 * Sets the device target channel.
527 * @param {string} channel The name of the target channel.
528 * @param {boolean} isPowerwashAllowed True iff powerwash is allowed.
531 setChannel_: function(channel
, isPowerwashAllowed
) {
532 chrome
.send('setChannel', [channel
, isPowerwashAllowed
]);
533 $('channel-change-confirmation').hidden
= false;
534 $('channel-change-confirmation').textContent
= loadTimeData
.getStringF(
535 'channel-changed', this.channelTable_
[channel
].name
);
536 this.updateTargetChannel_(channel
);
540 * Sets the value of the "Build Date" field of the "More Info" section.
541 * @param {string} buildDate The date of the build.
544 setBuildDate_: function(buildDate
) {
545 $('build-date-container').classList
.remove('empty');
546 $('build-date').textContent
= buildDate
;
550 * Updates channel-change-page-container visibility according to
554 updateChannelChangePageContainerVisibility_: function() {
555 if (!this.isNewChannelSwitcherUI_()) {
556 $('channel-change-page-container').hidden
= true;
559 $('channel-change-page-container').hidden
=
560 !help
.ChannelChangePage
.isPageReady();
564 * Updates channel-changer dropdown visibility if |visible| is
565 * true and new channel switcher UI is disallowed.
566 * @param {boolean} visible True if channel-changer should be
567 * displayed, false otherwise.
570 updateChannelChangerContainerVisibility_: function(visible
) {
571 if (this.isNewChannelSwitcherUI_()) {
572 $('channel-changer').hidden
= true;
575 $('channel-changer').hidden
= !visible
;
579 * Sets the regulatory label's source.
580 * @param {string} path The path to use for the image.
583 setRegulatoryLabelPath_: function(path
) {
584 $('regulatory-label').src
= path
;
588 * Sets the regulatory label's alt text.
589 * @param {string} text The text to use for the image.
592 setRegulatoryLabelText_: function(text
) {
593 $('regulatory-label').alt
= text
;
597 HelpPage
.setUpdateStatus = function(status
, message
) {
598 HelpPage
.getInstance().setUpdateStatus_(status
, message
);
601 HelpPage
.setProgress = function(progress
) {
602 HelpPage
.getInstance().setProgress_(progress
);
605 HelpPage
.setAndShowAllowedConnectionTypesMsg = function(message
) {
606 HelpPage
.getInstance().setAllowedConnectionTypesMsg_(message
);
607 HelpPage
.getInstance().showAllowedConnectionTypesMsg_(true);
610 HelpPage
.showAllowedConnectionTypesMsg = function(visible
) {
611 HelpPage
.getInstance().showAllowedConnectionTypesMsg_(visible
);
614 HelpPage
.setPromotionState = function(state
) {
615 HelpPage
.getInstance().setPromotionState_(state
);
618 HelpPage
.setObsoleteSystem = function(obsolete
) {
619 HelpPage
.getInstance().setObsoleteSystem_(obsolete
);
622 HelpPage
.setObsoleteSystemEndOfTheLine = function(endOfTheLine
) {
623 HelpPage
.getInstance().setObsoleteSystemEndOfTheLine_(endOfTheLine
);
626 HelpPage
.setOSVersion = function(version
) {
627 HelpPage
.getInstance().setOSVersion_(version
);
630 HelpPage
.setOSFirmware = function(firmware
) {
631 HelpPage
.getInstance().setOSFirmware_(firmware
);
634 HelpPage
.updateIsEnterpriseManaged = function(isEnterpriseManaged
) {
637 HelpPage
.getInstance().updateIsEnterpriseManaged_(isEnterpriseManaged
);
640 HelpPage
.updateCurrentChannel = function(channel
) {
643 HelpPage
.getInstance().updateCurrentChannel_(channel
);
646 HelpPage
.updateTargetChannel = function(channel
) {
649 HelpPage
.getInstance().updateTargetChannel_(channel
);
652 HelpPage
.updateEnableReleaseChannel = function(enabled
) {
653 HelpPage
.getInstance().updateEnableReleaseChannel_(enabled
);
656 HelpPage
.setChannel = function(channel
, isPowerwashAllowed
) {
657 HelpPage
.getInstance().setChannel_(channel
, isPowerwashAllowed
);
660 HelpPage
.setBuildDate = function(buildDate
) {
661 HelpPage
.getInstance().setBuildDate_(buildDate
);
664 HelpPage
.setRegulatoryLabelPath = function(path
) {
665 assert(cr
.isChromeOS
);
666 HelpPage
.getInstance().setRegulatoryLabelPath_(path
);
669 HelpPage
.setRegulatoryLabelText = function(text
) {
670 assert(cr
.isChromeOS
);
671 HelpPage
.getInstance().setRegulatoryLabelText_(text
);