diff options
author | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-03 22:04:40 +0000 |
---|---|---|
committer | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-03 22:04:40 +0000 |
commit | 91e1bd8b364d374372ab7be8c133ca03ffa1d2dd (patch) | |
tree | cc09b2d614599d8d3c3311d9a2080c071817f0f7 /chrome/browser | |
parent | 673336b8ef5a8708d7d3fe0dc8c3daa8d12d4097 (diff) | |
download | chromium_src-91e1bd8b364d374372ab7be8c133ca03ffa1d2dd.zip chromium_src-91e1bd8b364d374372ab7be8c133ca03ffa1d2dd.tar.gz chromium_src-91e1bd8b364d374372ab7be8c133ca03ffa1d2dd.tar.bz2 |
Add "loading..." message to theme install to counter jank.
BUG= http://crbug.com/17696
TEST= Install a theme. Note that a "loading" message appears to notify you that a theme is loading.
Review URL: http://codereview.chromium.org/191011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25383 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser.cc | 22 | ||||
-rw-r--r-- | chrome/browser/download/download_manager.cc | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 5 | ||||
-rw-r--r-- | chrome/browser/views/theme_install_bubble_view.cc | 151 | ||||
-rw-r--r-- | chrome/browser/views/theme_install_bubble_view.h | 67 |
5 files changed, 251 insertions, 0 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 877f887..514d0ff 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -83,6 +83,7 @@ #include "chrome/browser/user_data_manager.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/location_bar_view.h" +#include "chrome/browser/views/theme_install_bubble_view.h" #include "chrome/common/child_process_host.h" #endif // OS_WIN @@ -202,6 +203,10 @@ Browser::Browser(Type type, Profile* profile) registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, NotificationService::AllSources()); + // Need to know when to alert the user of theme install delay. + registrar_.Add(this, NotificationType::EXTENSION_READY_FOR_INSTALL, + NotificationService::AllSources()); + InitCommandState(); BrowserList::AddBrowser(this); @@ -2160,6 +2165,23 @@ void Browser::Observe(NotificationType type, window()->UserChangedTheme(); break; + case NotificationType::EXTENSION_READY_FOR_INSTALL: { +#if defined(OS_WIN) + if (BrowserList::GetLastActive() != this) + break; + TabContents* tab_contents = + BrowserList::GetLastActive()->GetSelectedTabContents(); + if (!tab_contents) + break; + if (platform_util::IsVisible(tab_contents->GetNativeView())) + ThemeInstallBubbleView::Show(tab_contents); +#else + NOTIMPLEMENTED(); +#endif + break; + } + + default: NOTREACHED() << "Got a notification we didn't register for."; } diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index 4c4dc9e..ae61ffd 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -32,6 +32,8 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" #include "chrome/common/platform_util.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" @@ -1250,6 +1252,10 @@ void DownloadManager::OpenChromeExtension(const FilePath& full_path, // We don't support extensions in OTR mode. ExtensionsService* service = profile_->GetExtensionsService(); if (service) { + NotificationService* nservice = NotificationService::current(); + nservice->Notify(NotificationType::EXTENSION_READY_FOR_INSTALL, + Source<DownloadManager>(this), + NotificationService::NoDetails()); CrxInstaller::Start(full_path, service->install_directory(), Extension::INTERNAL, diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 3aaf9fa..46bce98 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -490,6 +490,11 @@ void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { NotificationType::THEME_INSTALLED, Source<ExtensionsService>(this), Details<Extension>(extension)); + } else { + NotificationService::current()->Notify( + NotificationType::NO_THEME_DETECTED, + Source<ExtensionsService>(this), + NotificationService::NoDetails()); } } diff --git a/chrome/browser/views/theme_install_bubble_view.cc b/chrome/browser/views/theme_install_bubble_view.cc new file mode 100644 index 0000000..4920476 --- /dev/null +++ b/chrome/browser/views/theme_install_bubble_view.cc @@ -0,0 +1,151 @@ +// Copyright (c) 2009 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 "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "chrome/browser/views/theme_install_bubble_view.h" +#include "grit/generated_resources.h" + +namespace { + // Padding around text in popup box. + static const int kTextHorizPadding = 90; + static const int kTextVertPadding = 45; + + // Multiple loads can be started at once. Only show one bubble, and keep + // track of number of loads happening. Close bubble when num_loads < 1. + static int num_loads_extant_ = 0; +} + +ThemeInstallBubbleView::ThemeInstallBubbleView(TabContents* tab_contents) + : popup_(NULL) { + if (!tab_contents) + Close(); + + text_ = l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + gfx::Font font(rb.GetFont(ResourceBundle::LargeFont)); + SetFont(font); + + // We can't check for the size of tab_contents before we've generated + // the string and the font that determine the size of the bubble. + tab_contents->GetContainerBounds(&tab_contents_bounds_); + if (tab_contents_bounds_.height() < GetPreferredSize().height()) + Close(); + + // Close when theme has been installed. + registrar_.Add( + this, + NotificationType::BROWSER_THEME_CHANGED, + NotificationService::AllSources()); + + // Close when we are installing an extension, not a theme. + registrar_.Add( + this, + NotificationType::NO_THEME_DETECTED, + NotificationService::AllSources()); + registrar_.Add( + this, + NotificationType::EXTENSION_INSTALLED, + NotificationService::AllSources()); + + gfx::Rect rc(0, 0, 0, 0); + popup_ = new views::WidgetWin; + popup_->set_window_style(WS_POPUP); + popup_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW | + WS_EX_TRANSPARENT); + popup_->SetOpacity(0xCC); + popup_->Init(tab_contents->GetNativeView(), rc); + popup_->SetContentsView(this); + Reposition(); + popup_->Show(); + + SchedulePaint(); +} + +ThemeInstallBubbleView::~ThemeInstallBubbleView() { + num_loads_extant_ = 0; +} + +gfx::Size ThemeInstallBubbleView::GetPreferredSize() { + return gfx::Size(views::Label::GetFont().GetStringWidth(text_) + + kTextHorizPadding, + ResourceBundle::GetSharedInstance().GetFont( + ResourceBundle::LargeFont).height() + kTextVertPadding); +} + +void ThemeInstallBubbleView::Reposition() { + if (!popup_) + Close(); + + gfx::Size size = GetPreferredSize(); + int mid_x = tab_contents_bounds_.x() + + (tab_contents_bounds_.right() - tab_contents_bounds_.x()) / 2; + + int x = UILayoutIsRightToLeft() ? + mid_x + size.width() / 2 : mid_x - size.width() / 2; + int y = static_cast<int>(tab_contents_bounds_.y() + + (tab_contents_bounds_.bottom() - tab_contents_bounds_.y()) / 2 - + size.height() / 2); + + popup_->MoveWindow(x, y, size.width(), size.height()); +} + +void ThemeInstallBubbleView::Paint(gfx::Canvas* canvas) { + SkScalar rad[8]; + for (int i = 0; i < 8; ++i) + rad[i] = SkIntToScalar(kBubbleCornerRadius); + + gfx::Rect popup_bounds; + popup_->GetBounds(&popup_bounds, true); + + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + paint.setFlags(SkPaint::kAntiAlias_Flag); + paint.setColor(SK_ColorBLACK); + + int width = popup_bounds.width(); + int height = popup_bounds.height(); + SkRect rect; + rect.set(0, 0, + SkIntToScalar(width), + SkIntToScalar(height)); + SkPath path; + path.addRoundRect(rect, rad, SkPath::kCW_Direction); + canvas->drawPath(path, paint); + + int text_width = views::Label::GetFont().GetStringWidth(text_); + gfx::Rect body_bounds(kTextHorizPadding / 2, 0, text_width, height); + body_bounds.set_x(MirroredLeftPointForRect(body_bounds)); + + SkColor text_color = SK_ColorWHITE; + canvas->DrawStringInt(text_, views::Label::GetFont(), text_color, + body_bounds.x(), body_bounds.y(), body_bounds.width(), + body_bounds.height()); +} + +void ThemeInstallBubbleView::Close() { + --num_loads_extant_; + if (!popup_) { + num_loads_extant_ = 0; + return; + } + if (num_loads_extant_ < 1) { + registrar_.RemoveAll(); + popup_->Close(); + } +} + +void ThemeInstallBubbleView::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + Close(); +} + +// static +void ThemeInstallBubbleView::Show(TabContents* tab_contents) { + ++num_loads_extant_; + if (num_loads_extant_ < 2) + new ThemeInstallBubbleView(tab_contents); +} + diff --git a/chrome/browser/views/theme_install_bubble_view.h b/chrome/browser/views/theme_install_bubble_view.h new file mode 100644 index 0000000..3ac742f --- /dev/null +++ b/chrome/browser/views/theme_install_bubble_view.h @@ -0,0 +1,67 @@ +// Copyright (c) 2009 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 "app/gfx/canvas.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/notification_service.h" +#include "views/controls/label.h" +#include "views/widget/widget_win.h" + +// ThemeInstallBubbleView launches a "loading..." bubble in the center of the +// currently active browser window when an extension or theme is loaded. If +// an extension is being applied, the bubble goes away immediately. If a theme +// is being applied, it disappears when the theme has been loaded. The purpose +// of this bubble is to warn the user that the browser may be unresponsive +// while the theme is being installed. +// +// Edge case: note that if one installs a theme in one window and then switches +// rapidly to another window to install a theme there as well (in the short +// time between install begin and theme caching seizing the UI thread), the +// loading bubble will only appear over the first window. +class ThemeInstallBubbleView : public NotificationObserver, + public views::Label { + public: + explicit ThemeInstallBubbleView(TabContents* tab_contents); + + ~ThemeInstallBubbleView(); + + // NotificationObserver + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Show the loading bubble. + static void Show(TabContents* tab_contents); + + private: + // The roundedness of the edges of our bubble. + static const int kBubbleCornerRadius = 4; + + // The content area at the start of the animation. + gfx::Rect tab_contents_bounds_; + + // We use a HWND for the popup so that it may float above any HWNDs in our UI. + views::WidgetWin* popup_; + + // Text to show warning that theme is being installed. + std::wstring text_; + + // A scoped container for notification registries. + NotificationRegistrar registrar_; + + // Put the popup in the correct place on the tab. + void Reposition(); + + // Inherited from views. + gfx::Size GetPreferredSize(); + + // Shut down the popup and remove our notifications. + void Close(); + + virtual void Paint(gfx::Canvas* canvas); + + DISALLOW_COPY_AND_ASSIGN(ThemeInstallBubbleView); +}; + |