summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authordewittj@chromium.org <dewittj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-31 06:07:33 +0000
committerdewittj@chromium.org <dewittj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-31 06:07:33 +0000
commitc404bd8b7f13cb246d6537cd6ab9d2caa5ff4012 (patch)
tree38f000ab2a0b0c3b45790fd93dcb96cdd3a8cdd9 /ui
parent360ef9f95352c591a2c07b384f4b9cd9a8d6974a (diff)
downloadchromium_src-c404bd8b7f13cb246d6537cd6ab9d2caa5ff4012.zip
chromium_src-c404bd8b7f13cb246d6537cd6ab9d2caa5ff4012.tar.gz
chromium_src-c404bd8b7f13cb246d6537cd6ab9d2caa5ff4012.tar.bz2
Implement message center on Windows.
This takes the existing message center code for Ash, and refactors it into two layers - a system-specific layer (WebNotificationTray) and a platform-independent (modulo Views) layer (MessageCenterTray). The WebNotificationTray is responsible for rendering the tray icon and noticing system changes that cause differences in rendering. The MessageCenterTray delegates responsibility for rendering the message center and notification bubbles to the WebNotificationTray. This patch also adds a Windows port of MessageCenterTray - MessageCenterTrayWin. BUG=168605 TEST: message_center_unittests browser_tests (WebNotificationTrayWinTest.*) ash_unittests (WebNotificationTrayTest.*) Review URL: https://chromiumcodereview.appspot.com/11819048 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@179807 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/message_center/message_center.gyp4
-rw-r--r--ui/message_center/message_center.h2
-rw-r--r--ui/message_center/message_center_tray.cc111
-rw-r--r--ui/message_center/message_center_tray.h73
-rw-r--r--ui/message_center/message_center_tray_delegate.h44
-rw-r--r--ui/message_center/message_center_tray_unittest.cc208
-rw-r--r--ui/views/bubble/tray_bubble_view.cc9
-rw-r--r--ui/views/bubble/tray_bubble_view.h8
8 files changed, 452 insertions, 7 deletions
diff --git a/ui/message_center/message_center.gyp b/ui/message_center/message_center.gyp
index c2c631a..f778182 100644
--- a/ui/message_center/message_center.gyp
+++ b/ui/message_center/message_center.gyp
@@ -34,6 +34,9 @@
'message_center_constants.cc',
'message_center_constants.h',
'message_center_export.h',
+ 'message_center_tray.cc',
+ 'message_center_tray.h',
+ 'message_center_tray_delegate.h',
'message_center_switches.cc',
'message_center_switches.h',
'message_popup_bubble.cc',
@@ -67,6 +70,7 @@
'message_center',
],
'sources': [
+ 'message_center_tray_unittest.cc',
'notification_list_unittest.cc',
],
},
diff --git a/ui/message_center/message_center.h b/ui/message_center/message_center.h
index 3850489..e502913 100644
--- a/ui/message_center/message_center.h
+++ b/ui/message_center/message_center.h
@@ -14,8 +14,6 @@
#include "ui/message_center/notification_list.h"
#include "ui/notifications/notification_types.h"
-template <typename T> struct DefaultSingletonTraits;
-
namespace base {
class DictionaryValue;
}
diff --git a/ui/message_center/message_center_tray.cc b/ui/message_center/message_center_tray.cc
new file mode 100644
index 0000000..81c3bcd
--- /dev/null
+++ b/ui/message_center/message_center_tray.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2013 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 "ui/message_center/message_center_tray.h"
+
+#include "base/observer_list.h"
+#include "base/utf_string_conversions.h"
+#include "ui/message_center/message_center_tray_delegate.h"
+
+namespace message_center {
+
+MessageCenterTray::MessageCenterTray(
+ MessageCenterTrayDelegate* delegate,
+ message_center::MessageCenter* message_center)
+ : message_center_(message_center),
+ message_center_visible_(false),
+ popups_visible_(false),
+ delegate_(delegate) {
+ message_center_->AddObserver(this);
+}
+
+MessageCenterTray::~MessageCenterTray() {
+ message_center_->RemoveObserver(this);
+}
+
+bool MessageCenterTray::ShowMessageCenterBubble() {
+ if (message_center_visible_)
+ return true;
+
+ HidePopupBubble();
+
+ message_center_visible_ = delegate_->ShowMessageCenter();
+ message_center_->SetMessageCenterVisible(message_center_visible_);
+ return message_center_visible_;
+}
+
+bool MessageCenterTray::HideMessageCenterBubble() {
+ if (!message_center_visible_)
+ return false;
+ delegate_->HideMessageCenter();
+ message_center_visible_ = false;
+ message_center_->SetMessageCenterVisible(false);
+ NotifyMessageCenterTrayChanged();
+ return true;
+}
+
+void MessageCenterTray::ToggleMessageCenterBubble() {
+ if (message_center_visible_)
+ HideMessageCenterBubble();
+ else
+ ShowMessageCenterBubble();
+}
+
+void MessageCenterTray::ShowPopupBubble() {
+ if (message_center_visible_) {
+ // We don't want to show popups if the user is already looking at the
+ // message center. Instead, update it.
+ delegate_->UpdateMessageCenter();
+ return;
+ }
+
+ if (popups_visible_) {
+ delegate_->UpdatePopups();
+ NotifyMessageCenterTrayChanged();
+ return;
+ }
+
+ if (!message_center_->HasPopupNotifications())
+ return;
+
+ popups_visible_ = delegate_->ShowPopups();
+ NotifyMessageCenterTrayChanged();
+}
+
+bool MessageCenterTray::HidePopupBubble() {
+ if (!popups_visible_)
+ return false;
+
+ delegate_->HidePopups();
+ popups_visible_ = false;
+ NotifyMessageCenterTrayChanged();
+
+ return true;
+}
+
+void MessageCenterTray::OnMessageCenterChanged(bool new_notification) {
+ if (message_center_visible_) {
+ if (message_center_->NotificationCount() == 0)
+ HideMessageCenterBubble();
+ else
+ delegate_->UpdateMessageCenter();
+ }
+ if (popups_visible_) {
+ if (message_center_->NotificationCount() == 0)
+ HidePopupBubble();
+ else
+ delegate_->UpdatePopups();
+ }
+
+ if (new_notification)
+ ShowPopupBubble();
+
+ NotifyMessageCenterTrayChanged();
+}
+
+void MessageCenterTray::NotifyMessageCenterTrayChanged() {
+ delegate_->OnMessageCenterTrayChanged();
+}
+
+} // namespace message_center
diff --git a/ui/message_center/message_center_tray.h b/ui/message_center/message_center_tray.h
new file mode 100644
index 0000000..4d7f98a0
--- /dev/null
+++ b/ui/message_center/message_center_tray.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2013 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 UI_MESSAGE_CENTER_MESSAGE_CENTER_TRAY_H_
+#define UI_MESSAGE_CENTER_MESSAGE_CENTER_TRAY_H_
+
+#include "base/observer_list.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/message_center_export.h"
+#include "ui/message_center/message_center_tray_delegate.h"
+
+namespace message_center {
+
+class MessageBubbleBase;
+class MessagePopupBubble;
+class QuietModeBubble;
+
+// Implementation found with each supported platform's implementation of
+// MessageCenterTrayDelegate.
+MessageCenterTrayDelegate* CreateMessageCenterTray();
+
+// Class that observes a MessageCenter. Manages the popup and message center
+// bubbles. Tells the MessageCenterTrayHost when the tray is changed, as well
+// as when bubbles are shown and hidden.
+class MESSAGE_CENTER_EXPORT MessageCenterTray
+ : public message_center::MessageCenter::Observer {
+ public:
+ MessageCenterTray(MessageCenterTrayDelegate* delegate,
+ message_center::MessageCenter* message_center);
+ virtual ~MessageCenterTray();
+
+ // Shows or updates the message center bubble and hides the popup bubble.
+ // Returns whether the message center is visible after the call, whether or
+ // not it was visible before.
+ bool ShowMessageCenterBubble();
+
+ // Returns whether the message center was visible before.
+ bool HideMessageCenterBubble();
+
+ void ToggleMessageCenterBubble();
+
+ // Causes an update if the popup bubble is already shown.
+ void ShowPopupBubble();
+
+ // Returns whether the popup was visible before.
+ bool HidePopupBubble();
+
+ bool message_center_visible() { return message_center_visible_; }
+ bool popups_visible() { return popups_visible_; }
+ MessageCenterTrayDelegate* delegate() { return delegate_; }
+ message_center::MessageCenter* message_center() { return message_center_; }
+
+ // Overridden from message_center::MessageCenter::Observer.
+ virtual void OnMessageCenterChanged(bool new_notification) OVERRIDE;
+
+ private:
+ void NotifyMessageCenterTrayChanged();
+
+ // |message_center_| is a weak pointer that must live longer than
+ // MessageCenterTray.
+ message_center::MessageCenter* message_center_;
+ bool message_center_visible_;
+ bool popups_visible_;
+ // |delegate_| is a weak pointer that must live longer than MessageCenterTray.
+ MessageCenterTrayDelegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageCenterTray);
+};
+
+} // namespace message_center
+
+#endif // UI_MESSAGE_CENTER_MESSAGE_CENTER_TRAY_H_
diff --git a/ui/message_center/message_center_tray_delegate.h b/ui/message_center/message_center_tray_delegate.h
new file mode 100644
index 0000000..edd31a3
--- /dev/null
+++ b/ui/message_center/message_center_tray_delegate.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2013 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 UI_MESSAGE_CENTER_MESSAGE_CENTER_TRAY_DELEGATE_H_
+#define UI_MESSAGE_CENTER_MESSAGE_CENTER_TRAY_DELEGATE_H_
+
+namespace message_center {
+
+// A MessageCenterTrayDelegate class is responsible for managing the various UI
+// surfaces that should be displayed when the MessageCenter is changed.
+class MESSAGE_CENTER_EXPORT MessageCenterTrayDelegate {
+ public:
+ virtual ~MessageCenterTrayDelegate() {};
+
+ // Called whenever a change to the visible UI has occurred.
+ virtual void OnMessageCenterTrayChanged() = 0;
+
+ // Display the popup bubbles for new notifications to the user. Returns true
+ // if popups were actually displayed to the user.
+ virtual bool ShowPopups() = 0;
+
+ // Remove the popup bubbles from the UI.
+ virtual void HidePopups() = 0;
+
+ // Called when a change to the message center could cause a change to popups
+ // that are currently being displayed.
+ virtual void UpdatePopups() = 0;
+
+ // Display the message center containing all undismissed notifications to the
+ // user. Returns true if the center was actually displayed to the user.
+ virtual bool ShowMessageCenter() = 0;
+
+ // Remove the message center from the UI.
+ virtual void HideMessageCenter() = 0;
+
+ // Called when a change to the message center could cause a change to the
+ // message center widget that is currently being displayed.
+ virtual void UpdateMessageCenter() = 0;
+};
+
+} // namespace message_center
+
+#endif // UI_MESSAGE_CENTER_MESSAGE_CENTER_TRAY_DELEGATE_H_
diff --git a/ui/message_center/message_center_tray_unittest.cc b/ui/message_center/message_center_tray_unittest.cc
new file mode 100644
index 0000000..24a83e5
--- /dev/null
+++ b/ui/message_center/message_center_tray_unittest.cc
@@ -0,0 +1,208 @@
+// Copyright (c) 2013 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 "ui/message_center/message_center_tray.h"
+
+#include "base/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/message_center/message_center.h"
+#include "ui/notifications/notification_types.h"
+
+namespace message_center {
+namespace {
+
+class MockDelegate : public MessageCenterTrayDelegate {
+ public:
+ MockDelegate()
+ : show_popups_success_(true),
+ show_message_center_success_(true) {}
+ virtual ~MockDelegate() {}
+ virtual void OnMessageCenterTrayChanged() {}
+ virtual bool ShowPopups() {
+ return show_message_center_success_;
+ }
+ virtual void HidePopups() {}
+ virtual void UpdatePopups() {}
+ virtual bool ShowMessageCenter() {
+ return show_popups_success_;
+ }
+ virtual void HideMessageCenter() {}
+ virtual void UpdateMessageCenter() {}
+
+ bool show_popups_success_;
+ bool show_message_center_success_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockDelegate);
+};
+
+class MessageCenterTrayTest : public testing::Test {
+ public:
+ MessageCenterTrayTest() {}
+ virtual ~MessageCenterTrayTest() {}
+
+ virtual void SetUp() {
+ delegate_.reset(new MockDelegate);
+ message_center_.reset(new MessageCenter());
+ message_center_tray_.reset(
+ new MessageCenterTray(delegate_.get(), message_center_.get()));
+ }
+
+ virtual void TearDown() {
+ message_center_tray_.reset();
+ message_center_.reset();
+ delegate_.reset();
+ }
+
+ protected:
+ scoped_ptr<MockDelegate> delegate_;
+ scoped_ptr<MessageCenterTray> message_center_tray_;
+ scoped_ptr<MessageCenter> message_center_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MessageCenterTrayTest);
+};
+
+} // namespace
+
+TEST_F(MessageCenterTrayTest, BasicMessageCenter) {
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ bool shown = message_center_tray_->ShowMessageCenterBubble();
+ EXPECT_TRUE(shown);
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_TRUE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->HideMessageCenterBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->ToggleMessageCenterBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_TRUE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->ToggleMessageCenterBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+}
+
+TEST_F(MessageCenterTrayTest, BasicPopup) {
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->ShowPopupBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_->AddNotification(
+ ui::notifications::NOTIFICATION_TYPE_SIMPLE,
+ "BasicPopup",
+ ASCIIToUTF16("Test Web Notification"),
+ ASCIIToUTF16("Notification message body."),
+ ASCIIToUTF16("www.test.org"),
+ "" /* extension id */,
+ NULL /* optional_fields */);
+
+ ASSERT_TRUE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->HidePopupBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+}
+
+TEST_F(MessageCenterTrayTest, MessageCenterClosesPopups) {
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_->AddNotification(
+ ui::notifications::NOTIFICATION_TYPE_SIMPLE,
+ "MessageCenterClosesPopups",
+ ASCIIToUTF16("Test Web Notification"),
+ ASCIIToUTF16("Notification message body."),
+ ASCIIToUTF16("www.test.org"),
+ "" /* extension id */,
+ NULL /* optional_fields */);
+
+ ASSERT_TRUE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ bool shown = message_center_tray_->ShowMessageCenterBubble();
+ EXPECT_TRUE(shown);
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_TRUE(message_center_tray_->message_center_visible());
+
+ message_center_->AddNotification(
+ ui::notifications::NOTIFICATION_TYPE_SIMPLE,
+ "MessageCenterClosesPopups2",
+ ASCIIToUTF16("Test Web Notification"),
+ ASCIIToUTF16("Notification message body."),
+ ASCIIToUTF16("www.test.org"),
+ "" /* extension id */,
+ NULL /* optional_fields */);
+
+ message_center_tray_->ShowPopupBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_TRUE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->HideMessageCenterBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+}
+
+TEST_F(MessageCenterTrayTest, ShowBubbleFails) {
+ // Now the delegate will signal that it was unable to show a bubble.
+ delegate_->show_popups_success_ = false;
+ delegate_->show_message_center_success_ = false;
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_->AddNotification(
+ ui::notifications::NOTIFICATION_TYPE_SIMPLE,
+ "ShowBubbleFails",
+ ASCIIToUTF16("Test Web Notification"),
+ ASCIIToUTF16("Notification message body."),
+ ASCIIToUTF16("www.test.org"),
+ "" /* extension id */,
+ NULL /* optional_fields */);
+
+ message_center_tray_->ShowPopupBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ bool shown = message_center_tray_->ShowMessageCenterBubble();
+ EXPECT_FALSE(shown);
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->HideMessageCenterBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->ToggleMessageCenterBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+
+ message_center_tray_->HidePopupBubble();
+
+ ASSERT_FALSE(message_center_tray_->popups_visible());
+ ASSERT_FALSE(message_center_tray_->message_center_visible());
+}
+
+} // namespace message_center
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc
index 3b13f2b..c81752d 100644
--- a/ui/views/bubble/tray_bubble_view.cc
+++ b/ui/views/bubble/tray_bubble_view.cc
@@ -48,7 +48,7 @@ class TrayBubbleBorder : public views::BubbleBorder {
owner_(owner),
anchor_(anchor),
tray_arrow_offset_(params.arrow_offset) {
- set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
+ set_alignment(params.arrow_alignment);
set_background_color(params.arrow_color);
set_paint_arrow(!params.hide_arrow);
}
@@ -60,7 +60,7 @@ class TrayBubbleBorder : public views::BubbleBorder {
// it has no arrow.
virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
const gfx::Size& contents_size) const OVERRIDE {
- if (arrow_location() != NONE) {
+ if (has_arrow(arrow_location())) {
return views::BubbleBorder::GetBounds(position_relative_to,
contents_size);
}
@@ -235,7 +235,8 @@ TrayBubbleView::InitParams::InitParams(AnchorType anchor_type,
arrow_location(views::BubbleBorder::NONE),
arrow_offset(kArrowDefaultOffset),
hide_arrow(false),
- shadow(views::BubbleBorder::BIG_SHADOW) {
+ shadow(views::BubbleBorder::BIG_SHADOW),
+ arrow_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE) {
}
// static
@@ -295,7 +296,7 @@ TrayBubbleView::~TrayBubbleView() {
void TrayBubbleView::InitializeAndShowBubble() {
// Must occur after call to BubbleDelegateView::CreateBubble().
- SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
+ SetAlignment(params_.arrow_alignment);
bubble_border_->UpdateArrowOffset();
if (get_use_acceleration_when_possible())
diff --git a/ui/views/bubble/tray_bubble_view.h b/ui/views/bubble/tray_bubble_view.h
index 218d885..353473a 100644
--- a/ui/views/bubble/tray_bubble_view.h
+++ b/ui/views/bubble/tray_bubble_view.h
@@ -32,11 +32,16 @@ class TrayBubbleContentMask;
class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView {
public:
+ // AnchorType differentiates between bubbles that are anchored on a tray
+ // element (ANCHOR_TYPE_TRAY) and display an arrow, or that are floating on
+ // the screen away from the tray (ANCHOR_TYPE_BUBBLE).
enum AnchorType {
ANCHOR_TYPE_TRAY,
- ANCHOR_TYPE_BUBBLE
+ ANCHOR_TYPE_BUBBLE,
};
+ // AnchorAlignment determines to which side of the anchor the bubble will
+ // align itself.
enum AnchorAlignment {
ANCHOR_ALIGNMENT_BOTTOM,
ANCHOR_ALIGNMENT_LEFT,
@@ -97,6 +102,7 @@ class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView {
int arrow_offset;
bool hide_arrow; // hides arrow, but may still use "arrow geometry"
views::BubbleBorder::Shadow shadow;
+ views::BubbleBorder::BubbleAlignment arrow_alignment;
};
// Constructs and returns a TrayBubbleView. init_params may be modified.