summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authormirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-03 22:04:40 +0000
committermirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-03 22:04:40 +0000
commit91e1bd8b364d374372ab7be8c133ca03ffa1d2dd (patch)
treecc09b2d614599d8d3c3311d9a2080c071817f0f7 /chrome/browser
parent673336b8ef5a8708d7d3fe0dc8c3daa8d12d4097 (diff)
downloadchromium_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.cc22
-rw-r--r--chrome/browser/download/download_manager.cc6
-rw-r--r--chrome/browser/extensions/extensions_service.cc5
-rw-r--r--chrome/browser/views/theme_install_bubble_view.cc151
-rw-r--r--chrome/browser/views/theme_install_bubble_view.h67
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);
+};
+