summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-11 03:29:26 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-11 03:29:26 +0000
commitf3a5fad86e9fccdd21af528c43a78f1b9c20e1e4 (patch)
treea3cc652d8bd50ca97feefd4c429139c17e431868
parent634f22bcc80d020d87345341cc2c5b60b451b868 (diff)
downloadchromium_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.css34
-rw-r--r--chrome/browser/resources/about_page/about_page.html145
-rw-r--r--chrome/browser/resources/about_page/about_page.js227
-rw-r--r--chrome/browser/ui/webui/about_page/about_page_handler.cc471
-rw-r--r--chrome/browser/ui/webui/about_page/about_page_handler.h70
-rw-r--r--chrome/browser/ui/webui/about_page/about_page_ui.cc43
-rw-r--r--chrome/browser/ui/webui/about_page/about_page_ui.h21
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_