summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/about_chrome_view.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/views/about_chrome_view.cc
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/about_chrome_view.cc')
-rw-r--r--chrome/browser/views/about_chrome_view.cc490
1 files changed, 490 insertions, 0 deletions
diff --git a/chrome/browser/views/about_chrome_view.cc b/chrome/browser/views/about_chrome_view.cc
new file mode 100644
index 0000000..157ccc6
--- /dev/null
+++ b/chrome/browser/views/about_chrome_view.cc
@@ -0,0 +1,490 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "chrome/browser/views/about_chrome_view.h"
+
+#include <commdlg.h>
+
+#include "base/file_version_info.h"
+#include "base/string_util.h"
+#include "base/win_util.h"
+#include "chrome/app/locales/locale_settings.h"
+#include "chrome/app/theme/theme_resources.h"
+#include "chrome/common/gfx/color_utils.h"
+#include "chrome/browser/standard_layout.h"
+#include "chrome/browser/user_metrics.h"
+#include "chrome/browser/views/restart_message_box.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/views/text_field.h"
+#include "chrome/views/throbber.h"
+#include "chrome/views/window.h"
+#include "webkit/glue/webkit_glue.h"
+
+#include "generated_resources.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// AboutChromeView, public:
+
+AboutChromeView::AboutChromeView(Profile* profile)
+ : dialog_(NULL),
+ profile_(profile),
+ about_dlg_background_(NULL),
+ about_title_label_(NULL),
+ version_label_(NULL),
+ main_text_label_(NULL),
+ check_button_status_(CHECKBUTTON_HIDDEN),
+ google_updater_(NULL) {
+ DCHECK(profile);
+ Init();
+
+ google_updater_ = new GoogleUpdate(); // This object deletes itself.
+ google_updater_->AddStatusChangeListener(this);
+}
+
+AboutChromeView::~AboutChromeView() {
+ // The Google Updater will hold a pointer to us until it reports status, so we
+ // need to let it know that we will no longer be listening.
+ if (google_updater_)
+ google_updater_->RemoveStatusChangeListener();
+}
+
+void AboutChromeView::Init() {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+ scoped_ptr<FileVersionInfo> version_info(
+ FileVersionInfo::CreateFileVersionInfoForCurrentModule());
+ if (version_info.get() == NULL) {
+ NOTREACHED() << L"Failed to initialize about window";
+ return;
+ }
+
+ current_version_ = version_info->file_version();
+
+ std::wstring official;
+ if (version_info->is_official_build()) {
+ official = l10n_util::GetString(IDS_ABOUT_VERSION_OFFICIAL);
+ } else {
+ official = l10n_util::GetString(IDS_ABOUT_VERSION_UNOFFICIAL);
+ }
+
+ // Views we will add to the *parent* of this dialog, since it will display
+ // next to the buttons which we don't draw ourselves.
+ throbber_.reset(new ChromeViews::Throbber(50, true));
+ throbber_->SetParentOwned(false);
+ throbber_->SetVisible(false);
+
+ SkBitmap* success_image = rb.GetBitmapNamed(IDR_UPDATE_UPTODATE);
+ success_indicator_.SetImage(*success_image);
+ success_indicator_.SetParentOwned(false);
+
+ SkBitmap* update_available_image = rb.GetBitmapNamed(IDR_UPDATE_AVAILABLE);
+ update_available_indicator_.SetImage(*update_available_image);
+ update_available_indicator_.SetParentOwned(false);
+
+ SkBitmap* timeout_image = rb.GetBitmapNamed(IDR_UPDATE_FAIL);
+ timeout_indicator_.SetImage(*timeout_image);
+ timeout_indicator_.SetParentOwned(false);
+
+ update_label_.SetVisible(false);
+ update_label_.SetParentOwned(false);
+
+ // Regular view controls we draw by ourself. First, we add the background
+ // image for the dialog. We have two different background bitmaps, one for
+ // LTR UIs and one for RTL UIs. We load the correct bitmap based on the UI
+ // layout of the view.
+ about_dlg_background_ = new ChromeViews::ImageView();
+ SkBitmap* about_background;
+ if (UILayoutIsRightToLeft())
+ about_background = rb.GetBitmapNamed(IDR_ABOUT_BACKGROUND_RTL);
+ else
+ about_background = rb.GetBitmapNamed(IDR_ABOUT_BACKGROUND);
+
+ about_dlg_background_->SetImage(*about_background);
+ AddChildView(about_dlg_background_);
+
+ // Add the dialog labels.
+ about_title_label_ = new ChromeViews::Label(
+ l10n_util::GetString(IDS_PRODUCT_NAME));
+ about_title_label_->SetFont(ResourceBundle::GetSharedInstance().GetFont(
+ ResourceBundle::BaseFont).DeriveFont(18, BOLD_FONTTYPE));
+ AddChildView(about_title_label_);
+
+ // This is a text field so people can copy the version number from the dialog.
+ version_label_ = new ChromeViews::TextField();
+ version_label_->SetText(current_version_);
+ version_label_->SetReadOnly(true);
+ version_label_->RemoveBorder();
+ version_label_->SetFont(ResourceBundle::GetSharedInstance().GetFont(
+ ResourceBundle::BaseFont).DeriveFont(0, BOLD_FONTTYPE));
+ version_label_->set_default_width_in_chars(
+ static_cast<int>(current_version_.size() + 1));
+ AddChildView(version_label_);
+
+ // Text to display at the bottom of the dialog.
+ std::wstring main_text =
+ l10n_util::GetString(IDS_ABOUT_VERSION_COMPANY_NAME) + L"\n" +
+ l10n_util::GetString(IDS_ABOUT_VERSION_COPYRIGHT) + L"\n" +
+ l10n_util::GetStringF(IDS_ABOUT_VERSION_LICENSE,
+ l10n_util::GetString(IDS_ABOUT_VERSION_LICENSE_URL)) + L"\n\n" +
+ official + L" " + version_info->last_change() + L"\n" +
+ UTF8ToWide(webkit_glue::GetDefaultUserAgent());
+
+ main_text_label_ =
+ new ChromeViews::TextField(ChromeViews::TextField::STYLE_MULTILINE);
+ main_text_label_->SetText(main_text);
+ main_text_label_->SetReadOnly(true);
+ main_text_label_->RemoveBorder();
+ // Background color for the main label TextField.
+ SkColor main_label_background = color_utils::GetSysSkColor(COLOR_3DFACE);
+ main_text_label_->SetBackgroundColor(main_label_background);
+ AddChildView(main_text_label_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AboutChromeView, ChromeViews::View implementation:
+
+void AboutChromeView::GetPreferredSize(CSize *out) {
+ DCHECK(out);
+ *out = ChromeViews::Window::GetLocalizedContentsSize(
+ IDS_ABOUT_DIALOG_WIDTH_CHARS,
+ IDS_ABOUT_DIALOG_HEIGHT_LINES).ToSIZE();
+ // We compute the height of the dialog based on the size of the image (it
+ // would be nice to not hard code this), the text in the about dialog and the
+ // margins around the text.
+ out->cy += 145 + (kPanelVertMargin * 2);
+ // TODO(beng): Eventually the image should be positioned such that hard-
+ // coding the width isn't necessary. This breaks with fonts
+ // that are large and cause wrapping.
+ out->cx = 422;
+}
+
+void AboutChromeView::Layout() {
+ CSize panel_size;
+ GetPreferredSize(&panel_size);
+
+ CSize sz;
+
+ // Background image for the dialog.
+ about_dlg_background_->GetPreferredSize(&sz);
+ int background_image_height = sz.cy; // used to position main text below.
+ about_dlg_background_->SetBounds(0, 0, sz.cx, sz.cy);
+
+ // First label goes to the top left corner.
+ about_title_label_->GetPreferredSize(&sz);
+ about_title_label_->SetBounds(kPanelHorizMargin, kPanelVertMargin,
+ sz.cx, sz.cy);
+
+ // Then we have the version number right below it.
+ version_label_->GetPreferredSize(&sz);
+ version_label_->SetBounds(kPanelHorizMargin,
+ about_title_label_->GetY() +
+ about_title_label_->GetHeight() +
+ kRelatedControlVerticalSpacing,
+ sz.cx,
+ sz.cy);
+
+ // For the width of the main text label we want to use up the whole panel
+ // width and remaining height, minus a little margin on each side.
+ int y_pos = background_image_height + kPanelVertMargin;
+ sz.cx = panel_size.cx - 2 * kPanelHorizMargin;
+ sz.cy = panel_size.cy - y_pos;
+ // Draw the text right below the background image.
+ main_text_label_->SetBounds(kPanelHorizMargin,
+ y_pos,
+ sz.cx,
+ sz.cy);
+
+ // Get the y-coordinate of our parent so we can position the text left of the
+ // buttons at the bottom.
+ CRect parent_bounds;
+ GetParent()->GetLocalBounds(&parent_bounds, false);
+
+ throbber_->GetPreferredSize(&sz);
+ int throbber_topleft_x = kPanelHorizMargin;
+ int throbber_topleft_y = parent_bounds.bottom - sz.cy -
+ kButtonVEdgeMargin - 3;
+ throbber_->SetBounds(throbber_topleft_x, throbber_topleft_y, sz.cx, sz.cy);
+
+ // This image is hidden (see ViewHierarchyChanged) and displayed on demand.
+ success_indicator_.GetPreferredSize(&sz);
+ success_indicator_.SetBounds(throbber_topleft_x, throbber_topleft_y,
+ sz.cx, sz.cy);
+
+ // This image is hidden (see ViewHierarchyChanged) and displayed on demand.
+ update_available_indicator_.GetPreferredSize(&sz);
+ update_available_indicator_.SetBounds(throbber_topleft_x, throbber_topleft_y,
+ sz.cx, sz.cy);
+
+ // This image is hidden (see ViewHierarchyChanged) and displayed on demand.
+ timeout_indicator_.GetPreferredSize(&sz);
+ timeout_indicator_.SetBounds(throbber_topleft_x, throbber_topleft_y,
+ sz.cx, sz.cy);
+
+ // The update label should be at the bottom of the screen, to the right of
+ // the throbber. We specify width to the end of the dialog because it contains
+ // variable length messages.
+ update_label_.GetPreferredSize(&sz);
+ int update_label_x = throbber_->GetX() + throbber_->GetWidth() +
+ kRelatedControlHorizontalSpacing;
+ update_label_.SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ update_label_.SetBounds(update_label_x,
+ throbber_topleft_y + 1,
+ parent_bounds.Width() - update_label_x,
+ sz.cy);
+}
+
+void AboutChromeView::ViewHierarchyChanged(bool is_add,
+ ChromeViews::View* parent,
+ ChromeViews::View* child) {
+ // Since we want the some of the controls to show up in the same visual row
+ // as the buttons, which are provided by the framework, we must add the
+ // buttons to the non-client view, which is the parent of this view.
+ // Similarly, when we're removed from the view hierarchy, we must take care
+ // to remove these items as well.
+ if (child == this) {
+ if (is_add) {
+ parent->AddChildView(&update_label_);
+ parent->AddChildView(throbber_.get());
+ parent->AddChildView(&success_indicator_);
+ success_indicator_.SetVisible(false);
+ parent->AddChildView(&update_available_indicator_);
+ update_available_indicator_.SetVisible(false);
+ parent->AddChildView(&timeout_indicator_);
+ timeout_indicator_.SetVisible(false);
+
+ // On-demand updates for Chrome don't work in Vista when UAC is turned
+ // off. So, in this case we just want the About box to not mention
+ // on-demand updates. Silent updates (in the background) should still
+ // work as before.
+ if (win_util::UserAccountControlIsEnabled()) {
+ UpdateStatus(UPGRADE_CHECK_STARTED, GOOGLE_UPDATE_NO_ERROR);
+ google_updater_->CheckForUpdate(false); // false=don't upgrade yet.
+ }
+ } else {
+ parent->RemoveChildView(&update_label_);
+ parent->RemoveChildView(throbber_.get());
+ parent->RemoveChildView(&success_indicator_);
+ parent->RemoveChildView(&update_available_indicator_);
+ parent->RemoveChildView(&timeout_indicator_);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AboutChromeView, ChromeViews::DialogDelegate implementation:
+
+int AboutChromeView::GetDialogButtons() const {
+ return DIALOGBUTTON_OK | DIALOGBUTTON_CANCEL;
+}
+
+std::wstring AboutChromeView::GetDialogButtonLabel(
+ DialogButton button) const {
+ if (button == DIALOGBUTTON_OK) {
+ return l10n_util::GetString(IDS_ABOUT_CHROME_UPDATE_CHECK);
+ } else if (button == DIALOGBUTTON_CANCEL) {
+ // The OK button (which is the default button) has been re-purposed to be
+ // 'Check for Updates' so we want the Cancel button should have the label
+ // OK but act like a Cancel button in all other ways.
+ return l10n_util::GetString(IDS_OK);
+ }
+
+ NOTREACHED();
+ return L"";
+}
+
+bool AboutChromeView::IsDialogButtonEnabled(DialogButton button) const {
+ if (button == DIALOGBUTTON_OK && check_button_status_ != CHECKBUTTON_ENABLED)
+ return false;
+
+ return true;
+}
+
+bool AboutChromeView::IsDialogButtonVisible(DialogButton button) const {
+ if (button == DIALOGBUTTON_OK && check_button_status_ == CHECKBUTTON_HIDDEN)
+ return false;
+
+ return true;
+}
+
+bool AboutChromeView::CanResize() const {
+ return false;
+}
+
+bool AboutChromeView::CanMaximize() const {
+ return false;
+}
+
+bool AboutChromeView::IsAlwaysOnTop() const {
+ return false;
+}
+
+bool AboutChromeView::HasAlwaysOnTopMenu() const {
+ return false;
+}
+
+bool AboutChromeView::IsModal() const {
+ return true;
+}
+
+std::wstring AboutChromeView::GetWindowTitle() const {
+ return l10n_util::GetString(IDS_ABOUT_CHROME_TITLE);
+}
+
+bool AboutChromeView::Accept() {
+ UpdateStatus(UPGRADE_STARTED, GOOGLE_UPDATE_NO_ERROR);
+
+ // The Upgrade button isn't available until we have received notification
+ // that an update is available, at which point this pointer should have been
+ // null-ed out.
+ DCHECK(!google_updater_);
+ google_updater_ = new GoogleUpdate(); // This object deletes itself.
+ google_updater_->AddStatusChangeListener(this);
+ google_updater_->CheckForUpdate(true); // true=upgrade if new version found.
+
+ return false; // We never allow this button to close the window.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AboutChromeView, GoogleUpdateStatusListener implementation:
+
+void AboutChromeView::OnReportResults(GoogleUpdateUpgradeResult result,
+ GoogleUpdateErrorCode error_code,
+ const std::wstring& version) {
+ // The object will free itself after reporting its status, so we should
+ // no longer refer to it.
+ google_updater_ = NULL;
+
+ // Make a note of which version Google Update is reporting is the latest
+ // version.
+ new_version_available_ = version;
+ if (!new_version_available_.empty()) {
+ new_version_available_ = std::wstring(L"(") +
+ new_version_available_ +
+ std::wstring(L")");
+ }
+ UpdateStatus(result, error_code);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AboutChromeView, private:
+
+void AboutChromeView::UpdateStatus(GoogleUpdateUpgradeResult result,
+ GoogleUpdateErrorCode error_code) {
+ bool show_success_indicator = false;
+ bool show_update_available_indicator = false;
+ bool show_timeout_indicator = false;
+ bool show_throbber = false;
+ bool show_update_label = true; // Always visible, except at start.
+
+ switch (result) {
+ case UPGRADE_STARTED:
+ UserMetrics::RecordAction(L"Upgrade_Started", profile_);
+ check_button_status_ = CHECKBUTTON_DISABLED;
+ show_throbber = true;
+ update_label_.SetText(l10n_util::GetString(IDS_UPGRADE_STARTED));
+ break;
+ case UPGRADE_CHECK_STARTED:
+ UserMetrics::RecordAction(L"UpgradeCheck_Started", profile_);
+ check_button_status_ = CHECKBUTTON_HIDDEN;
+ show_throbber = true;
+ update_label_.SetText(l10n_util::GetString(IDS_UPGRADE_CHECK_STARTED));
+ break;
+ case UPGRADE_IS_AVAILABLE:
+ UserMetrics::RecordAction(L"UpgradeCheck_UpgradeIsAvailable", profile_);
+ check_button_status_ = CHECKBUTTON_ENABLED;
+ update_label_.SetText(
+ l10n_util::GetStringF(IDS_UPGRADE_AVAILABLE,
+ l10n_util::GetString(IDS_PRODUCT_NAME)));
+ show_update_available_indicator = true;
+ break;
+ case UPGRADE_ALREADY_UP_TO_DATE: {
+ // Google Update reported that Chrome is up-to-date. Now make sure that we
+ // are running the latest version and if not, notify the user by falling
+ // into the next case of UPGRADE_SUCCESSFUL.
+ scoped_ptr<installer::Version> installed_version(
+ InstallUtil::GetChromeVersion(false));
+ scoped_ptr<installer::Version> running_version(
+ installer::Version::GetVersionFromString(current_version_));
+ if (!installed_version.get() ||
+ !installed_version->IsHigherThan(running_version.get())) {
+ UserMetrics::RecordAction(L"UpgradeCheck_AlreadyUpToDate", profile_);
+ check_button_status_ = CHECKBUTTON_HIDDEN;
+ update_label_.SetText(
+ l10n_util::GetStringF(IDS_UPGRADE_ALREADY_UP_TO_DATE,
+ l10n_util::GetString(IDS_PRODUCT_NAME),
+ current_version_));
+ show_success_indicator = true;
+ break;
+ }
+ // No break here as we want to notify user about upgrade if there is one.
+ }
+ case UPGRADE_SUCCESSFUL:
+ if (result == UPGRADE_ALREADY_UP_TO_DATE)
+ UserMetrics::RecordAction(L"UpgradeCheck_AlreadyUpgraded", profile_);
+ else
+ UserMetrics::RecordAction(L"UpgradeCheck_Upgraded", profile_);
+ check_button_status_ = CHECKBUTTON_HIDDEN;
+ update_label_.SetText(l10n_util::GetStringF(IDS_UPGRADE_SUCCESSFUL,
+ l10n_util::GetString(IDS_PRODUCT_NAME),
+ new_version_available_));
+ show_success_indicator = true;
+ RestartMessageBox::ShowMessageBox(dialog_->GetHWND());
+ break;
+ case UPGRADE_ERROR:
+ UserMetrics::RecordAction(L"UpgradeCheck_Error", profile_);
+ check_button_status_ = CHECKBUTTON_HIDDEN;
+ update_label_.SetText(l10n_util::GetStringF(IDS_UPGRADE_ERROR,
+ IntToWString(error_code)));
+ show_timeout_indicator = true;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ success_indicator_.SetVisible(show_success_indicator);
+ update_available_indicator_.SetVisible(show_update_available_indicator);
+ timeout_indicator_.SetVisible(show_timeout_indicator);
+ update_label_.SetVisible(show_update_label);
+ throbber_->SetVisible(show_throbber);
+ if (show_throbber)
+ throbber_->Start();
+ else
+ throbber_->Stop();
+
+ // We have updated controls on the parent, so we need to update its layout.
+ View* parent = GetParent();
+ parent->Layout();
+
+ // Check button may have appeared/disappeared. We cannot call this during
+ // ViewHierarchyChanged because the |dialog_| pointer hasn't been set yet.
+ if (dialog_)
+ dialog_->UpdateDialogButtons();
+}