1 // Copyright 2013 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 /** 7 * Encapsulated handling of the channel change overlay. 8 */ 9 function ChannelChangePage() {} 10 11 cr.addSingletonGetter(ChannelChangePage); 12 13 ChannelChangePage.prototype = { 14 __proto__: help.HelpBasePage.prototype, 15 16 /** 17 * Name of the channel the device is currently on. 18 * @private 19 */ 20 currentChannel_: null, 21 22 /** 23 * Name of the channel the device is supposed to be on. 24 * @private 25 */ 26 targetChannel_: null, 27 28 /** 29 * True iff the device is enterprise-managed. 30 * @private 31 */ 32 isEnterpriseManaged_: undefined, 33 34 /** 35 * List of the channels names, from the least stable to the most stable. 36 * @private 37 */ 38 channelList_: ['dev-channel', 'beta-channel', 'stable-channel'], 39 40 /** 41 * List of the possible ui states. 42 * @private 43 */ 44 uiClassTable_: ['selected-channel-requires-powerwash', 45 'selected-channel-requires-delayed-update', 46 'selected-channel-good', 47 'selected-channel-unstable'], 48 49 /** 50 * Perform initial setup. 51 */ 52 initialize: function() { 53 help.HelpBasePage.prototype.initialize.call(this, 'channel-change-page'); 54 55 var self = this; 56 57 $('channel-change-page-cancel-button').onclick = function() { 58 help.HelpPage.cancelOverlay(); 59 }; 60 61 var options = this.getAllChannelOptions_(); 62 for (var i = 0; i < options.length; i++) { 63 var option = options[i]; 64 option.onclick = function() { 65 self.updateUI_(this.value); 66 }; 67 } 68 69 $('channel-change-page-powerwash-button').onclick = function() { 70 self.setChannel_(self.getSelectedOption_(), true); 71 help.HelpPage.cancelOverlay(); 72 }; 73 74 $('channel-change-page-change-button').onclick = function() { 75 self.setChannel_(self.getSelectedOption_(), false); 76 help.HelpPage.cancelOverlay(); 77 }; 78 }, 79 80 onBeforeShow: function() { 81 help.HelpBasePage.prototype.onBeforeShow.call(this); 82 if (this.targetChannel_ != null) 83 this.selectOption_(this.targetChannel_); 84 else if (this.currentChannel_ != null) 85 this.selectOption_(this.currentChannel_); 86 var options = this.getAllChannelOptions_(); 87 for (var i = 0; i < options.length; i++) { 88 var option = options[i]; 89 if (option.checked) 90 option.focus(); 91 } 92 }, 93 94 /** 95 * Returns the list of all radio buttons responsible for channel selection. 96 * @return {Array.<HTMLInputElement>} Array of radio buttons 97 * @private 98 */ 99 getAllChannelOptions_: function() { 100 return $('channel-change-page').querySelectorAll('input[type="radio"]'); 101 }, 102 103 /** 104 * Returns value of the selected option. 105 * @return {string} Selected channel name or null, if neither 106 * option is selected. 107 * @private 108 */ 109 getSelectedOption_: function() { 110 var options = this.getAllChannelOptions_(); 111 for (var i = 0; i < options.length; i++) { 112 var option = options[i]; 113 if (option.checked) 114 return option.value; 115 } 116 return null; 117 }, 118 119 /** 120 * Selects option for a given channel. 121 * @param {string} channel Name of channel option that should be selected. 122 * @private 123 */ 124 selectOption_: function(channel) { 125 var options = this.getAllChannelOptions_(); 126 for (var i = 0; i < options.length; i++) { 127 var option = options[i]; 128 if (option.value == channel) { 129 option.checked = true; 130 } 131 } 132 this.updateUI_(channel); 133 }, 134 135 /** 136 * Updates UI according to selected channel. 137 * @param {string} selectedChannel Selected channel 138 * @private 139 */ 140 updateUI_: function(selectedChannel) { 141 var currentStability = this.channelList_.indexOf(this.currentChannel_); 142 var newStability = this.channelList_.indexOf(selectedChannel); 143 144 var newOverlayClass = null; 145 146 if (selectedChannel == this.currentChannel_) { 147 if (this.currentChannel_ != this.targetChannel_) { 148 // Allow user to switch back to the current channel. 149 newOverlayClass = 'selected-channel-good'; 150 } 151 } else if (selectedChannel != this.targetChannel_) { 152 // Selected channel isn't equal to the current and target channel. 153 if (newStability > currentStability) { 154 // More stable channel is selected. For customer devices 155 // notify user about powerwash. 156 if (this.isEnterpriseManaged_) 157 newOverlayClass = 'selected-channel-requires-delayed-update'; 158 else 159 newOverlayClass = 'selected-channel-requires-powerwash'; 160 } else if (selectedChannel == 'dev-channel') { 161 // Warn user about unstable channel. 162 newOverlayClass = 'selected-channel-unstable'; 163 } else { 164 // Switching to the less stable channel. 165 newOverlayClass = 'selected-channel-good'; 166 } 167 } 168 169 // Switch to the new UI state. 170 for (var i = 0; i < this.uiClassTable_.length; i++) 171 $('channel-change-page').classList.remove(this.uiClassTable_[i]); 172 173 if (newOverlayClass) 174 $('channel-change-page').classList.add(newOverlayClass); 175 }, 176 177 /** 178 * Sets the device target channel. 179 * @param {string} channel The name of the target channel 180 * @param {boolean} isPowerwashAllowed True iff powerwash is allowed 181 * @private 182 */ 183 setChannel_: function(channel, isPowerwashAllowed) { 184 this.targetChannel_ = channel; 185 this.updateUI_(channel); 186 help.HelpPage.setChannel(channel, isPowerwashAllowed); 187 }, 188 189 /** 190 * Updates page UI according to device owhership policy. 191 * @param {boolean} isEnterpriseManaged True if the device is 192 * enterprise managed 193 * @private 194 */ 195 updateIsEnterpriseManaged_: function(isEnterpriseManaged) { 196 this.isEnterpriseManaged_ = isEnterpriseManaged; 197 help.HelpPage.updateChannelChangePageContainerVisibility(); 198 }, 199 200 /** 201 * Updates name of the current channel, i.e. the name of the 202 * channel the device is currently on. 203 * @param {string} channel The name of the current channel 204 * @private 205 */ 206 updateCurrentChannel_: function(channel) { 207 if (this.channelList_.indexOf(channel) < 0) 208 return; 209 this.currentChannel_ = channel; 210 this.selectOption_(channel); 211 help.HelpPage.updateChannelChangePageContainerVisibility(); 212 }, 213 214 /** 215 * Updates name of the target channel, i.e. the name of the 216 * channel the device is supposed to be in case of a pending 217 * channel change. 218 * @param {string} channel The name of the target channel 219 * @private 220 */ 221 updateTargetChannel_: function(channel) { 222 if (this.channelList_.indexOf(channel) < 0) 223 return; 224 this.targetChannel_ = channel; 225 help.HelpPage.updateChannelChangePageContainerVisibility(); 226 }, 227 228 /** 229 * @return {boolean} True if the page is ready and can be 230 * displayed, false otherwise 231 * @private 232 */ 233 isPageReady_: function() { 234 if (typeof this.isEnterpriseManaged_ == 'undefined') 235 return false; 236 if (!this.currentChannel_ || !this.targetChannel_) 237 return false; 238 return true; 239 }, 240 }; 241 242 ChannelChangePage.updateIsEnterpriseManaged = function(isEnterpriseManaged) { 243 ChannelChangePage.getInstance().updateIsEnterpriseManaged_( 244 isEnterpriseManaged); 245 }; 246 247 ChannelChangePage.updateCurrentChannel = function(channel) { 248 ChannelChangePage.getInstance().updateCurrentChannel_(channel); 249 }; 250 251 ChannelChangePage.updateTargetChannel = function(channel) { 252 ChannelChangePage.getInstance().updateTargetChannel_(channel); 253 }; 254 255 ChannelChangePage.isPageReady = function() { 256 return ChannelChangePage.getInstance().isPageReady_(); 257 }; 258 259 // Export 260 return { 261 ChannelChangePage: ChannelChangePage 262 }; 263 }); 264