Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / help / help_page.js
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.
4
5 cr.define('help', function() {
6   var Page = cr.ui.pageManager.Page;
7   var PageManager = cr.ui.pageManager.PageManager;
8
9   /**
10    * Encapsulated handling of the About page. Called 'help' internally to avoid
11    * confusion with generic AboutUI (about:memory, about:sandbox, etc.).
12    */
13   function HelpPage() {
14     var id = loadTimeData.valueExists('aboutOverlayTabTitle') ?
15       'aboutOverlayTabTitle' : 'aboutTitle';
16     Page.call(this, 'help', loadTimeData.getString(id), 'help-page');
17   }
18
19   cr.addSingletonGetter(HelpPage);
20
21   HelpPage.prototype = {
22     __proto__: Page.prototype,
23
24     /**
25      * List of the channel names. Should be ordered in increasing level of
26      * stability.
27      * @private
28      */
29     channelList_: ['dev-channel', 'beta-channel', 'stable-channel'],
30
31     /**
32      * Name of the channel the device is currently on.
33      * @private
34      */
35     currentChannel_: null,
36
37     /**
38      * Name of the channel the device is supposed to be on.
39      * @private
40      */
41     targetChannel_: null,
42
43     /**
44      * Last status received from the version updater.
45      * @private
46      */
47     status_: null,
48
49     /**
50      * Last message received from the version updater.
51      * @private
52      */
53     message_: null,
54
55     /**
56      * True if user is allowed to change channels, false otherwise.
57      * @private
58      */
59     can_change_channel_: false,
60
61     /** @override */
62     initializePage: function() {
63       Page.prototype.initializePage.call(this);
64
65       $('product-license').innerHTML = loadTimeData.getString('productLicense');
66       if (cr.isChromeOS) {
67         $('product-os-license').innerHTML =
68             loadTimeData.getString('productOsLicense');
69       }
70
71       var productTOS = $('product-tos');
72       if (productTOS)
73         productTOS.innerHTML = loadTimeData.getString('productTOS');
74
75       $('get-help').onclick = function() {
76         chrome.send('openHelpPage');
77       };
78 <if expr="_google_chrome">
79       $('report-issue').onclick = function() {
80         chrome.send('openFeedbackDialog');
81       };
82 </if>
83
84       this.maybeSetOnClick_($('more-info-expander'),
85           this.toggleMoreInfo_.bind(this));
86
87       this.maybeSetOnClick_($('promote'), function() {
88         chrome.send('promoteUpdater');
89       });
90       this.maybeSetOnClick_($('relaunch'), function() {
91         chrome.send('relaunchNow');
92       });
93       if (cr.isChromeOS) {
94         this.maybeSetOnClick_($('relaunch-and-powerwash'), function() {
95           chrome.send('relaunchAndPowerwash');
96         });
97
98         this.channelTable_ = {
99           'stable-channel': {
100             'name': loadTimeData.getString('stable'),
101             'label': loadTimeData.getString('currentChannelStable'),
102           },
103           'beta-channel': {
104             'name': loadTimeData.getString('beta'),
105             'label': loadTimeData.getString('currentChannelBeta')
106           },
107           'dev-channel': {
108             'name': loadTimeData.getString('dev'),
109             'label': loadTimeData.getString('currentChannelDev')
110           }
111         };
112       }
113       this.maybeSetOnClick_($('about-done'), function() {
114         // Event listener for the close button when shown as an overlay.
115         PageManager.closeOverlay();
116       });
117
118       var self = this;
119       var channelChanger = $('channel-changer');
120       if (channelChanger) {
121         channelChanger.onchange = function(event) {
122           self.setChannel_(event.target.value, false);
123         };
124       }
125
126       if (cr.isChromeOS) {
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');
132         });
133
134         $('change-channel').onclick = function() {
135           PageManager.showPageByName('channel-change-page', false);
136         };
137
138         var channelChangeDisallowedError = document.createElement('div');
139         channelChangeDisallowedError.className = 'channel-change-error-bubble';
140
141         var channelChangeDisallowedIcon = document.createElement('div');
142         channelChangeDisallowedIcon.classList.add('help-page-icon-large');
143         channelChangeDisallowedIcon.classList.add('channel-change-error-icon');
144         channelChangeDisallowedError.appendChild(channelChangeDisallowedIcon);
145
146         var channelChangeDisallowedText = document.createElement('div');
147         channelChangeDisallowedText.className = 'channel-change-error-text';
148         channelChangeDisallowedText.textContent =
149             loadTimeData.getString('channelChangeDisallowedMessage');
150         channelChangeDisallowedError.appendChild(channelChangeDisallowedText);
151
152         $('channel-change-disallowed-icon').onclick = function() {
153           PageManager.showBubble(channelChangeDisallowedError,
154                                  $('channel-change-disallowed-icon'),
155                                  $('help-container'),
156                                  cr.ui.ArrowLocation.TOP_END);
157         };
158
159         // Unhide the product label if/when the image loads.
160         var productLabel = $('product-label');
161         var show = function() { $('product-label-container').hidden = false; };
162         if (productLabel.naturalWidth)
163           show();
164         else
165           productLabel.onload = show;
166       }
167
168       var logo = $('product-logo');
169       logo.onclick = function(e) {
170         logo.classList.remove('spin');
171         setTimeout(function() { logo.classList.add('spin'); }, 0);
172       };
173
174       // Attempt to update.
175       chrome.send('onPageLoaded');
176     },
177
178     /** @override */
179     didClosePage: function() {
180       this.setMoreInfoVisible_(false);
181     },
182
183     /**
184      * Sets the visible state of the 'More Info' section.
185      * @param {boolean} visible Whether the section should be visible.
186      * @private
187      */
188     setMoreInfoVisible_: function(visible) {
189       var moreInfo = $('more-info-container');
190       if (visible == moreInfo.classList.contains('visible'))
191         return;
192
193       moreInfo.classList.toggle('visible', visible);
194       moreInfo.style.height = visible ? moreInfo.scrollHeight + 'px' : '';
195       moreInfo.addEventListener('webkitTransitionEnd', function(event) {
196         $('more-info-expander').textContent = visible ?
197             loadTimeData.getString('hideMoreInfo') :
198             loadTimeData.getString('showMoreInfo');
199       });
200     },
201
202     /**
203      * Toggles the visible state of the 'More Info' section.
204      * @private
205      */
206     toggleMoreInfo_: function() {
207       var moreInfo = $('more-info-container');
208       this.setMoreInfoVisible_(!moreInfo.classList.contains('visible'));
209     },
210
211     /**
212      * Assigns |method| to the onclick property of |el| if |el| exists.
213      * @param {HTMLElement} el The element on which to set the click handler.
214      * @param {Function} method The click handler.
215      * @private
216      */
217     maybeSetOnClick_: function(el, method) {
218       if (el)
219         el.onclick = method;
220     },
221
222     /**
223      * @param {string} state The state of the update.
224      * private
225      */
226     setUpdateImage_: function(state) {
227       $('update-status-icon').className = 'help-page-icon ' + state;
228     },
229
230     /**
231      * @return {boolean} True, if new channel switcher UI is used,
232      *    false otherwise.
233      * @private
234      */
235     isNewChannelSwitcherUI_: function() {
236       return !loadTimeData.valueExists('disableNewChannelSwitcherUI');
237     },
238
239     /**
240      * @return {boolean} True if target and current channels are not null and
241      *     not equal.
242      * @private
243      */
244     channelsDiffer_: function() {
245       var current = this.currentChannel_;
246       var target = this.targetChannel_;
247       return (current != null && target != null && current != target);
248     },
249
250     /**
251      * @return {boolean} True if target channel is more stable than the current
252      *     one, and false otherwise.
253      * @private
254      */
255     targetChannelIsMoreStable_: function() {
256       var current = this.currentChannel_;
257       var target = this.targetChannel_;
258       if (current == null || target == null)
259         return false;
260       var currentIndex = this.channelList_.indexOf(current);
261       var targetIndex = this.channelList_.indexOf(target);
262       if (currentIndex < 0 || targetIndex < 0)
263         return false;
264       return currentIndex < targetIndex;
265     },
266
267     /**
268      * @param {string} status The status of the update.
269      * @param {string} message Failure message to display.
270      * @private
271      */
272     setUpdateStatus_: function(status, message) {
273       this.status_ = status;
274       this.message_ = message;
275
276       this.updateUI_();
277     },
278
279     /**
280       * Updates UI elements on the page according to current state.
281       * @private
282       */
283     updateUI_: function() {
284       var status = this.status_;
285       var message = this.message_;
286       var channel = this.targetChannel_;
287
288       if (this.channelList_.indexOf(channel) >= 0) {
289         $('current-channel').textContent = loadTimeData.getStringF(
290             'currentChannel', this.channelTable_[channel].label);
291         this.updateChannelChangePageContainerVisibility_();
292       }
293
294       if (status == null)
295         return;
296
297       if (cr.isMac &&
298           $('update-status-message') &&
299           $('update-status-message').hidden) {
300         // Chrome has reached the end of the line on this system. The
301         // update-obsolete-system message is displayed. No other auto-update
302         // status should be displayed.
303         return;
304       }
305
306       if (status == 'checking') {
307         this.setUpdateImage_('working');
308         $('update-status-message').innerHTML =
309             loadTimeData.getString('updateCheckStarted');
310       } else if (status == 'updating') {
311         this.setUpdateImage_('working');
312         if (this.channelsDiffer_()) {
313           $('update-status-message').innerHTML =
314               loadTimeData.getStringF('updatingChannelSwitch',
315                                       this.channelTable_[channel].label);
316         } else {
317           $('update-status-message').innerHTML =
318               loadTimeData.getStringF('updating');
319         }
320       } else if (status == 'nearly_updated') {
321         this.setUpdateImage_('up-to-date');
322         if (this.channelsDiffer_()) {
323           $('update-status-message').innerHTML =
324               loadTimeData.getString('successfulChannelSwitch');
325         } else {
326           $('update-status-message').innerHTML =
327               loadTimeData.getString('updateAlmostDone');
328         }
329       } else if (status == 'updated') {
330         this.setUpdateImage_('up-to-date');
331         $('update-status-message').innerHTML =
332             loadTimeData.getString('upToDate');
333       } else if (status == 'failed') {
334         this.setUpdateImage_('failed');
335         $('update-status-message').innerHTML = message;
336       }
337
338       if (cr.isChromeOS) {
339         $('change-channel').disabled = !this.can_change_channel_ ||
340             status == 'nearly_updated';
341         $('channel-change-disallowed-icon').hidden = this.can_change_channel_;
342       }
343
344       // Following invariant must be established at the end of this function:
345       // { ~$('relaunch_and_powerwash').hidden -> $('relaunch').hidden }
346       var relaunchAndPowerwashHidden = true;
347       if ($('relaunch-and-powerwash')) {
348         // It's allowed to do powerwash only for customer devices,
349         // when user explicitly decides to update to a more stable
350         // channel.
351         relaunchAndPowerwashHidden =
352             !this.targetChannelIsMoreStable_() || status != 'nearly_updated';
353         $('relaunch-and-powerwash').hidden = relaunchAndPowerwashHidden;
354       }
355
356       if (cr.isChromeOS) {
357         // Only enable the update button if it hasn't been used yet or the
358         // status isn't 'updated'.
359         if (!$('request-update').disabled || status != 'updated') {
360           // Disable the button if an update is already in progress.
361           $('request-update').disabled =
362             ['checking', 'updating', 'nearly_updated'].indexOf(status) > -1;
363         }
364       }
365
366       var container = $('update-status-container');
367       if (container) {
368         container.hidden = status == 'disabled';
369         $('relaunch').hidden =
370             (status != 'nearly_updated') || !relaunchAndPowerwashHidden;
371
372         if (cr.isChromeOS) {
373           // Assume the "updated" status is stale if we haven't checked yet.
374           if (status == 'updated' && !$('request-update').disabled)
375             container.hidden = true;
376
377           // Hide the request update button if auto-updating is disabled or
378           // a relaunch button is showing.
379           $('request-update').hidden = status == 'disabled' ||
380             !$('relaunch').hidden || !relaunchAndPowerwashHidden;
381         }
382
383         if (!cr.isMac)
384           $('update-percentage').hidden = status != 'updating';
385       }
386     },
387
388     /**
389      * @param {number} progress The percent completion.
390      * @private
391      */
392     setProgress_: function(progress) {
393       $('update-percentage').innerHTML = progress + '%';
394     },
395
396     /**
397      * @param {string} message The allowed connection types message.
398      * @private
399      */
400     setAllowedConnectionTypesMsg_: function(message) {
401       $('allowed-connection-types-message').innerText = message;
402     },
403
404     /**
405      * @param {boolean} visible Whether to show the message.
406      * @private
407      */
408     showAllowedConnectionTypesMsg_: function(visible) {
409       $('allowed-connection-types-message').hidden = !visible;
410     },
411
412     /**
413      * @param {string} state The promote state to set.
414      * @private
415      */
416     setPromotionState_: function(state) {
417       if (state == 'hidden') {
418         $('promote').hidden = true;
419       } else if (state == 'enabled') {
420         $('promote').disabled = false;
421         $('promote').hidden = false;
422       } else if (state == 'disabled') {
423         $('promote').disabled = true;
424         $('promote').hidden = false;
425       }
426     },
427
428     /**
429      * @param {boolean} obsolete Whether the system is obsolete.
430      * @private
431      */
432     setObsoleteSystem_: function(obsolete) {
433       if (cr.isMac && $('update-obsolete-system-container')) {
434         $('update-obsolete-system-container').hidden = !obsolete;
435       }
436     },
437
438     /**
439      * @param {boolean} endOfTheLine Whether the train has rolled into
440      *     the station.
441      * @private
442      */
443     setObsoleteSystemEndOfTheLine_: function(endOfTheLine) {
444       if (cr.isMac &&
445           $('update-obsolete-system-container') &&
446           !$('update-obsolete-system-container').hidden &&
447           $('update-status-message')) {
448         $('update-status-message').hidden = endOfTheLine;
449         if (endOfTheLine) {
450           this.setUpdateImage_('failed');
451         }
452       }
453     },
454
455     /**
456      * @param {string} version Version of Chrome OS.
457      * @private
458      */
459     setOSVersion_: function(version) {
460       if (!cr.isChromeOS)
461         console.error('OS version unsupported on non-CrOS');
462
463       $('os-version').parentNode.hidden = (version == '');
464       $('os-version').textContent = version;
465     },
466
467     /**
468      * @param {string} firmware Firmware on Chrome OS.
469      * @private
470      */
471     setOSFirmware_: function(firmware) {
472       if (!cr.isChromeOS)
473         console.error('OS firmware unsupported on non-CrOS');
474
475       $('firmware').parentNode.hidden = (firmware == '');
476       $('firmware').textContent = firmware;
477     },
478
479     /**
480      * Updates page UI according to device owhership policy.
481      * @param {boolean} isEnterpriseManaged True if the device is
482      *     enterprise managed.
483      * @private
484      */
485     updateIsEnterpriseManaged_: function(isEnterpriseManaged) {
486       help.ChannelChangePage.updateIsEnterpriseManaged(isEnterpriseManaged);
487       this.updateUI_();
488     },
489
490     /**
491      * Updates name of the current channel, i.e. the name of the
492      * channel the device is currently on.
493      * @param {string} channel The name of the current channel.
494      * @private
495      */
496     updateCurrentChannel_: function(channel) {
497       if (this.channelList_.indexOf(channel) < 0)
498         return;
499       this.currentChannel_ = channel;
500       help.ChannelChangePage.updateCurrentChannel(channel);
501       this.updateUI_();
502     },
503
504     /**
505      * Updates name of the target channel, i.e. the name of the
506      * channel the device is supposed to be.
507      * @param {string} channel The name of the target channel.
508      * @private
509      */
510     updateTargetChannel_: function(channel) {
511       if (this.channelList_.indexOf(channel) < 0)
512         return;
513       this.targetChannel_ = channel;
514       help.ChannelChangePage.updateTargetChannel(channel);
515       this.updateUI_();
516     },
517
518     /**
519      * @param {boolean} enabled True if the release channel can be enabled.
520      * @private
521      */
522     updateEnableReleaseChannel_: function(enabled) {
523       this.updateChannelChangerContainerVisibility_(enabled);
524       this.can_change_channel_ = enabled;
525       this.updateUI_();
526     },
527
528     /**
529      * Sets the device target channel.
530      * @param {string} channel The name of the target channel.
531      * @param {boolean} isPowerwashAllowed True iff powerwash is allowed.
532      * @private
533      */
534     setChannel_: function(channel, isPowerwashAllowed) {
535       chrome.send('setChannel', [channel, isPowerwashAllowed]);
536       $('channel-change-confirmation').hidden = false;
537       $('channel-change-confirmation').textContent = loadTimeData.getStringF(
538           'channel-changed', this.channelTable_[channel].name);
539       this.updateTargetChannel_(channel);
540     },
541
542     /**
543      * Sets the value of the "Build Date" field of the "More Info" section.
544      * @param {string} buildDate The date of the build.
545      * @private
546      */
547     setBuildDate_: function(buildDate) {
548       $('build-date-container').classList.remove('empty');
549       $('build-date').textContent = buildDate;
550     },
551
552     /**
553      * Updates channel-change-page-container visibility according to
554      * internal state.
555      * @private
556      */
557     updateChannelChangePageContainerVisibility_: function() {
558       if (!this.isNewChannelSwitcherUI_()) {
559         $('channel-change-page-container').hidden = true;
560         return;
561       }
562       $('channel-change-page-container').hidden =
563           !help.ChannelChangePage.isPageReady();
564     },
565
566     /**
567      * Updates channel-changer dropdown visibility if |visible| is
568      * true and new channel switcher UI is disallowed.
569      * @param {boolean} visible True if channel-changer should be
570      *     displayed, false otherwise.
571      * @private
572      */
573     updateChannelChangerContainerVisibility_: function(visible) {
574       if (this.isNewChannelSwitcherUI_()) {
575         $('channel-changer').hidden = true;
576         return;
577       }
578       $('channel-changer').hidden = !visible;
579     },
580
581     /**
582      * Sets the product label's alt text.
583      * @param {string} text The text to use for the image.
584      * @private
585      */
586     setProductLabelText_: function(text) {
587       $('product-label').setAttribute('alt', text);
588     },
589   };
590
591   HelpPage.setUpdateStatus = function(status, message) {
592     HelpPage.getInstance().setUpdateStatus_(status, message);
593   };
594
595   HelpPage.setProgress = function(progress) {
596     HelpPage.getInstance().setProgress_(progress);
597   };
598
599   HelpPage.setAndShowAllowedConnectionTypesMsg = function(message) {
600     HelpPage.getInstance().setAllowedConnectionTypesMsg_(message);
601     HelpPage.getInstance().showAllowedConnectionTypesMsg_(true);
602   };
603
604   HelpPage.showAllowedConnectionTypesMsg = function(visible) {
605     HelpPage.getInstance().showAllowedConnectionTypesMsg_(visible);
606   };
607
608   HelpPage.setPromotionState = function(state) {
609     HelpPage.getInstance().setPromotionState_(state);
610   };
611
612   HelpPage.setObsoleteSystem = function(obsolete) {
613     HelpPage.getInstance().setObsoleteSystem_(obsolete);
614   };
615
616   HelpPage.setObsoleteSystemEndOfTheLine = function(endOfTheLine) {
617     HelpPage.getInstance().setObsoleteSystemEndOfTheLine_(endOfTheLine);
618   };
619
620   HelpPage.setOSVersion = function(version) {
621     HelpPage.getInstance().setOSVersion_(version);
622   };
623
624   HelpPage.setOSFirmware = function(firmware) {
625     HelpPage.getInstance().setOSFirmware_(firmware);
626   };
627
628   HelpPage.updateIsEnterpriseManaged = function(isEnterpriseManaged) {
629     if (!cr.isChromeOS)
630       return;
631     HelpPage.getInstance().updateIsEnterpriseManaged_(isEnterpriseManaged);
632   };
633
634   HelpPage.updateCurrentChannel = function(channel) {
635     if (!cr.isChromeOS)
636       return;
637     HelpPage.getInstance().updateCurrentChannel_(channel);
638   };
639
640   HelpPage.updateTargetChannel = function(channel) {
641     if (!cr.isChromeOS)
642       return;
643     HelpPage.getInstance().updateTargetChannel_(channel);
644   };
645
646   HelpPage.updateEnableReleaseChannel = function(enabled) {
647     HelpPage.getInstance().updateEnableReleaseChannel_(enabled);
648   };
649
650   HelpPage.setChannel = function(channel, isPowerwashAllowed) {
651     HelpPage.getInstance().setChannel_(channel, isPowerwashAllowed);
652   };
653
654   HelpPage.setBuildDate = function(buildDate) {
655     HelpPage.getInstance().setBuildDate_(buildDate);
656   };
657
658   HelpPage.setProductLabelText = function(text) {
659     HelpPage.getInstance().setProductLabelText_(text);
660   };
661
662   // Export
663   return {
664     HelpPage: HelpPage
665   };
666 });