diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-11 03:29:26 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-11 03:29:26 +0000 |
commit | f3a5fad86e9fccdd21af528c43a78f1b9c20e1e4 (patch) | |
tree | a3cc652d8bd50ca97feefd4c429139c17e431868 | |
parent | 634f22bcc80d020d87345341cc2c5b60b451b868 (diff) | |
download | chromium_src-f3a5fad86e9fccdd21af528c43a78f1b9c20e1e4.zip chromium_src-f3a5fad86e9fccdd21af528c43a78f1b9c20e1e4.tar.gz chromium_src-f3a5fad86e9fccdd21af528c43a78f1b9c20e1e4.tar.bz2 |
git add files for about page move
BUG=none
TEST=tree compiles
Review URL: http://codereview.chromium.org/9166033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117161 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/resources/about_page/about_page.css | 34 | ||||
-rw-r--r-- | chrome/browser/resources/about_page/about_page.html | 145 | ||||
-rw-r--r-- | chrome/browser/resources/about_page/about_page.js | 227 | ||||
-rw-r--r-- | chrome/browser/ui/webui/about_page/about_page_handler.cc | 471 | ||||
-rw-r--r-- | chrome/browser/ui/webui/about_page/about_page_handler.h | 70 | ||||
-rw-r--r-- | chrome/browser/ui/webui/about_page/about_page_ui.cc | 43 | ||||
-rw-r--r-- | chrome/browser/ui/webui/about_page/about_page_ui.h | 21 |
7 files changed, 1011 insertions, 0 deletions
diff --git a/chrome/browser/resources/about_page/about_page.css b/chrome/browser/resources/about_page/about_page.css new file mode 100644 index 0000000..29b6a1e --- /dev/null +++ b/chrome/browser/resources/about_page/about_page.css @@ -0,0 +1,34 @@ +#aboutPage { + -webkit-user-select: text; +} + +.loading { + font-style: italic; +} + +#channelSelect { + margin-bottom: 5px; +} + +#channelWarning { + color: red; + font-weight: bold; +} + +.update-icon { + width: 17px; + height: 17px; + display: inline-block; + vertical-align: text-top; + background-repeat: no-repeat; +} + +.update-icon.fail { + background-image: url('../../../app/theme/update_fail.png'); +} +.update-icon.available { + background-image: url('../../../app/theme/update_available.png'); +} +.update-icon.up-to-date { + background-image: url('../../../app/theme/update_uptodate.png'); +} diff --git a/chrome/browser/resources/about_page/about_page.html b/chrome/browser/resources/about_page/about_page.html new file mode 100644 index 0000000..665efa2 --- /dev/null +++ b/chrome/browser/resources/about_page/about_page.html @@ -0,0 +1,145 @@ +<!DOCTYPE html> +<html i18n-values="dir:textdirection;"> +<head> +<meta charset="utf-8"> +<title i18n-content="pageTitle"></title> + +<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css"> +<link rel="stylesheet" href="chrome://resources/css/chrome_shared2.css"> +<link rel="stylesheet" href="chrome://resources/css/open_sans.css"> +<link rel="stylesheet" href="about_page.css"> + +<script src="chrome://resources/js/cr.js"></script> +<script src="chrome://resources/js/util.js"></script> + +<script src="chrome://about-page-frame/about_page.js"></script> +</head> + +<body> + +<div id="aboutPage" class="page"> + <h1 i18n-content="product"></h1> + <div id="aboutPageLessInfo"> + <section> + <div> + <!-- White space is significant between spans. --> + <div> + <span i18n-content="browser"></span> + <span i18n-content="browser_version"></span> + </div> + <div> +<if expr="not pp_ifdef('chromeos')"> + <span i18n-content="os"></span> <span id="osVersion0"> +</if> +<if expr="pp_ifdef('chromeos')"> + <span i18n-content="platform"></span> <span id="osVersion0"> +</if> + <span class="loading" i18n-content="loading"></span></span></div> + <div><span i18n-content="firmware"></span> <span id="osFirmware0"> + <span class="loading" i18n-content="loading"></span></span></div> + <div> + <button id="moreInfoButton" class="link-button" + i18n-content="more_info"></button> + </div> + </div> + </section> + </div> + <div id="aboutPageMoreInfo" hidden> + <section> + <h3 i18n-content="channel"></h3> + <div> + <select id="channelSelect"> + <option value="stable-channel" i18n-content="stable"></option> + <option value="beta-channel" i18n-content="beta"></option> + <option value="dev-channel" i18n-content="dev"></option> + </select> + <div id="channelWarningBlock" hidden> + <div id="channelWarning" i18n-content="channel_warning_header"></div> + <div i18n-content="channel_warning_text"></div> + </div> + </div> + </section> + <section> + <h3 i18n-content="browser"></h3> + <div i18n-content="browser_version"></div> + </section> + <section> +<if expr="not pp_ifdef('chromeos')"> + <h3 i18n-content="os"></h3> +</if> +<if expr="pp_ifdef('chromeos')"> + <h3 i18n-content="platform"></h3> +</if> + <div id="osVersion1"> + <span class="loading" i18n-content="loading"></span> + </div> + </section> + <section> + <h3 i18n-content="firmware"></h3> + <div id="osFirmware1"> + <span class="loading" i18n-content="loading"></span> + </section> + <section> + <h3>WebKit</h3> + <div i18n-content="webkit_version"></div> + </section> + <section> + <h3 i18n-content="js_engine"></h3> + <div i18n-content="js_engine_version"></div> + </section> + <section> + <h3 i18n-content="user_agent"></h3> + <div i18n-content="user_agent_info"></div> + </section> + <section> + <h3 i18n-content="command_line"></h3> + <div i18n-content="command_line_info"></div> + </section> + </div> + <section> + <div> + <span i18n-content="copyright"></span> + <div> + <!-- Odd formatting to avoid unwanted spaces between elements. --> + <span i18n-content="license_content_0"> + </span><a target="_blank" + i18n-values="href:license_link_0" + i18n-content="license_link_content_0"> + </a><span i18n-content="license_content_1"> + </span><a target="_blank" + i18n-values="href:license_link_1" + i18n-content="license_link_content_1"> + </a><span i18n-content="license_content_2"> + </span> + </div> + <div> + <span i18n-content="cros_license_content_0"> + </span><a target="_blank" + i18n-values="href:cros_license_link_0" + i18n-content="cros_license_link_content_0"> + </a><span i18n-content="cros_license_content_1"> + </span> + </div> + </div> + </section> + <section> + <div> + <div> + <div id="updateIcon" class="update-icon up-to-date"></div> + <span id="updateStatus" i18n-content="update_status"></span> + </div> + <div> + <!-- TODO seanparent: fill in last checked. --> + <!-- <span i18n-content="last_check"></span> --> + <button id="checkNow" i18n-content="check_now" disabled></button> + </div> + </div> + </section> +</div> + +</body> + +<script src="chrome://about-page-frame/strings.js"></script> +<script src="chrome://resources/js/i18n_template.js"></script> +<script src="chrome://resources/js/i18n_process.js"></script> +</html> diff --git a/chrome/browser/resources/about_page/about_page.js b/chrome/browser/resources/about_page/about_page.js new file mode 100644 index 0000000..b2e8a98 --- /dev/null +++ b/chrome/browser/resources/about_page/about_page.js @@ -0,0 +1,227 @@ +// Copyright (c) 2012 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('options', function() { + const OptionsPage = options.OptionsPage; + + /** + * The number of milliseconds used for showing a message. + * @type {number} + */ + const MESSAGE_DELAY_MS = 1000; // 1 sec. + + /** + * Encapsulated handling of about page. + */ + function AboutPage() { + OptionsPage.call(this, 'about', templateData.aboutPageTabTitle, + 'aboutPage'); + } + + cr.addSingletonGetter(AboutPage); + + AboutPage.prototype = { + // Inherit AboutPage from OptionsPage. + __proto__: OptionsPage.prototype, + + /** + * The queue is used for updating the status message with delay, like: + * [["Check for update...", 1000], ["Chrome OS is up to date", 0]] + * @type {!Array.<!Array>} + */ + statusMessageQueue_: [], + + /** + * True if the status message queue flush started. + * @type {boolean} + */ + statusMessageQueueFlushStarted_: false, + + /** + * The selected release channel. + * @type {string} + */ + selectedChannel_: '', + + // Initialize AboutPage. + initializePage: function() { + // Call base class implementation to start preference initialization. + OptionsPage.prototype.initializePage.call(this); + + $('checkNow').onclick = function(event) { + chrome.send('CheckNow'); + }; + + $('moreInfoButton').onclick = function(event) { + $('aboutPageLessInfo').hidden = true; + $('aboutPageMoreInfo').hidden = false; + }; + + var self = this; + $('channelSelect').onchange = function(event) { + self.channelSelectOnChanged_(event.target.value); + } + + // Notify the handler that the page is ready. + chrome.send('PageReady'); + }, + + // Update the Default Browsers section based on the current state. + updateOSVersion_: function(versionString) { + $('osVersion0').textContent = versionString; + $('osVersion1').textContent = versionString; + }, + + updateOSFirmware_: function(firmwareString) { + $('osFirmware0').textContent = firmwareString; + $('osFirmware1').textContent = firmwareString; + }, + + /** + * Updates the status message like "Checking for update...". + * @param {string} message The message to be shown. + * @param {boolean} insertDelay show the message for a while. + * @private + */ + updateStatus_: function(message, insertDelay) { + // Add the message to the queue with delay if needed. + // The delay is inserted so users can read the message. + var delayMs = insertDelay ? MESSAGE_DELAY_MS : 0; + this.statusMessageQueue_.push([message, delayMs]); + // Start the periodic flusher if not started. + if (this.statusMessageQueueFlushStarted_ == false) { + this.flushStatusMessageQueuePeriodically_(); + } + }, + + /** + * Flushes the status message queue periodically using a timer. + * @private + */ + flushStatusMessageQueuePeriodically_: function() { + // Stop the periodic flusher if the queue becomes empty. + if (this.statusMessageQueue_.length == 0) { + this.statusMessageQueueFlushStarted_ = false; + return; + } + this.statusMessageQueueFlushStarted_ = true; + + // Update the status message. + var pair = this.statusMessageQueue_.shift(); + var message = pair[0]; + var delayMs = pair[1]; + $('updateStatus').textContent = message; + + // Schedule the next flush with delay as needed. + var self = this; + window.setTimeout( + function() { self.flushStatusMessageQueuePeriodically_() }, + delayMs); + }, + + updateEnable_: function(enable) { + $('checkNow').disabled = !enable; + }, + + enableReleaseChannel_: function(enable) { + $('channelSelect').disabled = !enable; + }, + + setReleaseChannel_: function(channel) { + // Write the value into the pref which will end up in the policy. + // Eventually, the update engine will use the policy value as the + // source truth for the update channel (see http://crosbug/17015). + Preferences.setStringPref("cros.system.releaseChannel", channel); + this.selectedChannel_ = channel; + chrome.send('SetReleaseTrack', [channel]); + }, + + // This function is called when the user changes the release channel from + // the 'channelSelect' <select> element. It either calls back into Chrome to + // switch the channel or displays a confirmation box if switching to dev. + channelSelectOnChanged_: function(value) { + if (value == 'dev-channel') { + // Open confirm dialog. + var self = this; + AlertOverlay.show( + localStrings.getString('channel_warning_header'), + localStrings.getString('channel_warning_text'), + localStrings.getString('ok'), + localStrings.getString('cancel'), + function() { + // Ok, so set release track and update selected channel. + $('channelWarningBlock').hidden = false; + self.setReleaseChannel_(value); }, + function() { + // Cancel, so switch back to previous selected channel. + self.updateSelectedOption_(self.selectedChannel_); } + ); + } else { + $('channelWarningBlock').hidden = true; + this.setReleaseChannel_(value); + } + }, + + // Updates the selected option in 'channelSelect' <select> element. + updateSelectedOption_: function(value) { + var options = $('channelSelect').querySelectorAll('option'); + for (var i = 0; i < options.length; i++) { + var option = options[i]; + if (option.value == value) { + option.selected = true; + this.selectedChannel_ = value; + } + } + if (value == 'dev-channel') + $('channelWarningBlock').hidden = false; + }, + + // Changes the "check now" button to "restart now" button. + changeToRestartButton_: function() { + $('checkNow').textContent = localStrings.getString('restart_now'); + $('checkNow').disabled = false; + $('checkNow').onclick = function(event) { + chrome.send('RestartNow'); + }; + }, + }; + + AboutPage.updateOSVersionCallback = function(versionString) { + AboutPage.getInstance().updateOSVersion_(versionString); + }; + + AboutPage.updateOSFirmwareCallback = function(firmwareString) { + AboutPage.getInstance().updateOSFirmware_(firmwareString); + }; + + AboutPage.updateStatusCallback = function(message, insertDelay) { + AboutPage.getInstance().updateStatus_(message, insertDelay); + }; + + AboutPage.updateEnableCallback = function(enable) { + AboutPage.getInstance().updateEnable_(enable); + }; + + AboutPage.updateEnableReleaseChannelCallback = function(enable) { + AboutPage.getInstance().enableReleaseChannel_(enable); + }; + + AboutPage.updateSelectedOptionCallback = function(value) { + AboutPage.getInstance().updateSelectedOption_(value); + }; + + AboutPage.setUpdateImage = function(state) { + $('updateIcon').className= 'update-icon ' + state; + }; + + AboutPage.changeToRestartButton = function() { + AboutPage.getInstance().changeToRestartButton_(); + }; + + // Export + return { + AboutPage: AboutPage + }; + +}); diff --git a/chrome/browser/ui/webui/about_page/about_page_handler.cc b/chrome/browser/ui/webui/about_page/about_page_handler.cc new file mode 100644 index 0000000..2eaca13 --- /dev/null +++ b/chrome/browser/ui/webui/about_page/about_page_handler.cc @@ -0,0 +1,471 @@ +// Copyright (c) 2012 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. + +#include "chrome/browser/ui/webui/about_page/about_page_handler.h" + +#include <vector> + +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/command_line.h" +#include "base/i18n/time_formatting.h" +#include "base/string16.h" +#include "base/string_number_conversions.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/cros_settings.h" +#include "chrome/browser/chromeos/dbus/dbus_thread_manager.h" +#include "chrome/browser/chromeos/dbus/power_manager_client.h" +#include "chrome/browser/chromeos/dbus/update_engine_client.h" +#include "chrome/browser/chromeos/login/user_manager.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/google/google_util.h" +#include "chrome/browser/policy/browser_policy_connector.h" +#include "chrome/common/chrome_version_info.h" +#include "chrome/common/url_constants.h" +#include "content/browser/webui/web_ui.h" +#include "content/public/common/content_client.h" +#include "googleurl/src/gurl.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" +#include "grit/theme_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "v8/include/v8.h" +#include "webkit/glue/user_agent.h" +#include "webkit/glue/webkit_glue.h" +#include "webkit/glue/user_agent.h" + +namespace { + +// These are used as placeholder text around the links in the text in the +// license. +const char kBeginLink[] = "BEGIN_LINK"; +const char kEndLink[] = "END_LINK"; +const char kBeginLinkChr[] = "BEGIN_LINK_CHR"; +const char kBeginLinkOss[] = "BEGIN_LINK_OSS"; +const char kEndLinkChr[] = "END_LINK_CHR"; +const char kEndLinkOss[] = "END_LINK_OSS"; +const char kBeginLinkCrosOss[] = "BEGIN_LINK_CROS_OSS"; +const char kEndLinkCrosOss[] = "END_LINK_CROS_OSS"; + +const char kDomainChangable[] = "domain"; + +// Returns a substring [start, end) from |text|. +std::string StringSubRange(const std::string& text, size_t start, + size_t end) { + DCHECK(end > start); + return text.substr(start, end - start); +} + +bool CanChangeReleaseChannel() { + // On non managed machines we have local owner who is the only one to change + // anything. + if (chromeos::UserManager::Get()->current_user_is_owner()) + return true; + // On a managed machine we delegate this setting to the users of the same + // domain only if the policy value is "domain". + if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) { + std::string value; + chromeos::CrosSettings::Get()->GetString(chromeos::kReleaseChannel, &value); + if (value != kDomainChangable) + return false; + // Get the currently logged in user and strip the domain part only. + std::string domain = ""; + std::string user = chromeos::UserManager::Get()->logged_in_user().email(); + size_t at_pos = user.find('@'); + if (at_pos != std::string::npos && at_pos + 1 < user.length()) + domain = user.substr(user.find('@') + 1); + return domain == g_browser_process->browser_policy_connector()-> + GetEnterpriseDomain(); + } + return false; +} + +} // namespace + +using chromeos::DBusThreadManager; +using chromeos::UpdateEngineClient; +using chromeos::UserManager; +using chromeos::VersionLoader; +using chromeos::WizardController; + +class AboutPageHandler::UpdateObserver + : public UpdateEngineClient::Observer { + public: + explicit UpdateObserver(AboutPageHandler* handler) : page_handler_(handler) {} + virtual ~UpdateObserver() {} + + AboutPageHandler* page_handler() const { return page_handler_; } + + private: + virtual void UpdateStatusChanged( + const UpdateEngineClient::Status& status) OVERRIDE { + page_handler_->UpdateStatus(status); + } + + AboutPageHandler* page_handler_; + + DISALLOW_COPY_AND_ASSIGN(UpdateObserver); +}; + +AboutPageHandler::AboutPageHandler() + : progress_(-1), + sticky_(false), + started_(false) { +} + +AboutPageHandler::~AboutPageHandler() { + if (update_observer_.get()) { + DBusThreadManager::Get()->GetUpdateEngineClient()-> + RemoveObserver(update_observer_.get()); + } +} + +void AboutPageHandler::GetLocalizedValues(DictionaryValue* localized_strings) { + DCHECK(localized_strings); + DCHECK(localized_strings->empty()); + + struct L10nResources { + const char* name; + int ids; + }; + + static L10nResources resources[] = { + { "pageTitle", IDS_ABOUT_TAB_TITLE }, + { "firmware", IDS_ABOUT_PAGE_FIRMWARE }, + { "product", IDS_PRODUCT_OS_NAME }, + { "os", IDS_PRODUCT_OS_NAME }, + { "platform", IDS_PLATFORM_LABEL }, + { "loading", IDS_ABOUT_PAGE_LOADING }, + { "check_now", IDS_ABOUT_PAGE_CHECK_NOW }, + { "update_status", IDS_UPGRADE_CHECK_STARTED }, + { "restart_now", IDS_RELAUNCH_AND_UPDATE }, + { "browser", IDS_PRODUCT_NAME }, + { "more_info", IDS_ABOUT_PAGE_MORE_INFO }, + { "copyright", IDS_ABOUT_VERSION_COPYRIGHT }, + { "channel", IDS_ABOUT_PAGE_CHANNEL }, + { "stable", IDS_ABOUT_PAGE_CHANNEL_STABLE }, + { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA }, + { "dev", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT }, + { "canary", IDS_ABOUT_PAGE_CHANNEL_CANARY }, + { "channel_warning_header", IDS_ABOUT_PAGE_CHANNEL_WARNING_HEADER }, + { "channel_warning_text", IDS_ABOUT_PAGE_CHANNEL_WARNING_TEXT }, + { "user_agent", IDS_ABOUT_VERSION_USER_AGENT }, + { "command_line", IDS_ABOUT_VERSION_COMMAND_LINE }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resources); ++i) { + localized_strings->SetString(resources[i].name, + l10n_util::GetStringUTF16(resources[i].ids)); + } + + // browser version + + chrome::VersionInfo version_info; + DCHECK(version_info.is_valid()); + + std::string browser_version = version_info.Version(); + std::string version_modifier = + chrome::VersionInfo::GetVersionStringModifier(); + if (!version_modifier.empty()) + browser_version += " " + version_modifier; + +#if !defined(GOOGLE_CHROME_BUILD) + browser_version += " ("; + browser_version += version_info.LastChange(); + browser_version += ")"; +#endif + + localized_strings->SetString("browser_version", browser_version); + + // license + + std::string text = l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_LICENSE); + + bool chromium_url_appears_first = + text.find(kBeginLinkChr) < text.find(kBeginLinkOss); + + size_t link1 = text.find(kBeginLink); + DCHECK(link1 != std::string::npos); + size_t link1_end = text.find(kEndLink, link1); + DCHECK(link1_end != std::string::npos); + size_t link2 = text.find(kBeginLink, link1_end); + DCHECK(link2 != std::string::npos); + size_t link2_end = text.find(kEndLink, link2); + DCHECK(link2_end != std::string::npos); + + localized_strings->SetString("license_content_0", text.substr(0, link1)); + localized_strings->SetString("license_content_1", + StringSubRange(text, link1_end + strlen(kEndLinkOss), link2)); + localized_strings->SetString("license_content_2", + text.substr(link2_end + strlen(kEndLinkOss))); + + // The Chromium link within the main text of the dialog. + localized_strings->SetString(chromium_url_appears_first ? + "license_link_content_0" : "license_link_content_1", + StringSubRange(text, + text.find(kBeginLinkChr) + strlen(kBeginLinkChr), + text.find(kEndLinkChr))); + GURL url = google_util::AppendGoogleLocaleParam( + GURL(chrome::kChromiumProjectURL)); + localized_strings->SetString(chromium_url_appears_first ? + "license_link_0" : "license_link_1", url.spec()); + + // The Open Source link within the main text of the dialog. + localized_strings->SetString(chromium_url_appears_first ? + "license_link_content_1" : "license_link_content_0", + StringSubRange(text, + text.find(kBeginLinkOss) + strlen(kBeginLinkOss), + text.find(kEndLinkOss))); + localized_strings->SetString(chromium_url_appears_first ? + "license_link_1" : "license_link_0", chrome::kChromeUICreditsURL); + + std::string cros_text = + l10n_util::GetStringUTF8(IDS_ABOUT_CROS_VERSION_LICENSE); + + size_t cros_link = cros_text.find(kBeginLinkCrosOss); + DCHECK(cros_link != std::string::npos); + size_t cros_link_end = cros_text.find(kEndLinkCrosOss, cros_link); + DCHECK(cros_link_end != std::string::npos); + + localized_strings->SetString("cros_license_content_0", + cros_text.substr(0, cros_link)); + localized_strings->SetString("cros_license_content_1", + cros_text.substr(cros_link_end + strlen(kEndLinkCrosOss))); + localized_strings->SetString("cros_license_link_content_0", + StringSubRange(cros_text, cros_link + strlen(kBeginLinkCrosOss), + cros_link_end)); + localized_strings->SetString("cros_license_link_0", + chrome::kChromeUIOSCreditsURL); + + // webkit + + localized_strings->SetString("webkit_version", + webkit_glue::GetWebKitVersion()); + + // javascript + + localized_strings->SetString("js_engine", "V8"); + localized_strings->SetString("js_engine_version", v8::V8::GetVersion()); + + // user agent + + localized_strings->SetString("user_agent_info", + content::GetUserAgent(GURL())); + + // command line + +#if defined(OS_WIN) + localized_strings->SetString("command_line_info", + WideToUTF16(CommandLine::ForCurrentProcess()->GetCommandLineString())); +#elif defined(OS_POSIX) + // TODO(viettrungluu): something horrible might happen if there are non-UTF-8 + // arguments (since |SetString()| requires Unicode). + std::string command_line = ""; + typedef std::vector<std::string> ArgvList; + const ArgvList& argv = CommandLine::ForCurrentProcess()->argv(); + for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++) + command_line += " " + *iter; + localized_strings->SetString("command_line_info", command_line); +#endif +} + +void AboutPageHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback("PageReady", + base::Bind(&AboutPageHandler::PageReady, base::Unretained(this))); + web_ui()->RegisterMessageCallback("SetReleaseTrack", + base::Bind(&AboutPageHandler::SetReleaseTrack, base::Unretained(this))); + + web_ui()->RegisterMessageCallback("CheckNow", + base::Bind(&AboutPageHandler::CheckNow, base::Unretained(this))); + web_ui()->RegisterMessageCallback("RestartNow", + base::Bind(&AboutPageHandler::RestartNow, base::Unretained(this))); +} + +void AboutPageHandler::PageReady(const ListValue* args) { + // Version information is loaded from a callback + loader_.GetVersion(&consumer_, + base::Bind(&AboutPageHandler::OnOSVersion, + base::Unretained(this)), + VersionLoader::VERSION_FULL); + loader_.GetFirmware(&consumer_, + base::Bind(&AboutPageHandler::OnOSFirmware, + base::Unretained(this))); + + scoped_ptr<base::Value> can_change_channel_value( + base::Value::CreateBooleanValue(CanChangeReleaseChannel())); + web_ui()->CallJavascriptFunction( + "AboutPage.updateEnableReleaseChannelCallback", + *can_change_channel_value); + + UpdateEngineClient* update_engine_client = + DBusThreadManager::Get()->GetUpdateEngineClient(); + + update_observer_.reset(new UpdateObserver(this)); + update_engine_client->AddObserver(update_observer_.get()); + + // Update the WebUI page with the current status. See comments below. + UpdateStatus(update_engine_client->GetLastStatus()); + + // Initiate update check. UpdateStatus() below will be called when we + // get update status via update_observer_. If the update has been + // already complete, update_observer_ won't receive a notification. + // This is why we manually update the WebUI page above. + CheckNow(NULL); + + // Request the channel information. Use the observer to track the about + // page handler and ensure it does not get deleted before the callback. + update_engine_client->GetReleaseTrack( + base::Bind(UpdateSelectedChannel, update_observer_.get())); +} + +void AboutPageHandler::SetReleaseTrack(const ListValue* args) { + if (!CanChangeReleaseChannel()) { + LOG(WARNING) << "Non-owner tried to change release track."; + return; + } + const std::string channel = UTF16ToUTF8(ExtractStringValue(args)); + DBusThreadManager::Get()->GetUpdateEngineClient()->SetReleaseTrack(channel); + // For local owner set the field in the policy blob too. + if (UserManager::Get()->current_user_is_owner()) { + chromeos::CrosSettings::Get()->SetString(chromeos::kReleaseChannel, + channel); + } +} + +void AboutPageHandler::CheckNow(const ListValue* args) { + // Make sure that libcros is loaded and OOBE is complete. + if (!WizardController::default_controller() || + WizardController::IsDeviceRegistered()) { + DBusThreadManager::Get()->GetUpdateEngineClient()-> + RequestUpdateCheck(UpdateEngineClient::EmptyUpdateCheckCallback()); + } +} + +void AboutPageHandler::RestartNow(const ListValue* args) { + DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); +} + +void AboutPageHandler::UpdateStatus( + const UpdateEngineClient::Status& status) { + string16 message; + std::string image = "up-to-date"; + bool enabled = false; + + switch (status.status) { + case UpdateEngineClient::UPDATE_STATUS_IDLE: + if (!sticky_) { + message = l10n_util::GetStringFUTF16(IDS_UPGRADE_ALREADY_UP_TO_DATE, + l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)); + enabled = true; + } + break; + case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE: + message = l10n_util::GetStringUTF16(IDS_UPGRADE_CHECK_STARTED); + sticky_ = false; + break; + case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE: + message = l10n_util::GetStringUTF16(IDS_UPDATE_AVAILABLE); + started_ = true; + break; + case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING: + { + int progress = static_cast<int>(status.download_progress * 100.0); + if (progress != progress_) { + progress_ = progress; + message = l10n_util::GetStringFUTF16Int(IDS_UPDATE_DOWNLOADING, + progress_); + } + started_ = true; + } + break; + case UpdateEngineClient::UPDATE_STATUS_VERIFYING: + message = l10n_util::GetStringUTF16(IDS_UPDATE_VERIFYING); + started_ = true; + break; + case UpdateEngineClient::UPDATE_STATUS_FINALIZING: + message = l10n_util::GetStringUTF16(IDS_UPDATE_FINALIZING); + started_ = true; + break; + case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT: + message = l10n_util::GetStringUTF16(IDS_UPDATE_COMPLETED); + image = "available"; + sticky_ = true; + break; + default: + // case UpdateEngineClient::UPDATE_STATUS_ERROR: + // case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT: + + // The error is only displayed if we were able to determine an + // update was available. + if (started_) { + message = l10n_util::GetStringUTF16(IDS_UPDATE_ERROR); + image = "fail"; + enabled = true; + sticky_ = true; + started_ = false; + } + break; + } + if (message.size()) { + scoped_ptr<Value> update_message(Value::CreateStringValue(message)); + // "Checking for update..." needs to be shown for a while, so users + // can read it, hence insert delay for this. + scoped_ptr<Value> insert_delay(Value::CreateBooleanValue( + status.status == + UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE)); + web_ui()->CallJavascriptFunction("AboutPage.updateStatusCallback", + *update_message, *insert_delay); + + scoped_ptr<Value> enabled_value(Value::CreateBooleanValue(enabled)); + web_ui()->CallJavascriptFunction("AboutPage.updateEnableCallback", + *enabled_value); + + scoped_ptr<Value> image_string(Value::CreateStringValue(image)); + web_ui()->CallJavascriptFunction("AboutPage.setUpdateImage", + *image_string); + } + // We'll change the "Check For Update" button to "Restart" button. + if (status.status == UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { + web_ui()->CallJavascriptFunction("AboutPage.changeToRestartButton"); + } +} + +void AboutPageHandler::OnOSVersion(VersionLoader::Handle handle, + std::string version) { + if (version.size()) { + scoped_ptr<Value> version_string(Value::CreateStringValue(version)); + web_ui()->CallJavascriptFunction("AboutPage.updateOSVersionCallback", + *version_string); + } +} + +void AboutPageHandler::OnOSFirmware(VersionLoader::Handle handle, + std::string firmware) { + if (firmware.size()) { + scoped_ptr<Value> firmware_string(Value::CreateStringValue(firmware)); + web_ui()->CallJavascriptFunction("AboutPage.updateOSFirmwareCallback", + *firmware_string); + } +} + +// Callback from UpdateEngine with channel information. +// static +void AboutPageHandler::UpdateSelectedChannel(UpdateObserver* observer, + const std::string& channel) { + if (DBusThreadManager::Get()->GetUpdateEngineClient() + ->HasObserver(observer)) { + // If UpdateEngineClient still has the observer, then the page handler + // is valid. + AboutPageHandler* handler = observer->page_handler(); + scoped_ptr<Value> channel_string(Value::CreateStringValue(channel)); + handler->web_ui()->CallJavascriptFunction( + "AboutPage.updateSelectedOptionCallback", *channel_string); + } +} diff --git a/chrome/browser/ui/webui/about_page/about_page_handler.h b/chrome/browser/ui/webui/about_page/about_page_handler.h new file mode 100644 index 0000000..d2d847d --- /dev/null +++ b/chrome/browser/ui/webui/about_page/about_page_handler.h @@ -0,0 +1,70 @@ +// Copyright (c) 2012 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. + +#ifndef CHROME_BROWSER_UI_WEBUI_ABOUT_PAGE_ABOUT_PAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_ABOUT_PAGE_ABOUT_PAGE_HANDLER_H_ + +#include <string> + +#include "base/compiler_specific.h" +#include "chrome/browser/chromeos/dbus/update_engine_client.h" +#include "chrome/browser/chromeos/version_loader.h" +#include "content/public/browser/web_ui_message_handler.h" + +// ChromeOS about page UI handler. +class AboutPageHandler : public content::WebUIMessageHandler { + public: + AboutPageHandler(); + virtual ~AboutPageHandler(); + + // WebUIMessageHandler implementation. + virtual void RegisterMessages() OVERRIDE; + + // Fills |localized_strings| with string values for the UI. + void GetLocalizedValues(base::DictionaryValue* localized_strings); + + private: + class UpdateObserver; + + // The function is called from JavaScript when the about page is ready. + void PageReady(const base::ListValue* args); + + // The function is called from JavaScript to set the release track like + // "beta-channel" and "dev-channel". + void SetReleaseTrack(const base::ListValue* args); + + // Initiates update check. + void CheckNow(const base::ListValue* args); + + // Restarts the system. + void RestartNow(const base::ListValue* args); + + // Callback from VersionLoader giving the version. + void OnOSVersion(chromeos::VersionLoader::Handle handle, + std::string version); + void OnOSFirmware(chromeos::VersionLoader::Handle handle, + std::string firmware); + void UpdateStatus(const chromeos::UpdateEngineClient::Status& status); + + // UpdateEngine Callback handler. + static void UpdateSelectedChannel(UpdateObserver* observer, + const std::string& channel); + + // Handles asynchronously loading the version. + chromeos::VersionLoader loader_; + + // Used to request the version. + CancelableRequestConsumer consumer_; + + // Update Observer + scoped_ptr<UpdateObserver> update_observer_; + + int progress_; + bool sticky_; + bool started_; + + DISALLOW_COPY_AND_ASSIGN(AboutPageHandler); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_ABOUT_PAGE_ABOUT_PAGE_HANDLER_H_ diff --git a/chrome/browser/ui/webui/about_page/about_page_ui.cc b/chrome/browser/ui/webui/about_page/about_page_ui.cc new file mode 100644 index 0000000..573a6c9 --- /dev/null +++ b/chrome/browser/ui/webui/about_page/about_page_ui.cc @@ -0,0 +1,43 @@ +// Copyright (c) 2012 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. + +#include "chrome/browser/ui/webui/about_page/about_page_ui.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/about_page/about_page_handler.h" +#include "chrome/browser/ui/webui/chrome_url_data_manager.h" +#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h" +#include "chrome/browser/ui/webui/shared_resources_data_source.h" +#include "chrome/common/url_constants.h" +#include "content/public/browser/web_contents.h" +#include "grit/browser_resources.h" + +namespace { + +ChromeWebUIDataSource* CreateAboutPageHTMLSource() { + ChromeWebUIDataSource* source = + new ChromeWebUIDataSource(chrome::kChromeUIAboutPageFrameHost); + + source->set_json_path("strings.js"); + source->add_resource_path("about_page.js", IDR_ABOUT_PAGE_JS); + source->set_default_resource(IDR_ABOUT_PAGE_HTML); + return source; +} + +} // namespace + +AboutPageUI::AboutPageUI(content::WebContents* contents) : WebUI(contents) { + Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); + ChromeWebUIDataSource* source = CreateAboutPageHTMLSource(); + profile->GetChromeURLDataManager()->AddDataSource(source); + profile->GetChromeURLDataManager()->AddDataSource( + new SharedResourcesDataSource()); + + AboutPageHandler* handler = new AboutPageHandler(); + handler->GetLocalizedValues(source->localized_strings()); + AddMessageHandler(handler); +} + +AboutPageUI::~AboutPageUI() { +} diff --git a/chrome/browser/ui/webui/about_page/about_page_ui.h b/chrome/browser/ui/webui/about_page/about_page_ui.h new file mode 100644 index 0000000..a53181f --- /dev/null +++ b/chrome/browser/ui/webui/about_page/about_page_ui.h @@ -0,0 +1,21 @@ +// Copyright (c) 2012 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. + + +#ifndef CHROME_BROWSER_UI_WEBUI_ABOUT_PAGE_ABOUT_PAGE_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_ABOUT_PAGE_ABOUT_PAGE_UI_H_ +#pragma once + +#include "content/browser/webui/web_ui.h" + +class AboutPageUI : public WebUI { + public: + explicit AboutPageUI(content::WebContents* contents); + virtual ~AboutPageUI(); + + private: + DISALLOW_COPY_AND_ASSIGN(AboutPageUI); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_ABOUT_PAGE_ABOUT_PAGE_UI_H_ |