blob: 139f966ab91abbd8fefb823060ee6a0fa31a2d5a [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('help', function() {
var Page = cr.ui.pageManager.Page;
var PageManager = cr.ui.pageManager.PageManager;
/**
* Encapsulated handling of the About page. Called 'help' internally to avoid
* confusion with generic AboutUI (about:memory, about:sandbox, etc.).
*/
function HelpPage() {
var id = loadTimeData.valueExists('aboutOverlayTabTitle') ?
'aboutOverlayTabTitle' : 'aboutTitle';
Page.call(this, 'help', loadTimeData.getString(id), 'help-page');
}
cr.addSingletonGetter(HelpPage);
HelpPage.prototype = {
__proto__: Page.prototype,
/**
* List of the channel names. Should be ordered in increasing level of
* stability.
* @private
*/
channelList_: ['dev-channel', 'beta-channel', 'stable-channel'],
/**
* Name of the channel the device is currently on.
* @private
*/
currentChannel_: null,
/**
* Name of the channel the device is supposed to be on.
* @private
*/
targetChannel_: null,
/**
* Last status received from the version updater.
* @private
*/
status_: null,
/**
* Last message received from the version updater.
* @private
*/
message_: null,
/**
* True if user is allowed to change channels, false otherwise.
* @private
*/
can_change_channel_: false,
/** @override */
initializePage: function() {
Page.prototype.initializePage.call(this);
$('product-license').innerHTML = loadTimeData.getString('productLicense');
if (cr.isChromeOS) {
$('product-os-license').innerHTML =
loadTimeData.getString('productOsLicense');
}
var productTOS = $('product-tos');
if (productTOS)
productTOS.innerHTML = loadTimeData.getString('productTOS');
$('get-help').onclick = function() {
chrome.send('openHelpPage');
};
<if expr="_google_chrome">
$('report-issue').onclick = function() {
chrome.send('openFeedbackDialog');
};
</if>
this.maybeSetOnClick_($('more-info-expander'),
this.toggleMoreInfo_.bind(this));
this.maybeSetOnClick_($('promote'), function() {
chrome.send('promoteUpdater');
});
this.maybeSetOnClick_($('relaunch'), function() {
chrome.send('relaunchNow');
});
if (cr.isChromeOS) {
this.maybeSetOnClick_($('relaunch-and-powerwash'), function() {
chrome.send('relaunchAndPowerwash');
});
this.channelTable_ = {
'stable-channel': {
'name': loadTimeData.getString('stable'),
'label': loadTimeData.getString('currentChannelStable'),
},
'beta-channel': {
'name': loadTimeData.getString('beta'),
'label': loadTimeData.getString('currentChannelBeta')
},
'dev-channel': {
'name': loadTimeData.getString('dev'),
'label': loadTimeData.getString('currentChannelDev')
}
};
}
this.maybeSetOnClick_($('about-done'), function() {
// Event listener for the close button when shown as an overlay.
PageManager.closeOverlay();
});
var self = this;
var channelChanger = $('channel-changer');
if (channelChanger) {
channelChanger.onchange = function(event) {
self.setChannel_(event.target.value, false);
};
}
if (cr.isChromeOS) {
// Add event listener for the check for and apply updates button.
this.maybeSetOnClick_($('request-update'), function() {
self.setUpdateStatus_('checking');
$('request-update').disabled = true;
chrome.send('requestUpdate');
});
$('change-channel').onclick = function() {
PageManager.showPageByName('channel-change-page', false);
};
var channelChangeDisallowedError = document.createElement('div');
channelChangeDisallowedError.className = 'channel-change-error-bubble';
var channelChangeDisallowedIcon = document.createElement('div');
channelChangeDisallowedIcon.className =
'help-page-icon channel-change-error-icon';
channelChangeDisallowedError.appendChild(channelChangeDisallowedIcon);
var channelChangeDisallowedText = document.createElement('div');
channelChangeDisallowedText.className = 'channel-change-error-text';
channelChangeDisallowedText.textContent =
loadTimeData.getString('channelChangeDisallowedMessage');
channelChangeDisallowedError.appendChild(channelChangeDisallowedText);
$('channel-change-disallowed-icon').onclick = function() {
PageManager.showBubble(channelChangeDisallowedError,
$('channel-change-disallowed-icon'),
$('help-container'),
cr.ui.ArrowLocation.TOP_END);
};
// Unhide the regulatory label if/when the image loads.
$('regulatory-label').onload = function() {
$('regulatory-label-container').hidden = false;
};
}
var logo = $('product-logo');
logo.onclick = function(e) {
logo.classList.remove('spin');
setTimeout(function() { logo.classList.add('spin'); }, 0);
};
// Attempt to update.
chrome.send('onPageLoaded');
},
/** @override */
didClosePage: function() {
this.setMoreInfoVisible_(false);
},
/**
* Sets the visible state of the 'More Info' section.
* @param {boolean} visible Whether the section should be visible.
* @private
*/
setMoreInfoVisible_: function(visible) {
var moreInfo = $('more-info-container');
if (!moreInfo || visible == moreInfo.classList.contains('visible'))
return;
moreInfo.classList.toggle('visible', visible);
moreInfo.style.height = visible ? moreInfo.scrollHeight + 'px' : '';
moreInfo.addEventListener('webkitTransitionEnd', function(event) {
$('more-info-expander').textContent = visible ?
loadTimeData.getString('hideMoreInfo') :
loadTimeData.getString('showMoreInfo');
});
},
/**
* Toggles the visible state of the 'More Info' section.
* @private
*/
toggleMoreInfo_: function() {
var moreInfo = $('more-info-container');
this.setMoreInfoVisible_(!moreInfo.classList.contains('visible'));
},
/**
* Assigns |method| to the onclick property of |el| if |el| exists.
* @param {HTMLElement} el The element on which to set the click handler.
* @param {Function} method The click handler.
* @private
*/
maybeSetOnClick_: function(el, method) {
if (el)
el.onclick = method;
},
/**
* @param {string} state The state of the update.
* private
*/
setUpdateImage_: function(state) {
$('update-status-icon').className = 'help-page-icon ' + state;
},
/**
* @return {boolean} True, if new channel switcher UI is used,
* false otherwise.
* @private
*/
isNewChannelSwitcherUI_: function() {
return !loadTimeData.valueExists('disableNewChannelSwitcherUI');
},
/**
* @return {boolean} True if target and current channels are not null and
* not equal.
* @private
*/
channelsDiffer_: function() {
var current = this.currentChannel_;
var target = this.targetChannel_;
return (current != null && target != null && current != target);
},
/**
* @return {boolean} True if target channel is more stable than the current
* one, and false otherwise.
* @private
*/
targetChannelIsMoreStable_: function() {
var current = this.currentChannel_;
var target = this.targetChannel_;
if (current == null || target == null)
return false;
var currentIndex = this.channelList_.indexOf(current);
var targetIndex = this.channelList_.indexOf(target);
if (currentIndex < 0 || targetIndex < 0)
return false;
return currentIndex < targetIndex;
},
/**
* @param {string} status The status of the update.
* @param {string} message Failure message to display.
* @private
*/
setUpdateStatus_: function(status, message) {
this.status_ = status;
this.message_ = message;
this.updateUI_();
},
/**
* Updates UI elements on the page according to current state.
* @private
*/
updateUI_: function() {
var status = this.status_;
var message = this.message_;
var channel = this.targetChannel_;
if (this.channelList_.indexOf(channel) >= 0) {
$('current-channel').textContent = loadTimeData.getStringF(
'currentChannel', this.channelTable_[channel].label);
this.updateChannelChangePageContainerVisibility_();
}
if (status == null)
return;
if (cr.isMac &&
$('update-status-message') &&
$('update-status-message').hidden) {
// Chrome has reached the end of the line on this system. The
// update-obsolete-system message is displayed. No other auto-update
// status should be displayed.
return;
}
if (status == 'checking') {
this.setUpdateImage_('working');
$('update-status-message').innerHTML =
loadTimeData.getString('updateCheckStarted');
} else if (status == 'updating') {
this.setUpdateImage_('working');
if (this.channelsDiffer_()) {
$('update-status-message').innerHTML =
loadTimeData.getStringF('updatingChannelSwitch',
this.channelTable_[channel].label);
} else {
$('update-status-message').innerHTML =
loadTimeData.getStringF('updating');
}
} else if (status == 'nearly_updated') {
this.setUpdateImage_('up-to-date');
if (this.channelsDiffer_()) {
$('update-status-message').innerHTML =
loadTimeData.getString('successfulChannelSwitch');
} else {
$('update-status-message').innerHTML =
loadTimeData.getString('updateAlmostDone');
}
} else if (status == 'updated') {
this.setUpdateImage_('up-to-date');
$('update-status-message').innerHTML = message ? message :
loadTimeData.getString('upToDate');
} else if (status == 'failed') {
this.setUpdateImage_('failed');
$('update-status-message').innerHTML = message;
}
if (cr.isChromeOS) {
$('change-channel').disabled = !this.can_change_channel_ ||
status == 'nearly_updated';
$('channel-change-disallowed-icon').hidden = this.can_change_channel_;
}
// Following invariant must be established at the end of this function:
// { ~$('relaunch_and_powerwash').hidden -> $('relaunch').hidden }
var relaunchAndPowerwashHidden = true;
if ($('relaunch-and-powerwash')) {
// It's allowed to do powerwash only for customer devices,
// when user explicitly decides to update to a more stable
// channel.
relaunchAndPowerwashHidden =
!this.targetChannelIsMoreStable_() || status != 'nearly_updated';
$('relaunch-and-powerwash').hidden = relaunchAndPowerwashHidden;
}
if (cr.isChromeOS) {
// Only enable the update button if it hasn't been used yet or the
// status isn't 'updated'.
if (!$('request-update').disabled || status != 'updated') {
// Disable the button if an update is already in progress.
$('request-update').disabled =
['checking', 'updating', 'nearly_updated'].indexOf(status) > -1;
}
}
var container = $('update-status-container');
if (container) {
container.hidden = status == 'disabled';
$('relaunch').hidden =
(status != 'nearly_updated') || !relaunchAndPowerwashHidden;
if (cr.isChromeOS) {
// Assume the "updated" status is stale if we haven't checked yet.
if (status == 'updated' && !$('request-update').disabled)
container.hidden = true;
// Hide the request update button if auto-updating is disabled or
// a relaunch button is showing.
$('request-update').hidden = status == 'disabled' ||
!$('relaunch').hidden || !relaunchAndPowerwashHidden;
}
if (!cr.isMac)
$('update-percentage').hidden = status != 'updating';
}
},
/**
* @param {number} progress The percent completion.
* @private
*/
setProgress_: function(progress) {
$('update-percentage').innerHTML = progress + '%';
},
/**
* @param {string} message The allowed connection types message.
* @private
*/
setAllowedConnectionTypesMsg_: function(message) {
$('allowed-connection-types-message').innerText = message;
},
/**
* @param {boolean} visible Whether to show the message.
* @private
*/
showAllowedConnectionTypesMsg_: function(visible) {
$('allowed-connection-types-message').hidden = !visible;
},
/**
* @param {string} state The promote state to set.
* @private
*/
setPromotionState_: function(state) {
if (state == 'hidden') {
$('promote').hidden = true;
} else if (state == 'enabled') {
$('promote').disabled = false;
$('promote').hidden = false;
} else if (state == 'disabled') {
$('promote').disabled = true;
$('promote').hidden = false;
}
},
/**
* @param {boolean} obsolete Whether the system is obsolete.
* @private
*/
setObsoleteSystem_: function(obsolete) {
if ($('update-obsolete-system-container')) {
$('update-obsolete-system-container').hidden = !obsolete;
}
},
/**
* @param {boolean} endOfTheLine Whether the train has rolled into
* the station.
* @private
*/
setObsoleteSystemEndOfTheLine_: function(endOfTheLine) {
if ($('update-obsolete-system-container') &&
!$('update-obsolete-system-container').hidden &&
$('update-status-message')) {
$('update-status-message').hidden = endOfTheLine;
if (endOfTheLine) {
this.setUpdateImage_('failed');
}
}
},
/**
* @param {string} version Version of Chrome OS.
* @private
*/
setOSVersion_: function(version) {
if (!cr.isChromeOS)
console.error('OS version unsupported on non-CrOS');
$('os-version').parentNode.hidden = (version == '');
$('os-version').textContent = version;
},
/**
* @param {string} firmware Firmware on Chrome OS.
* @private
*/
setOSFirmware_: function(firmware) {
if (!cr.isChromeOS)
console.error('OS firmware unsupported on non-CrOS');
$('firmware').parentNode.hidden = (firmware == '');
$('firmware').textContent = firmware;
},
/**
* Updates page UI according to device owhership policy.
* @param {boolean} isEnterpriseManaged True if the device is
* enterprise managed.
* @private
*/
updateIsEnterpriseManaged_: function(isEnterpriseManaged) {
help.ChannelChangePage.updateIsEnterpriseManaged(isEnterpriseManaged);
this.updateUI_();
},
/**
* Updates name of the current channel, i.e. the name of the
* channel the device is currently on.
* @param {string} channel The name of the current channel.
* @private
*/
updateCurrentChannel_: function(channel) {
if (this.channelList_.indexOf(channel) < 0)
return;
this.currentChannel_ = channel;
help.ChannelChangePage.updateCurrentChannel(channel);
this.updateUI_();
},
/**
* Updates name of the target channel, i.e. the name of the
* channel the device is supposed to be.
* @param {string} channel The name of the target channel.
* @private
*/
updateTargetChannel_: function(channel) {
if (this.channelList_.indexOf(channel) < 0)
return;
this.targetChannel_ = channel;
help.ChannelChangePage.updateTargetChannel(channel);
this.updateUI_();
},
/**
* @param {boolean} enabled True if the release channel can be enabled.
* @private
*/
updateEnableReleaseChannel_: function(enabled) {
this.updateChannelChangerContainerVisibility_(enabled);
this.can_change_channel_ = enabled;
this.updateUI_();
},
/**
* Sets the device target channel.
* @param {string} channel The name of the target channel.
* @param {boolean} isPowerwashAllowed True iff powerwash is allowed.
* @private
*/
setChannel_: function(channel, isPowerwashAllowed) {
chrome.send('setChannel', [channel, isPowerwashAllowed]);
$('channel-change-confirmation').hidden = false;
$('channel-change-confirmation').textContent = loadTimeData.getStringF(
'channel-changed', this.channelTable_[channel].name);
this.updateTargetChannel_(channel);
},
/**
* Sets the value of the "Build Date" field of the "More Info" section.
* @param {string} buildDate The date of the build.
* @private
*/
setBuildDate_: function(buildDate) {
$('build-date-container').classList.remove('empty');
$('build-date').textContent = buildDate;
},
/**
* Updates channel-change-page-container visibility according to
* internal state.
* @private
*/
updateChannelChangePageContainerVisibility_: function() {
if (!this.isNewChannelSwitcherUI_()) {
$('channel-change-page-container').hidden = true;
return;
}
$('channel-change-page-container').hidden =
!help.ChannelChangePage.isPageReady();
},
/**
* Updates channel-changer dropdown visibility if |visible| is
* true and new channel switcher UI is disallowed.
* @param {boolean} visible True if channel-changer should be
* displayed, false otherwise.
* @private
*/
updateChannelChangerContainerVisibility_: function(visible) {
if (this.isNewChannelSwitcherUI_()) {
$('channel-changer').hidden = true;
return;
}
$('channel-changer').hidden = !visible;
},
/**
* Sets the regulatory label's source.
* @param {string} path The path to use for the image.
* @private
*/
setRegulatoryLabelPath_: function(path) {
$('regulatory-label').src = path;
},
/**
* Sets the regulatory label's alt text.
* @param {string} text The text to use for the image.
* @private
*/
setRegulatoryLabelText_: function(text) {
$('regulatory-label').alt = text;
},
};
HelpPage.setUpdateStatus = function(status, message) {
HelpPage.getInstance().setUpdateStatus_(status, message);
};
HelpPage.setProgress = function(progress) {
HelpPage.getInstance().setProgress_(progress);
};
HelpPage.setAndShowAllowedConnectionTypesMsg = function(message) {
HelpPage.getInstance().setAllowedConnectionTypesMsg_(message);
HelpPage.getInstance().showAllowedConnectionTypesMsg_(true);
};
HelpPage.showAllowedConnectionTypesMsg = function(visible) {
HelpPage.getInstance().showAllowedConnectionTypesMsg_(visible);
};
HelpPage.setPromotionState = function(state) {
HelpPage.getInstance().setPromotionState_(state);
};
HelpPage.setObsoleteSystem = function(obsolete) {
HelpPage.getInstance().setObsoleteSystem_(obsolete);
};
HelpPage.setObsoleteSystemEndOfTheLine = function(endOfTheLine) {
HelpPage.getInstance().setObsoleteSystemEndOfTheLine_(endOfTheLine);
};
HelpPage.setOSVersion = function(version) {
HelpPage.getInstance().setOSVersion_(version);
};
HelpPage.setOSFirmware = function(firmware) {
HelpPage.getInstance().setOSFirmware_(firmware);
};
HelpPage.updateIsEnterpriseManaged = function(isEnterpriseManaged) {
if (!cr.isChromeOS)
return;
HelpPage.getInstance().updateIsEnterpriseManaged_(isEnterpriseManaged);
};
HelpPage.updateCurrentChannel = function(channel) {
if (!cr.isChromeOS)
return;
HelpPage.getInstance().updateCurrentChannel_(channel);
};
HelpPage.updateTargetChannel = function(channel) {
if (!cr.isChromeOS)
return;
HelpPage.getInstance().updateTargetChannel_(channel);
};
HelpPage.updateEnableReleaseChannel = function(enabled) {
HelpPage.getInstance().updateEnableReleaseChannel_(enabled);
};
HelpPage.setChannel = function(channel, isPowerwashAllowed) {
HelpPage.getInstance().setChannel_(channel, isPowerwashAllowed);
};
HelpPage.setBuildDate = function(buildDate) {
HelpPage.getInstance().setBuildDate_(buildDate);
};
HelpPage.setRegulatoryLabelPath = function(path) {
assert(cr.isChromeOS);
HelpPage.getInstance().setRegulatoryLabelPath_(path);
};
HelpPage.setRegulatoryLabelText = function(text) {
assert(cr.isChromeOS);
HelpPage.getInstance().setRegulatoryLabelText_(text);
};
// Export
return {
HelpPage: HelpPage
};
});