summaryrefslogtreecommitdiff
path: root/chromium/ui/message_center
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-05 14:08:31 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-11 07:46:53 +0000
commit6a4cabb866f66d4128a97cdc6d9d08ce074f1247 (patch)
treeab00f70a5e89278d6a0d16ff0c42578dc4d84a2d /chromium/ui/message_center
parente733310db58160074f574c429d48f8308c0afe17 (diff)
downloadqtwebengine-chromium-6a4cabb866f66d4128a97cdc6d9d08ce074f1247.tar.gz
BASELINE: Update Chromium to 57.0.2987.144
Change-Id: I29db402ff696c71a04c4dbaec822c2e53efe0267 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/ui/message_center')
-rw-r--r--chromium/ui/message_center/BUILD.gn13
-rw-r--r--chromium/ui/message_center/fake_notifier_settings_provider.cc129
-rw-r--r--chromium/ui/message_center/fake_notifier_settings_provider.h74
-rw-r--r--chromium/ui/message_center/mojo/notification.mojom2
-rw-r--r--chromium/ui/message_center/notification_delegate.h6
-rw-r--r--chromium/ui/message_center/notification_delegate_views.cc4
-rw-r--r--chromium/ui/message_center/notifier_settings.h6
-rw-r--r--chromium/ui/message_center/views/custom_notification_content_view_delegate.cc18
-rw-r--r--chromium/ui/message_center/views/custom_notification_content_view_delegate.h45
-rw-r--r--chromium/ui/message_center/views/custom_notification_view.cc63
-rw-r--r--chromium/ui/message_center/views/custom_notification_view.h19
-rw-r--r--chromium/ui/message_center/views/custom_notification_view_unittest.cc96
-rw-r--r--chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc6
-rw-r--r--chromium/ui/message_center/views/message_center_bubble.cc4
-rw-r--r--chromium/ui/message_center/views/message_center_button_bar.cc8
-rw-r--r--chromium/ui/message_center/views/message_center_view.cc28
-rw-r--r--chromium/ui/message_center/views/message_center_view.h19
-rw-r--r--chromium/ui/message_center/views/message_center_view_unittest.cc2
-rw-r--r--chromium/ui/message_center/views/message_list_view.cc40
-rw-r--r--chromium/ui/message_center/views/message_list_view.h29
-rw-r--r--chromium/ui/message_center/views/message_list_view_unittest.cc185
-rw-r--r--chromium/ui/message_center/views/message_popup_collection_unittest.cc1
-rw-r--r--chromium/ui/message_center/views/message_view.cc109
-rw-r--r--chromium/ui/message_center/views/message_view.h16
-rw-r--r--chromium/ui/message_center/views/message_view_factory.cc4
-rw-r--r--chromium/ui/message_center/views/notification_view.cc63
-rw-r--r--chromium/ui/message_center/views/notification_view.h11
-rw-r--r--chromium/ui/message_center/views/notification_view_unittest.cc4
-rw-r--r--chromium/ui/message_center/views/notifier_settings_view.cc26
-rw-r--r--chromium/ui/message_center/views/notifier_settings_view.h6
-rw-r--r--chromium/ui/message_center/views/notifier_settings_view_unittest.cc110
-rw-r--r--chromium/ui/message_center/views/toast_contents_view.h5
32 files changed, 699 insertions, 452 deletions
diff --git a/chromium/ui/message_center/BUILD.gn b/chromium/ui/message_center/BUILD.gn
index ea3cf13c2b7..5011167e952 100644
--- a/chromium/ui/message_center/BUILD.gn
+++ b/chromium/ui/message_center/BUILD.gn
@@ -16,7 +16,7 @@ component("message_center") {
defines = [ "MESSAGE_CENTER_IMPLEMENTATION" ]
- if (enable_notifications && !is_android) {
+ if (!is_ios && !is_android) {
deps += [
"//base:i18n",
"//base/third_party/dynamic_annotations",
@@ -98,6 +98,8 @@ component("message_center") {
"views/bounded_label.cc",
"views/bounded_label.h",
"views/constants.h",
+ "views/custom_notification_content_view_delegate.cc",
+ "views/custom_notification_content_view_delegate.h",
"views/custom_notification_view.cc",
"views/custom_notification_view.h",
"views/desktop_popup_alignment_delegate.cc",
@@ -167,14 +169,12 @@ component("message_center") {
static_library("test_support") {
testonly = true
- if (enable_notifications && !is_android) {
+ if (!is_ios && !is_android) {
sources = [
"fake_message_center.cc",
"fake_message_center.h",
"fake_message_center_tray_delegate.cc",
"fake_message_center_tray_delegate.h",
- "fake_notifier_settings_provider.cc",
- "fake_notifier_settings_provider.h",
]
deps = [
"//base",
@@ -218,7 +218,7 @@ test("message_center_unittests") {
"//ui/resources:ui_test_pak_data",
]
- if (enable_notifications && !is_android) {
+ if (!is_ios && !is_android) {
sources += [
"cocoa/notification_controller_unittest.mm",
"cocoa/popup_collection_unittest.mm",
@@ -238,6 +238,7 @@ test("message_center_unittests") {
"views/bounded_label_unittest.cc",
"views/custom_notification_view_unittest.cc",
"views/message_center_view_unittest.cc",
+ "views/message_list_view_unittest.cc",
"views/message_popup_collection_unittest.cc",
"views/notification_view_unittest.cc",
"views/notifier_settings_view_unittest.cc",
@@ -260,5 +261,5 @@ test("message_center_unittests") {
"//ui/message_center/mojo:test_interfaces",
]
}
- } # enable_notifications && !is_android
+ } # !is_ios && !is_android
}
diff --git a/chromium/ui/message_center/fake_notifier_settings_provider.cc b/chromium/ui/message_center/fake_notifier_settings_provider.cc
deleted file mode 100644
index a2c8c5e586a..00000000000
--- a/chromium/ui/message_center/fake_notifier_settings_provider.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// 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/fake_notifier_settings_provider.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "ui/gfx/image/image.h"
-
-namespace message_center {
-
-FakeNotifierSettingsProvider::NotifierGroupItem::NotifierGroupItem() {
-}
-
-FakeNotifierSettingsProvider::NotifierGroupItem::NotifierGroupItem(
- const NotifierGroupItem& other) = default;
-
-FakeNotifierSettingsProvider::NotifierGroupItem::~NotifierGroupItem() {
-}
-
-FakeNotifierSettingsProvider::FakeNotifierSettingsProvider()
- : closed_called_count_(0),
- active_item_index_(0),
- notifier_settings_requested_count_(0u) { }
-
-FakeNotifierSettingsProvider::FakeNotifierSettingsProvider(
- const std::vector<Notifier*>& notifiers)
- : closed_called_count_(0),
- active_item_index_(0),
- notifier_settings_requested_count_(0u) {
- NotifierGroupItem item;
- item.group = new NotifierGroup(base::UTF8ToUTF16("Fake name"),
- base::UTF8ToUTF16("fake@email.com"));
- item.notifiers = notifiers;
- items_.push_back(item);
-}
-
-FakeNotifierSettingsProvider::~FakeNotifierSettingsProvider() {
- for (size_t i = 0; i < items_.size(); ++i) {
- delete items_[i].group;
- }
-}
-
-size_t FakeNotifierSettingsProvider::GetNotifierGroupCount() const {
- return items_.size();
-}
-
-const message_center::NotifierGroup&
-FakeNotifierSettingsProvider::GetNotifierGroupAt(size_t index) const {
- return *(items_[index].group);
-}
-
-bool FakeNotifierSettingsProvider::IsNotifierGroupActiveAt(
- size_t index) const {
- return active_item_index_ == index;
-}
-
-void FakeNotifierSettingsProvider::SwitchToNotifierGroup(size_t index) {
- active_item_index_ = index;
-}
-
-const message_center::NotifierGroup&
-FakeNotifierSettingsProvider::GetActiveNotifierGroup() const {
- return *(items_[active_item_index_].group);
-}
-
-void FakeNotifierSettingsProvider::GetNotifierList(
- std::vector<Notifier*>* notifiers) {
- notifiers->clear();
- for (size_t i = 0; i < items_[active_item_index_].notifiers.size(); ++i)
- notifiers->push_back(items_[active_item_index_].notifiers[i]);
-}
-
-void FakeNotifierSettingsProvider::SetNotifierEnabled(const Notifier& notifier,
- bool enabled) {
- enabled_[&notifier] = enabled;
-}
-
-void FakeNotifierSettingsProvider::OnNotifierSettingsClosing() {
- closed_called_count_++;
-}
-
-bool FakeNotifierSettingsProvider::NotifierHasAdvancedSettings(
- const message_center::NotifierId& notifier_id) const {
- if (!notifier_id_with_settings_handler_)
- return false;
- return *notifier_id_with_settings_handler_ == notifier_id;
-}
-
-void FakeNotifierSettingsProvider::OnNotifierAdvancedSettingsRequested(
- const NotifierId& notifier_id,
- const std::string* notification_id) {
- notifier_settings_requested_count_++;
-}
-
-void FakeNotifierSettingsProvider::AddObserver(
- NotifierSettingsObserver* observer) {
-}
-
-void FakeNotifierSettingsProvider::RemoveObserver(
- NotifierSettingsObserver* observer) {
-}
-
-bool FakeNotifierSettingsProvider::WasEnabled(const Notifier& notifier) {
- return enabled_[&notifier];
-}
-
-void FakeNotifierSettingsProvider::AddGroup(
- NotifierGroup* group, const std::vector<Notifier*>& notifiers) {
- NotifierGroupItem item;
- item.group = group;
- item.notifiers = notifiers;
- items_.push_back(item);
-}
-
-void FakeNotifierSettingsProvider::SetNotifierHasAdvancedSettings(
- const NotifierId& notifier_id) {
- notifier_id_with_settings_handler_.reset(new NotifierId(notifier_id));
-}
-
-int FakeNotifierSettingsProvider::closed_called_count() {
- return closed_called_count_;
-}
-
-size_t FakeNotifierSettingsProvider::settings_requested_count() const {
- return notifier_settings_requested_count_;
-}
-
-} // namespace message_center
diff --git a/chromium/ui/message_center/fake_notifier_settings_provider.h b/chromium/ui/message_center/fake_notifier_settings_provider.h
deleted file mode 100644
index eefb208df12..00000000000
--- a/chromium/ui/message_center/fake_notifier_settings_provider.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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_FAKE_NOTIFIER_SETTINGS_PROVIDER_H_
-#define UI_MESSAGE_CENTER_FAKE_NOTIFIER_SETTINGS_PROVIDER_H_
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "ui/message_center/notifier_settings.h"
-
-namespace message_center {
-
-// A NotifierSettingsProvider that returns a configurable, fixed set of
-// notifiers and records which callbacks were called. For use in tests.
-class FakeNotifierSettingsProvider : public NotifierSettingsProvider {
- public:
- FakeNotifierSettingsProvider();
- explicit FakeNotifierSettingsProvider(
- const std::vector<Notifier*>& notifiers);
- ~FakeNotifierSettingsProvider() override;
-
- size_t GetNotifierGroupCount() const override;
- const NotifierGroup& GetNotifierGroupAt(size_t index) const override;
- bool IsNotifierGroupActiveAt(size_t index) const override;
- void SwitchToNotifierGroup(size_t index) override;
- const NotifierGroup& GetActiveNotifierGroup() const override;
-
- void GetNotifierList(std::vector<Notifier*>* notifiers) override;
-
- void SetNotifierEnabled(const Notifier& notifier, bool enabled) override;
-
- void OnNotifierSettingsClosing() override;
- bool NotifierHasAdvancedSettings(
- const NotifierId& notifier_id) const override;
- void OnNotifierAdvancedSettingsRequested(
- const NotifierId& notifier_id,
- const std::string* notification_id) override;
- void AddObserver(NotifierSettingsObserver* observer) override;
- void RemoveObserver(NotifierSettingsObserver* observer) override;
-
- bool WasEnabled(const Notifier& notifier);
- int closed_called_count();
-
- void AddGroup(NotifierGroup* group, const std::vector<Notifier*>& notifiers);
-
- // For testing, this method can be used to specify a notifier that has a learn
- // more button. This class only saves the last one that was set.
- void SetNotifierHasAdvancedSettings(const NotifierId& notifier_id);
- size_t settings_requested_count() const;
-
- private:
- struct NotifierGroupItem {
- NotifierGroup* group;
- std::vector<Notifier*> notifiers;
-
- NotifierGroupItem();
- NotifierGroupItem(const NotifierGroupItem& other);
- ~NotifierGroupItem();
- };
-
- std::map<const Notifier*, bool> enabled_;
- std::vector<NotifierGroupItem> items_;
- int closed_called_count_;
- size_t active_item_index_;
- std::unique_ptr<NotifierId> notifier_id_with_settings_handler_;
- size_t notifier_settings_requested_count_;
-};
-
-} // namespace message_center
-
-#endif // UI_MESSAGE_CENTER_FAKE_NOTIFIER_SETTINGS_PROVIDER_H_
diff --git a/chromium/ui/message_center/mojo/notification.mojom b/chromium/ui/message_center/mojo/notification.mojom
index ce67c17517e..a9651b3eec6 100644
--- a/chromium/ui/message_center/mojo/notification.mojom
+++ b/chromium/ui/message_center/mojo/notification.mojom
@@ -4,7 +4,7 @@
module message_center.mojom;
-import "mojo/common/common_custom_types.mojom";
+import "mojo/common/string16.mojom";
import "skia/public/interfaces/bitmap.mojom";
import "url/mojo/url.mojom";
diff --git a/chromium/ui/message_center/notification_delegate.h b/chromium/ui/message_center/notification_delegate.h
index a493c18e252..b9432fb12bc 100644
--- a/chromium/ui/message_center/notification_delegate.h
+++ b/chromium/ui/message_center/notification_delegate.h
@@ -15,9 +15,7 @@
#include "ui/message_center/message_center_export.h"
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
-namespace views {
-class View;
-}
+#include "ui/message_center/views/custom_notification_content_view_delegate.h"
#endif
namespace message_center {
@@ -59,7 +57,7 @@ class MESSAGE_CENTER_EXPORT NotificationDelegate
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
// To be called to construct the contents view of a popup for notifications
// whose type is NOTIFICATION_TYPE_CUSTOM.
- virtual std::unique_ptr<views::View> CreateCustomContent();
+ virtual std::unique_ptr<CustomContent> CreateCustomContent();
#endif
// Indicates whether this notification should be displayed when there is
diff --git a/chromium/ui/message_center/notification_delegate_views.cc b/chromium/ui/message_center/notification_delegate_views.cc
index 6f993d2c640..1d12a307f08 100644
--- a/chromium/ui/message_center/notification_delegate_views.cc
+++ b/chromium/ui/message_center/notification_delegate_views.cc
@@ -8,8 +8,8 @@
namespace message_center {
-std::unique_ptr<views::View> NotificationDelegate::CreateCustomContent() {
- return std::unique_ptr<views::View>();
+std::unique_ptr<CustomContent> NotificationDelegate::CreateCustomContent() {
+ return nullptr;
}
} // namespace message_center
diff --git a/chromium/ui/message_center/notifier_settings.h b/chromium/ui/message_center/notifier_settings.h
index 9bbb87ab9ef..5e4c7a1c28c 100644
--- a/chromium/ui/message_center/notifier_settings.h
+++ b/chromium/ui/message_center/notifier_settings.h
@@ -178,9 +178,9 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsProvider {
virtual const message_center::NotifierGroup& GetActiveNotifierGroup()
const = 0;
- // Collects the current notifier list and fills to |notifiers|. Caller takes
- // the ownership of the elements of |notifiers|.
- virtual void GetNotifierList(std::vector<Notifier*>* notifiers) = 0;
+ // Provides the current notifier list in |notifiers|.
+ virtual void GetNotifierList(
+ std::vector<std::unique_ptr<Notifier>>* notifiers) = 0;
// Called when the |enabled| for the |notifier| has been changed by user
// operation.
diff --git a/chromium/ui/message_center/views/custom_notification_content_view_delegate.cc b/chromium/ui/message_center/views/custom_notification_content_view_delegate.cc
new file mode 100644
index 00000000000..a3ee7cdc76b
--- /dev/null
+++ b/chromium/ui/message_center/views/custom_notification_content_view_delegate.cc
@@ -0,0 +1,18 @@
+// Copyright 2016 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/views/custom_notification_content_view_delegate.h"
+
+#include "ui/views/view.h"
+
+namespace message_center {
+
+CustomContent::CustomContent(
+ std::unique_ptr<views::View> view,
+ std::unique_ptr<CustomNotificationContentViewDelegate> delegate)
+ : view(std::move(view)), delegate(std::move(delegate)) {}
+
+CustomContent::~CustomContent() {}
+
+} // namespace message_center
diff --git a/chromium/ui/message_center/views/custom_notification_content_view_delegate.h b/chromium/ui/message_center/views/custom_notification_content_view_delegate.h
new file mode 100644
index 00000000000..fbbcc68f0aa
--- /dev/null
+++ b/chromium/ui/message_center/views/custom_notification_content_view_delegate.h
@@ -0,0 +1,45 @@
+// Copyright 2016 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_CUSTOM_NOTIFICATION_CONTENT_VIEW_DELEGATE_H_
+#define UI_MESSAGE_CENTER_CUSTOM_NOTIFICATION_CONTENT_VIEW_DELEGATE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "ui/message_center/message_center_export.h"
+
+namespace views {
+class View;
+} // namespace views
+
+namespace message_center {
+
+// Delegate for a view that is hosted by CustomNotificationView.
+class MESSAGE_CENTER_EXPORT CustomNotificationContentViewDelegate {
+ public:
+ virtual bool IsCloseButtonFocused() const = 0;
+ virtual void RequestFocusOnCloseButton() = 0;
+ virtual bool IsPinned() const = 0;
+};
+
+// The struct to hold a view and CustomNotificationContentViewDelegate
+// associating with the view.
+struct MESSAGE_CENTER_EXPORT CustomContent {
+ public:
+ CustomContent(
+ std::unique_ptr<views::View> view,
+ std::unique_ptr<CustomNotificationContentViewDelegate> delegate);
+ ~CustomContent();
+
+ std::unique_ptr<views::View> view;
+ std::unique_ptr<CustomNotificationContentViewDelegate> delegate;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CustomContent);
+};
+
+} // namespace message_center
+
+#endif // UI_MESSAGE_CENTER_CUSTOM_NOTIFICATION_CONTENT_VIEW_DELEGATE_H_
diff --git a/chromium/ui/message_center/views/custom_notification_view.cc b/chromium/ui/message_center/views/custom_notification_view.cc
index b3528679e22..91b894673e9 100644
--- a/chromium/ui/message_center/views/custom_notification_view.cc
+++ b/chromium/ui/message_center/views/custom_notification_view.cc
@@ -11,6 +11,7 @@
#include "ui/views/background.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h"
+#include "ui/views/painter.h"
namespace message_center {
@@ -20,10 +21,15 @@ CustomNotificationView::CustomNotificationView(
: MessageView(controller, notification) {
DCHECK_EQ(NOTIFICATION_TYPE_CUSTOM, notification.type());
- contents_view_ = notification.delegate()->CreateCustomContent().release();
+ auto custom_content = notification.delegate()->CreateCustomContent();
+
+ contents_view_ = custom_content->view.release();
DCHECK(contents_view_);
AddChildView(contents_view_);
+ contents_view_delegate_ = std::move(custom_content->delegate);
+ DCHECK(contents_view_delegate_);
+
if (contents_view_->background()) {
background_view()->background()->SetNativeControlColor(
contents_view_->background()->get_color());
@@ -31,11 +37,20 @@ CustomNotificationView::CustomNotificationView(
AddChildView(small_image());
- CreateOrUpdateCloseButtonView(notification);
+ focus_painter_ = views::Painter::CreateSolidFocusPainter(
+ kFocusBorderColor, gfx::Insets(0, 1, 3, 2));
}
CustomNotificationView::~CustomNotificationView() {}
+void CustomNotificationView::OnContentFocused() {
+ SchedulePaint();
+}
+
+void CustomNotificationView::OnContentBlured() {
+ SchedulePaint();
+}
+
void CustomNotificationView::SetDrawBackgroundAsActive(bool active) {
// Do nothing if |contents_view_| has a background.
if (contents_view_->background())
@@ -44,6 +59,23 @@ void CustomNotificationView::SetDrawBackgroundAsActive(bool active) {
MessageView::SetDrawBackgroundAsActive(active);
}
+bool CustomNotificationView::IsCloseButtonFocused() const {
+ if (!contents_view_delegate_)
+ return false;
+ return contents_view_delegate_->IsCloseButtonFocused();
+}
+
+void CustomNotificationView::RequestFocusOnCloseButton() {
+ if (contents_view_delegate_)
+ contents_view_delegate_->RequestFocusOnCloseButton();
+}
+
+bool CustomNotificationView::IsPinned() const {
+ if (!contents_view_delegate_)
+ return false;
+ return contents_view_delegate_->IsPinned();
+}
+
gfx::Size CustomNotificationView::GetPreferredSize() const {
const gfx::Insets insets = GetInsets();
const int contents_width = kNotificationWidth - insets.width();
@@ -61,6 +93,33 @@ void CustomNotificationView::Layout() {
MessageView::Layout();
contents_view_->SetBoundsRect(GetContentsBounds());
+
+ // If the content view claims focus, defer focus handling to the content view.
+ if (contents_view_->IsFocusable())
+ SetFocusBehavior(FocusBehavior::NEVER);
+}
+
+bool CustomNotificationView::HasFocus() const {
+ // In case that focus handling is defered to the content view, asking the
+ // content view about focus.
+ if (contents_view_ && contents_view_->IsFocusable())
+ return contents_view_->HasFocus();
+ else
+ return MessageView::HasFocus();
+}
+
+void CustomNotificationView::RequestFocus() {
+ if (contents_view_ && contents_view_->IsFocusable())
+ contents_view_->RequestFocus();
+ else
+ MessageView::RequestFocus();
+}
+
+void CustomNotificationView::OnPaint(gfx::Canvas* canvas) {
+ MessageView::OnPaint(canvas);
+ if (contents_view_ && contents_view_->IsFocusable())
+ views::Painter::PaintFocusPainter(contents_view_, canvas,
+ focus_painter_.get());
}
} // namespace message_center
diff --git a/chromium/ui/message_center/views/custom_notification_view.h b/chromium/ui/message_center/views/custom_notification_view.h
index 8a5ab622dee..ff9d2a7240f 100644
--- a/chromium/ui/message_center/views/custom_notification_view.h
+++ b/chromium/ui/message_center/views/custom_notification_view.h
@@ -9,6 +9,10 @@
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/views/message_view.h"
+namespace views {
+class Painter;
+}
+
namespace message_center {
// View for notification with NOTIFICATION_TYPE_CUSTOM that hosts the custom
@@ -19,18 +23,33 @@ class MESSAGE_CENTER_EXPORT CustomNotificationView : public MessageView {
const Notification& notification);
~CustomNotificationView() override;
+ // These method are called by the content view when focus handling is defered
+ // to the content.
+ void OnContentFocused();
+ void OnContentBlured();
+
// Overidden from MessageView:
void SetDrawBackgroundAsActive(bool active) override;
+ bool IsCloseButtonFocused() const override;
+ void RequestFocusOnCloseButton() override;
+ bool IsPinned() const override;
// Overridden from views::View:
gfx::Size GetPreferredSize() const override;
void Layout() override;
+ bool HasFocus() const override;
+ void RequestFocus() override;
+ void OnPaint(gfx::Canvas* canvas) override;
private:
friend class CustomNotificationViewTest;
// The view for the custom content. Owned by view hierarchy.
views::View* contents_view_ = nullptr;
+ std::unique_ptr<CustomNotificationContentViewDelegate>
+ contents_view_delegate_;
+
+ std::unique_ptr<views::Painter> focus_painter_;
DISALLOW_COPY_AND_ASSIGN(CustomNotificationView);
};
diff --git a/chromium/ui/message_center/views/custom_notification_view_unittest.cc b/chromium/ui/message_center/views/custom_notification_view_unittest.cc
index a5d87f41846..1e5e2713d3d 100644
--- a/chromium/ui/message_center/views/custom_notification_view_unittest.cc
+++ b/chromium/ui/message_center/views/custom_notification_view_unittest.cc
@@ -26,6 +26,21 @@ namespace {
const SkColor kBackgroundColor = SK_ColorGREEN;
+std::unique_ptr<ui::GestureEvent> GenerateGestureEvent(ui::EventType type) {
+ ui::GestureEventDetails detail(type);
+ std::unique_ptr<ui::GestureEvent> event(
+ new ui::GestureEvent(0, 0, 0, base::TimeTicks(), detail));
+ return event;
+}
+
+std::unique_ptr<ui::GestureEvent> GenerateGestureHorizontalScrollUpdateEvent(
+ int dx) {
+ ui::GestureEventDetails detail(ui::ET_GESTURE_SCROLL_UPDATE, dx, 0);
+ std::unique_ptr<ui::GestureEvent> event(
+ new ui::GestureEvent(0, 0, 0, base::TimeTicks(), detail));
+ return event;
+}
+
class TestCustomView : public views::View {
public:
TestCustomView() {
@@ -66,13 +81,22 @@ class TestCustomView : public views::View {
DISALLOW_COPY_AND_ASSIGN(TestCustomView);
};
+class TestContentViewDelegate : public CustomNotificationContentViewDelegate {
+ public:
+ bool IsCloseButtonFocused() const override { return false; }
+ void RequestFocusOnCloseButton() override {}
+ bool IsPinned() const override { return false; }
+};
+
class TestNotificationDelegate : public NotificationDelegate {
public:
TestNotificationDelegate() {}
// NotificateDelegate
- std::unique_ptr<views::View> CreateCustomContent() override {
- return base::WrapUnique(new TestCustomView);
+ std::unique_ptr<CustomContent> CreateCustomContent() override {
+ return base::MakeUnique<CustomContent>(
+ base::MakeUnique<TestCustomView>(),
+ base::MakeUnique<TestContentViewDelegate>());
}
private:
@@ -187,15 +211,23 @@ class CustomNotificationViewTest : public views::ViewsTestBase {
widget()->OnKeyEvent(&event);
}
- views::ImageButton* close_button() {
- return notification_view_->close_button();
+ void UpdateNotificationViews() {
+ notification_view()->UpdateWithNotification(*notification());
}
+
+ float GetNotificationScrollAmount() const {
+ return notification_view_->GetTransform().To2dTranslation().x();
+ }
+
TestMessageCenterController* controller() { return &controller_; }
Notification* notification() { return notification_.get(); }
TestCustomView* custom_view() {
return static_cast<TestCustomView*>(notification_view_->contents_view_);
}
views::Widget* widget() { return notification_view_->GetWidget(); }
+ CustomNotificationView* notification_view() {
+ return notification_view_.get();
+ }
private:
TestMessageCenterController controller_;
@@ -210,15 +242,6 @@ TEST_F(CustomNotificationViewTest, Background) {
EXPECT_EQ(kBackgroundColor, GetBackgroundColor());
}
-TEST_F(CustomNotificationViewTest, ClickCloseButton) {
- widget()->Show();
-
- gfx::Point cursor_location(1, 1);
- views::View::ConvertPointToWidget(close_button(), &cursor_location);
- PerformClick(cursor_location);
- EXPECT_TRUE(controller()->IsRemoved(notification()->id()));
-}
-
TEST_F(CustomNotificationViewTest, Events) {
widget()->Show();
custom_view()->RequestFocus();
@@ -239,4 +262,51 @@ TEST_F(CustomNotificationViewTest, Events) {
EXPECT_EQ(1, custom_view()->keyboard_event_count());
}
+TEST_F(CustomNotificationViewTest, SlideOut) {
+ UpdateNotificationViews();
+ std::string notification_id = notification()->id();
+
+ auto event_begin = GenerateGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN);
+ auto event_scroll10 = GenerateGestureHorizontalScrollUpdateEvent(-10);
+ auto event_scroll500 = GenerateGestureHorizontalScrollUpdateEvent(-500);
+ auto event_end = GenerateGestureEvent(ui::ET_GESTURE_SCROLL_END);
+
+ notification_view()->OnGestureEvent(event_begin.get());
+ notification_view()->OnGestureEvent(event_scroll10.get());
+ EXPECT_FALSE(controller()->IsRemoved(notification_id));
+ EXPECT_EQ(-10.f, GetNotificationScrollAmount());
+ notification_view()->OnGestureEvent(event_end.get());
+ EXPECT_FALSE(controller()->IsRemoved(notification_id));
+ EXPECT_EQ(0.f, GetNotificationScrollAmount());
+
+ notification_view()->OnGestureEvent(event_begin.get());
+ notification_view()->OnGestureEvent(event_scroll500.get());
+ EXPECT_FALSE(controller()->IsRemoved(notification_id));
+ EXPECT_EQ(-500.f, GetNotificationScrollAmount());
+ notification_view()->OnGestureEvent(event_end.get());
+ EXPECT_TRUE(controller()->IsRemoved(notification_id));
+}
+
+// Pinning notification is ChromeOS only feature.
+#if defined(OS_CHROMEOS)
+
+TEST_F(CustomNotificationViewTest, SlideOutPinned) {
+ notification()->set_pinned(true);
+ UpdateNotificationViews();
+ std::string notification_id = notification()->id();
+
+ auto event_begin = GenerateGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN);
+ auto event_scroll500 = GenerateGestureHorizontalScrollUpdateEvent(-500);
+ auto event_end = GenerateGestureEvent(ui::ET_GESTURE_SCROLL_END);
+
+ notification_view()->OnGestureEvent(event_begin.get());
+ notification_view()->OnGestureEvent(event_scroll500.get());
+ EXPECT_FALSE(controller()->IsRemoved(notification_id));
+ EXPECT_LT(-500.f, GetNotificationScrollAmount());
+ notification_view()->OnGestureEvent(event_end.get());
+ EXPECT_FALSE(controller()->IsRemoved(notification_id));
+}
+
+#endif // defined(OS_CHROMEOS)
+
} // namespace message_center
diff --git a/chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc b/chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc
index 1c32a1eb1e2..d6e7ff8f131 100644
--- a/chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc
+++ b/chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc
@@ -14,7 +14,7 @@ namespace message_center {
DesktopPopupAlignmentDelegate::DesktopPopupAlignmentDelegate()
: alignment_(POPUP_ALIGNMENT_BOTTOM | POPUP_ALIGNMENT_RIGHT),
- primary_display_id_(display::Display::kInvalidDisplayID),
+ primary_display_id_(display::kInvalidDisplayId),
screen_(NULL) {}
DesktopPopupAlignmentDelegate::~DesktopPopupAlignmentDelegate() {
@@ -119,9 +119,9 @@ void DesktopPopupAlignmentDelegate::OnDisplayRemoved(
void DesktopPopupAlignmentDelegate::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t metrics) {
- // Set to kInvalidDisplayID so the alignment is updated regardless of whether
+ // Set to kInvalidDisplayId so the alignment is updated regardless of whether
// the primary display actually changed.
- primary_display_id_ = display::Display::kInvalidDisplayID;
+ primary_display_id_ = display::kInvalidDisplayId;
UpdatePrimaryDisplay();
}
diff --git a/chromium/ui/message_center/views/message_center_bubble.cc b/chromium/ui/message_center/views/message_center_bubble.cc
index c135b2178a8..e340ca3f840 100644
--- a/chromium/ui/message_center/views/message_center_bubble.cc
+++ b/chromium/ui/message_center/views/message_center_bubble.cc
@@ -95,9 +95,7 @@ void MessageCenterBubble::InitializeContents(
set_bubble_view(new_bubble_view);
bubble_view()->GetWidget()->AddObserver(this);
message_center_view_ = new MessageCenterView(
- message_center(), tray(), max_height(), initially_settings_visible_,
- false); /* MessageCenterBubble should be used only on ChromeOS.
- Message center is never shown top down in ChromeOS. */
+ message_center(), tray(), max_height(), initially_settings_visible_);
bubble_view()->AddChildView(new ContentsView(this, message_center_view_));
// Resize the content of the bubble view to the given bubble size. This is
// necessary in case of the bubble border forcing a bigger size then the
diff --git a/chromium/ui/message_center/views/message_center_button_bar.cc b/chromium/ui/message_center/views/message_center_button_bar.cc
index fb86d939ed5..5f89a6a5a28 100644
--- a/chromium/ui/message_center/views/message_center_button_bar.cc
+++ b/chromium/ui/message_center/views/message_center_button_bar.cc
@@ -68,9 +68,9 @@ NotificationCenterButton::NotificationCenterButton(
int text_id)
: views::ToggleImageButton(listener), size_(kButtonSize, kButtonSize) {
ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
- SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_id));
- SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hover_id));
- SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pressed_id));
+ SetImage(STATE_NORMAL, *resource_bundle.GetImageSkiaNamed(normal_id));
+ SetImage(STATE_HOVERED, *resource_bundle.GetImageSkiaNamed(hover_id));
+ SetImage(STATE_PRESSED, *resource_bundle.GetImageSkiaNamed(pressed_id));
SetImageAlignment(views::ImageButton::ALIGN_CENTER,
views::ImageButton::ALIGN_MIDDLE);
if (text_id)
@@ -159,7 +159,7 @@ MessageCenterButtonBar::MessageCenterButtonBar(
IDS_MESSAGE_CENTER_CLEAR_ALL);
close_all_button_->SetImage(
views::Button::STATE_DISABLED,
- resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED));
+ *resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED));
button_container_->AddChildView(close_all_button_);
settings_button_ =
diff --git a/chromium/ui/message_center/views/message_center_view.cc b/chromium/ui/message_center/views/message_center_view.cc
index b95ebf55edd..a16898da43f 100644
--- a/chromium/ui/message_center/views/message_center_view.cc
+++ b/chromium/ui/message_center/views/message_center_view.cc
@@ -62,14 +62,12 @@ void SetViewHierarchyEnabled(views::View* view, bool enabled) {
MessageCenterView::MessageCenterView(MessageCenter* message_center,
MessageCenterTray* tray,
int max_height,
- bool initially_settings_visible,
- bool top_down)
+ bool initially_settings_visible)
: message_center_(message_center),
tray_(tray),
scroller_(NULL),
settings_view_(NULL),
button_bar_(NULL),
- top_down_(top_down),
settings_visible_(initially_settings_visible),
source_view_(NULL),
source_height_(0),
@@ -97,6 +95,7 @@ MessageCenterView::MessageCenterView(MessageCenter* message_center,
scroller_ = new views::ScrollView();
scroller_->ClipHeightTo(kMinScrollViewHeight, max_height - button_height);
scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false));
+ scroller_->SetHorizontalScrollBar(new views::OverlayScrollBar(true));
scroller_->set_background(
views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
@@ -104,8 +103,9 @@ MessageCenterView::MessageCenterView(MessageCenter* message_center,
scroller_->layer()->SetFillsBoundsOpaquely(false);
scroller_->layer()->SetMasksToBounds(true);
- message_list_view_.reset(new MessageListView(this, top_down));
+ message_list_view_.reset(new MessageListView());
message_list_view_->set_owned_by_client();
+ message_list_view_->AddObserver(this);
// We want to swap the contents of the scroll view between the empty list
// view and the message list view, without constructing them afresh each
@@ -129,6 +129,8 @@ MessageCenterView::MessageCenterView(MessageCenter* message_center,
}
MessageCenterView::~MessageCenterView() {
+ message_list_view_->RemoveObserver(this);
+
if (!is_closing_)
message_center_->RemoveObserver(this);
}
@@ -212,19 +214,16 @@ void MessageCenterView::Layout() {
bool animating = settings_transition_animation_ &&
settings_transition_animation_->is_animating();
if (animating && settings_transition_animation_->current_part_index() == 0) {
- if (!top_down_) {
- button_bar_->SetBounds(
- 0, height() - button_height, width(), button_height);
- }
+ button_bar_->SetBounds(0, height() - button_height, width(), button_height);
return;
}
scroller_->SetBounds(0,
- top_down_ ? button_height : 0,
+ 0,
width(),
height() - button_height);
settings_view_->SetBounds(0,
- top_down_ ? button_height : 0,
+ 0,
width(),
height() - button_height);
@@ -239,15 +238,15 @@ void MessageCenterView::Layout() {
// Draw separator line on the top of the button bar if it is on the bottom
// or draw it at the bottom if the bar is on the top.
button_bar_->SetBorder(views::CreateSolidSidedBorder(
- top_down_ ? 0 : 1, 0, top_down_ ? 1 : 0, 0, kFooterDelimiterColor));
+ 1, 0, 0, 0, kFooterDelimiterColor));
} else {
button_bar_->SetBorder(
- views::CreateEmptyBorder(top_down_ ? 0 : 1, 0, top_down_ ? 1 : 0, 0));
+ views::CreateEmptyBorder(1, 0, 0, 0));
}
button_bar_->SchedulePaint();
}
button_bar_->SetBounds(0,
- top_down_ ? 0 : height() - button_height,
+ height() - button_height,
width(),
button_height);
if (GetWidget())
@@ -344,8 +343,7 @@ void MessageCenterView::OnNotificationRemoved(const std::string& id,
// Moves the keyboard focus to the next notification if the removed
// notification is focused so that the user can dismiss notifications
// without re-focusing by tab key.
- if (view->IsCloseButtonFocused() ||
- view == GetFocusManager()->GetFocusedView()) {
+ if (view->IsCloseButtonFocused() || view->HasFocus()) {
views::View* next_focused_view = NULL;
if (message_list_view_->child_count() > index + 1)
next_focused_view = message_list_view_->child_at(index + 1);
diff --git a/chromium/ui/message_center/views/message_center_view.h b/chromium/ui/message_center/views/message_center_view.h
index 843a08064c1..212500e78bd 100644
--- a/chromium/ui/message_center/views/message_center_view.h
+++ b/chromium/ui/message_center/views/message_center_view.h
@@ -13,6 +13,7 @@
#include "ui/message_center/message_center_observer.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/views/message_center_controller.h"
+#include "ui/message_center/views/message_list_view.h"
#include "ui/message_center/views/message_view.h"
#include "ui/views/view.h"
@@ -34,22 +35,22 @@ class NotifierSettingsView;
// button bar, settings view, scrol view, and message list view. Acts as a
// controller for the message list view, passing data back and forth to message
// center.
-class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View,
- public MessageCenterObserver,
- public MessageCenterController,
- public gfx::AnimationDelegate {
+class MESSAGE_CENTER_EXPORT MessageCenterView
+ : public views::View,
+ public MessageCenterObserver,
+ public MessageCenterController,
+ public MessageListView::Observer,
+ public gfx::AnimationDelegate {
public:
MessageCenterView(MessageCenter* message_center,
MessageCenterTray* tray,
int max_height,
- bool initially_settings_visible,
- bool top_down);
+ bool initially_settings_visible);
~MessageCenterView() override;
void SetNotifications(const NotificationList::Notifications& notifications);
void ClearAllClosableNotifications();
- void OnAllNotificationsCleared();
size_t NumMessageViewsForTest() const;
@@ -86,6 +87,9 @@ class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View,
int button_index) override;
void ClickOnSettingsButton(const std::string& notification_id) override;
+ // Overridden from MessageListView::Observer:
+ void OnAllNotificationsCleared() override;
+
// Overridden from gfx::AnimationDelegate:
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationProgressed(const gfx::Animation* animation) override;
@@ -118,7 +122,6 @@ class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View,
std::unique_ptr<MessageListView> message_list_view_;
NotifierSettingsView* settings_view_;
MessageCenterButtonBar* button_bar_;
- bool top_down_;
// Data for transition animation between settings view and message list.
bool settings_visible_;
diff --git a/chromium/ui/message_center/views/message_center_view_unittest.cc b/chromium/ui/message_center/views/message_center_view_unittest.cc
index 2ccdbb70756..5a16ecd1c86 100644
--- a/chromium/ui/message_center/views/message_center_view_unittest.cc
+++ b/chromium/ui/message_center/views/message_center_view_unittest.cc
@@ -215,7 +215,7 @@ void MessageCenterViewTest::SetUp() {
// Then create a new MessageCenterView with that single notification.
message_center_view_.reset(new MessageCenterView(
- message_center_.get(), NULL, 100, false, /*top_down =*/false));
+ message_center_.get(), NULL, 100, false));
GetMessageListView()->quit_message_loop_after_animation_for_test_ = true;
GetMessageCenterView()->SetBounds(0, 0, 380, 600);
message_center_view_->SetNotifications(notifications);
diff --git a/chromium/ui/message_center/views/message_list_view.cc b/chromium/ui/message_center/views/message_list_view.cc
index a5f2a70a2fd..0c0d6bf4ef5 100644
--- a/chromium/ui/message_center/views/message_list_view.cc
+++ b/chromium/ui/message_center/views/message_list_view.cc
@@ -23,14 +23,11 @@ namespace {
const int kAnimateClearingNextNotificationDelayMS = 40;
} // namespace
-MessageListView::MessageListView(MessageCenterView* message_center_view,
- bool top_down)
- : message_center_view_(message_center_view),
- reposition_top_(-1),
+MessageListView::MessageListView()
+ : reposition_top_(-1),
fixed_height_(0),
has_deferred_task_(false),
clear_all_started_(false),
- top_down_(top_down),
animator_(this),
quit_message_loop_after_animation_for_test_(false),
weak_ptr_factory_(this) {
@@ -47,9 +44,9 @@ MessageListView::MessageListView(MessageCenterView* message_center_view,
set_background(
views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
SetBorder(views::CreateEmptyBorder(
- top_down ? 0 : kMarginBetweenItems - shadow_insets.top(), /* top */
- kMarginBetweenItems - shadow_insets.left(), /* left */
- top_down ? kMarginBetweenItems - shadow_insets.bottom() : 0, /* bottom */
+ kMarginBetweenItems - shadow_insets.top(), /* top */
+ kMarginBetweenItems - shadow_insets.left(), /* left */
+ 0, /* bottom */
kMarginBetweenItems - shadow_insets.right() /* right */));
animator_.AddObserver(this);
}
@@ -102,13 +99,19 @@ void MessageListView::AddNotificationAt(MessageView* view, int index) {
void MessageListView::RemoveNotification(MessageView* view) {
DCHECK_EQ(view->parent(), this);
+
+
if (GetContentsBounds().IsEmpty()) {
delete view;
} else {
+ if (adding_views_.find(view) != adding_views_.end())
+ adding_views_.erase(view);
+ if (animator_.IsAnimating(view))
+ animator_.StopAnimatingView(view);
+
if (view->layer()) {
deleting_views_.insert(view);
} else {
- animator_.StopAnimatingView(view);
delete view;
}
DoUpdateIfPossible();
@@ -209,12 +212,21 @@ void MessageListView::ClearAllClosableNotifications(
clearing_all_views_.push_back(child);
}
if (clearing_all_views_.empty()) {
- message_center_view()->OnAllNotificationsCleared();
+ for (auto& observer : observers_)
+ observer.OnAllNotificationsCleared();
} else {
DoUpdateIfPossible();
}
}
+void MessageListView::AddObserver(MessageListView::Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void MessageListView::RemoveObserver(MessageListView::Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
void MessageListView::OnBoundsAnimatorProgressed(
views::BoundsAnimator* animator) {
DCHECK_EQ(&animator_, animator);
@@ -232,7 +244,8 @@ void MessageListView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
if (clear_all_started_) {
clear_all_started_ = false;
- message_center_view()->OnAllNotificationsCleared();
+ for (auto& observer : observers_)
+ observer.OnAllNotificationsCleared();
}
if (has_deferred_task_) {
@@ -273,8 +286,7 @@ void MessageListView::DoUpdateIfPossible() {
int new_height = GetHeightForWidth(child_area.width() + GetInsets().width());
SetSize(gfx::Size(child_area.width() + GetInsets().width(), new_height));
- if (top_down_ ||
- base::CommandLine::ForCurrentProcess()->HasSwitch(
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableMessageCenterAlwaysScrollUpUponNotificationRemoval))
AnimateNotificationsBelowTarget();
else
@@ -436,7 +448,7 @@ bool MessageListView::AnimateChild(views::View* child,
return false;
} else {
gfx::Rect target(child_area.x(), top, child_area.width(), height);
- if (child->bounds().origin() != target.origin() && animate_on_move)
+ if (child->origin() != target.origin() && animate_on_move)
animator_.AnimateViewTo(child, target);
else
child->SetBoundsRect(target);
diff --git a/chromium/ui/message_center/views/message_list_view.h b/chromium/ui/message_center/views/message_list_view.h
index 0f381d3a5ff..e71bc8f4e0a 100644
--- a/chromium/ui/message_center/views/message_list_view.h
+++ b/chromium/ui/message_center/views/message_list_view.h
@@ -24,17 +24,21 @@ class Layer;
namespace message_center {
-class MessageCenterView;
class MessageView;
// Displays a list of messages for rich notifications. Functions as an array of
// MessageViews and animates them on transitions. It also supports
// repositioning.
-class MessageListView : public views::View,
- public views::BoundsAnimatorObserver {
+class MESSAGE_CENTER_EXPORT MessageListView
+ : public views::View,
+ public views::BoundsAnimatorObserver {
public:
- explicit MessageListView(MessageCenterView* message_center_view,
- bool top_down);
+ class Observer {
+ public:
+ virtual void OnAllNotificationsCleared() = 0;
+ };
+
+ MessageListView();
~MessageListView() override;
void AddNotificationAt(MessageView* view, int i);
@@ -44,7 +48,10 @@ class MessageListView : public views::View,
void ResetRepositionSession();
void ClearAllClosableNotifications(const gfx::Rect& visible_scroll_rect);
- MESSAGE_CENTER_EXPORT void SetRepositionTargetForTest(
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ void SetRepositionTargetForTest(
const gfx::Rect& target_rect);
protected:
@@ -61,6 +68,7 @@ class MessageListView : public views::View,
private:
friend class MessageCenterViewTest;
+ friend class MessageListViewTest;
bool IsValidChild(const views::View* child) const;
void DoUpdateIfPossible();
@@ -81,17 +89,15 @@ class MessageListView : public views::View,
// Animate clearing one notification.
void AnimateClearingOneNotification();
- MessageCenterView* message_center_view() const {
- return message_center_view_;
- }
- MessageCenterView* message_center_view_; // Weak reference.
+ // List of MessageListView::Observer
+ base::ObserverList<Observer> observers_;
+
// The top position of the reposition target rectangle.
int reposition_top_;
int fixed_height_;
bool has_deferred_task_;
bool clear_all_started_;
- bool top_down_;
std::set<views::View*> adding_views_;
std::set<views::View*> deleting_views_;
std::set<views::View*> deleted_when_done_;
@@ -107,4 +113,5 @@ class MessageListView : public views::View,
};
} // namespace message_center
+
#endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_LIST_VIEW_H_
diff --git a/chromium/ui/message_center/views/message_list_view_unittest.cc b/chromium/ui/message_center/views/message_list_view_unittest.cc
new file mode 100644
index 00000000000..a4dc8b12bd9
--- /dev/null
+++ b/chromium/ui/message_center/views/message_list_view_unittest.cc
@@ -0,0 +1,185 @@
+// Copyright 2016 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 <map>
+#include <memory>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/message_center/fake_message_center.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_list.h"
+#include "ui/message_center/views/message_center_controller.h"
+#include "ui/message_center/views/message_list_view.h"
+#include "ui/message_center/views/notification_view.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace message_center {
+
+static const char* kNotificationId1 = "notification id 1";
+
+namespace {
+
+/* Types **********************************************************************/
+
+enum CallType { GET_PREFERRED_SIZE, GET_HEIGHT_FOR_WIDTH, LAYOUT };
+
+/* Instrumented/Mock NotificationView subclass ********************************/
+
+class MockNotificationView : public NotificationView {
+ public:
+ class Test {
+ public:
+ virtual void RegisterCall(CallType type) = 0;
+ };
+
+ MockNotificationView(MessageCenterController* controller,
+ const Notification& notification,
+ Test* test);
+ ~MockNotificationView() override;
+
+ gfx::Size GetPreferredSize() const override;
+ int GetHeightForWidth(int w) const override;
+ void Layout() override;
+
+ private:
+ Test* test_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockNotificationView);
+};
+
+MockNotificationView::MockNotificationView(MessageCenterController* controller,
+ const Notification& notification,
+ Test* test)
+ : NotificationView(controller, notification), test_(test) {}
+
+MockNotificationView::~MockNotificationView() {}
+
+gfx::Size MockNotificationView::GetPreferredSize() const {
+ test_->RegisterCall(GET_PREFERRED_SIZE);
+ DCHECK(child_count() > 0);
+ return NotificationView::GetPreferredSize();
+}
+
+int MockNotificationView::GetHeightForWidth(int width) const {
+ test_->RegisterCall(GET_HEIGHT_FOR_WIDTH);
+ DCHECK(child_count() > 0);
+ return NotificationView::GetHeightForWidth(width);
+}
+
+void MockNotificationView::Layout() {
+ test_->RegisterCall(LAYOUT);
+ DCHECK(child_count() > 0);
+ NotificationView::Layout();
+}
+
+} // anonymous namespace
+
+/* Test fixture ***************************************************************/
+
+class MessageListViewTest : public views::ViewsTestBase,
+ public MockNotificationView::Test,
+ public MessageListView::Observer,
+ public MessageCenterController {
+ public:
+ MessageListViewTest() {}
+
+ ~MessageListViewTest() override {}
+
+ void SetUp() override {
+ views::ViewsTestBase::SetUp();
+
+ message_list_view_.reset(new MessageListView());
+ message_list_view_->AddObserver(this);
+ message_list_view_->set_owned_by_client();
+
+ widget_.reset(new views::Widget());
+ views::Widget::InitParams params =
+ CreateParams(views::Widget::InitParams::TYPE_POPUP);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(50, 50, 650, 650);
+ widget_->Init(params);
+ views::View* root = widget_->GetRootView();
+ root->AddChildView(message_list_view_.get());
+ widget_->Show();
+ widget_->Activate();
+ }
+
+ void TearDown() override {
+ widget_->CloseNow();
+ widget_.reset();
+
+ message_list_view_->RemoveObserver(this);
+ message_list_view_.reset();
+
+ views::ViewsTestBase::TearDown();
+ }
+
+ protected:
+ MessageListView* message_list_view() const {
+ return message_list_view_.get();
+ }
+
+ MockNotificationView* CreateNotificationView(
+ const Notification& notification) {
+ return new MockNotificationView(this, notification, this);
+ }
+
+ private:
+ // MockNotificationView::Test override
+ void RegisterCall(CallType type) override {}
+
+ // MessageListView::Observer override
+ void OnAllNotificationsCleared() override {}
+
+ // MessageCenterController override:
+ void ClickOnNotification(const std::string& notification_id) override {}
+ void RemoveNotification(const std::string& notification_id,
+ bool by_user) override {}
+ std::unique_ptr<ui::MenuModel> CreateMenuModel(
+ const NotifierId& notifier_id,
+ const base::string16& display_source) override {
+ NOTREACHED();
+ return nullptr;
+ }
+ bool HasClickedListener(const std::string& notification_id) override {
+ return false;
+ }
+ void ClickOnNotificationButton(const std::string& notification_id,
+ int button_index) override {}
+ void ClickOnSettingsButton(const std::string& notification_id) override {}
+
+ // Widget to host a MessageListView.
+ std::unique_ptr<views::Widget> widget_;
+ // MessageListView to be tested.
+ std::unique_ptr<MessageListView> message_list_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageListViewTest);
+};
+
+/* Unit tests *****************************************************************/
+
+TEST_F(MessageListViewTest, AddNotification) {
+ // Create a dummy notification.
+ auto notification_view = CreateNotificationView(
+ Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
+ base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"),
+ gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
+ NotifierId(NotifierId::APPLICATION, "extension_id"),
+ message_center::RichNotificationData(), nullptr));
+
+ EXPECT_EQ(0, message_list_view()->child_count());
+ EXPECT_FALSE(message_list_view()->Contains(notification_view));
+
+ // Add a notification.
+ message_list_view()->AddNotificationAt(notification_view, 0);
+
+ EXPECT_EQ(1, message_list_view()->child_count());
+ EXPECT_TRUE(message_list_view()->Contains(notification_view));
+}
+
+} // namespace
diff --git a/chromium/ui/message_center/views/message_popup_collection_unittest.cc b/chromium/ui/message_center/views/message_popup_collection_unittest.cc
index 5d62ad3ed48..d621d857c1f 100644
--- a/chromium/ui/message_center/views/message_popup_collection_unittest.cc
+++ b/chromium/ui/message_center/views/message_popup_collection_unittest.cc
@@ -11,6 +11,7 @@
#include <numeric>
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
diff --git a/chromium/ui/message_center/views/message_view.cc b/chromium/ui/message_center/views/message_view.cc
index 4031d01ad1b..d4fb66ceba7 100644
--- a/chromium/ui/message_center/views/message_view.cc
+++ b/chromium/ui/message_center/views/message_view.cc
@@ -10,28 +10,30 @@
#include "ui/base/models/simple_menu_model.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/shadow_util.h"
#include "ui/gfx/shadow_value.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/message_center_controller.h"
-#include "ui/message_center/views/padded_button.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/background.h"
+#include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/painter.h"
-#include "ui/views/shadow_border.h"
namespace {
-constexpr int kCloseIconTopPadding = 5;
-constexpr int kCloseIconRightPadding = 5;
-
-constexpr int kShadowOffset = 1;
-constexpr int kShadowBlur = 4;
+#if defined(OS_CHROMEOS)
+const int kShadowCornerRadius = 2;
+#else
+const int kShadowCornerRadius = 0;
+#endif
+const int kShadowElevation = 2;
// Creates a text for spoken feedback from the data contained in the
// notification.
@@ -62,8 +64,7 @@ MessageView::MessageView(MessageCenterController* controller,
const Notification& notification)
: controller_(controller),
notification_id_(notification.id()),
- notifier_id_(notification.notifier_id()),
- display_source_(notification.display_source()) {
+ notifier_id_(notification.notifier_id()) {
SetFocusBehavior(FocusBehavior::ALWAYS);
// Create the opaque background that's above the view's shadow.
@@ -73,7 +74,6 @@ MessageView::MessageView(MessageCenterController* controller,
AddChildView(background_view_);
views::ImageView* small_image_view = new views::ImageView();
- small_image_view->SetImage(notification.small_image().AsImageSkia());
small_image_view->SetImageSize(gfx::Size(kSmallImageSize, kSmallImageSize));
// The small image view should be added to view hierarchy by the derived
// class. This ensures that it is on top of other views.
@@ -83,7 +83,7 @@ MessageView::MessageView(MessageCenterController* controller,
focus_painter_ = views::Painter::CreateSolidFocusPainter(
kFocusBorderColor, gfx::Insets(0, 1, 3, 2));
- accessible_name_ = CreateAccessibleName(notification);
+ UpdateWithNotification(notification);
}
MessageView::~MessageView() {
@@ -92,40 +92,25 @@ MessageView::~MessageView() {
void MessageView::UpdateWithNotification(const Notification& notification) {
small_image_view_->SetImage(notification.small_image().AsImageSkia());
display_source_ = notification.display_source();
- CreateOrUpdateCloseButtonView(notification);
accessible_name_ = CreateAccessibleName(notification);
+ set_slide_out_enabled(!notification.pinned());
}
// static
gfx::Insets MessageView::GetShadowInsets() {
- return gfx::Insets(kShadowBlur / 2 - kShadowOffset,
- kShadowBlur / 2,
- kShadowBlur / 2 + kShadowOffset,
- kShadowBlur / 2);
+ return -gfx::ShadowValue::GetMargin(
+ gfx::ShadowDetails::Get(kShadowElevation, kShadowCornerRadius).values);
}
void MessageView::CreateShadowBorder() {
- SetBorder(std::unique_ptr<views::Border>(new views::ShadowBorder(
- gfx::ShadowValue(gfx::Vector2d(0, kShadowOffset), kShadowBlur,
- message_center::kShadowColor))));
-}
-
-bool MessageView::IsCloseButtonFocused() {
- if (!close_button_)
- return false;
-
- views::FocusManager* focus_manager = GetFocusManager();
- return focus_manager &&
- focus_manager->GetFocusedView() == close_button_.get();
-}
-
-void MessageView::RequestFocusOnCloseButton() {
- if (close_button_)
- close_button_->RequestFocus();
-}
-
-bool MessageView::IsPinned() {
- return !close_button_;
+ const auto& shadow =
+ gfx::ShadowDetails::Get(kShadowElevation, kShadowCornerRadius);
+ gfx::Insets ninebox_insets = gfx::ShadowValue::GetBlurRegion(shadow.values) +
+ gfx::Insets(kShadowCornerRadius);
+ SetBorder(views::CreateBorderPainter(
+ std::unique_ptr<views::Painter>(views::Painter::CreateImagePainter(
+ shadow.ninebox_image, ninebox_insets)),
+ -gfx::ShadowValue::GetMargin(shadow.values)));
}
void MessageView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
@@ -169,7 +154,6 @@ bool MessageView::OnKeyReleased(const ui::KeyEvent& event) {
void MessageView::OnPaint(gfx::Canvas* canvas) {
DCHECK_EQ(this, small_image_view_->parent());
- DCHECK_EQ(this, close_button_->parent());
SlideOutView::OnPaint(canvas);
views::Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
}
@@ -191,16 +175,15 @@ void MessageView::Layout() {
// Background.
background_view_->SetBoundsRect(content_bounds);
-
- // Close button.
- if (close_button_) {
- gfx::Rect content_bounds = GetContentsBounds();
- gfx::Size close_size(close_button_->GetPreferredSize());
- gfx::Rect close_rect(content_bounds.right() - close_size.width(),
- content_bounds.y(), close_size.width(),
- close_size.height());
- close_button_->SetBoundsRect(close_rect);
- }
+#if defined(OS_CHROMEOS)
+ // ChromeOS rounds the corners of the message view. TODO(estade): should we do
+ // this for all platforms?
+ gfx::Path path;
+ constexpr SkScalar kCornerRadius = SkIntToScalar(2);
+ path.addRoundRect(gfx::RectToSkRect(background_view_->GetLocalBounds()),
+ kCornerRadius, kCornerRadius);
+ background_view_->set_clip_path(path);
+#endif
gfx::Size small_image_size(small_image_view_->GetPreferredSize());
gfx::Rect small_image_rect(small_image_size);
@@ -246,13 +229,6 @@ void MessageView::OnGestureEvent(ui::GestureEvent* event) {
event->SetHandled();
}
-void MessageView::ButtonPressed(views::Button* sender,
- const ui::Event& event) {
- if (close_button_ && sender == close_button_.get()) {
- controller()->RemoveNotification(notification_id(), true); // By user.
- }
-}
-
void MessageView::OnSlideOut() {
controller_->RemoveNotification(notification_id_, true); // By user.
}
@@ -264,27 +240,4 @@ void MessageView::SetDrawBackgroundAsActive(bool active) {
SchedulePaint();
}
-void MessageView::CreateOrUpdateCloseButtonView(
- const Notification& notification) {
- set_slide_out_enabled(!notification.pinned());
-
- if (!notification.pinned() && !close_button_) {
- PaddedButton* close = new PaddedButton(this);
- close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding);
- close->SetNormalImage(IDR_NOTIFICATION_CLOSE);
- close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER);
- close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED);
- close->set_animate_on_state_change(false);
- close->SetAccessibleName(l10n_util::GetStringUTF16(
- IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
- close->SetTooltipText(l10n_util::GetStringUTF16(
- IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_TOOLTIP));
- close->set_owned_by_client();
- AddChildView(close);
- close_button_.reset(close);
- } else if (notification.pinned() && close_button_) {
- close_button_.reset();
- }
-}
-
} // namespace message_center
diff --git a/chromium/ui/message_center/views/message_view.h b/chromium/ui/message_center/views/message_view.h
index 9eeadbd73e5..862f27f183c 100644
--- a/chromium/ui/message_center/views/message_view.h
+++ b/chromium/ui/message_center/views/message_view.h
@@ -16,11 +16,9 @@
#include "ui/gfx/image/image_skia.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/notification.h"
-#include "ui/views/controls/button/button.h"
#include "ui/views/controls/slide_out_view.h"
namespace views {
-class ImageButton;
class ImageView;
class Painter;
class ScrollView;
@@ -38,8 +36,7 @@ const int kWebNotificationIconSize = 40;
// An base class for a notification entry. Contains background and other
// elements shared by derived notification views.
-class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
- public views::ButtonListener {
+class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView {
public:
MessageView(MessageCenterController* controller,
const Notification& notification);
@@ -54,9 +51,9 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
// Creates a shadow around the notification.
void CreateShadowBorder();
- bool IsCloseButtonFocused();
- void RequestFocusOnCloseButton();
- bool IsPinned();
+ virtual bool IsCloseButtonFocused() const = 0;
+ virtual void RequestFocusOnCloseButton() = 0;
+ virtual bool IsPinned() const = 0;
// Overridden from views::View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
@@ -71,9 +68,6 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
// Overridden from ui::EventHandler:
void OnGestureEvent(ui::GestureEvent* event) override;
- // Overridden from ButtonListener:
- void ButtonPressed(views::Button* sender, const ui::Event& event) override;
-
void set_scroller(views::ScrollView* scroller) { scroller_ = scroller; }
std::string notification_id() { return notification_id_; }
NotifierId notifier_id() { return notifier_id_; }
@@ -98,7 +92,6 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
views::View* background_view() { return background_view_; }
views::ImageView* small_image() { return small_image_view_.get(); }
- views::ImageButton* close_button() { return close_button_.get(); }
views::ScrollView* scroller() { return scroller_; }
MessageCenterController* controller() { return controller_; }
@@ -108,7 +101,6 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
NotifierId notifier_id_;
views::View* background_view_ = nullptr; // Owned by views hierarchy.
std::unique_ptr<views::ImageView> small_image_view_;
- std::unique_ptr<views::ImageButton> close_button_;
views::ScrollView* scroller_ = nullptr;
base::string16 accessible_name_;
diff --git a/chromium/ui/message_center/views/message_view_factory.cc b/chromium/ui/message_center/views/message_view_factory.cc
index 6f7da82b100..c09982a8f27 100644
--- a/chromium/ui/message_center/views/message_view_factory.cc
+++ b/chromium/ui/message_center/views/message_view_factory.cc
@@ -43,8 +43,8 @@ MessageView* MessageViewFactory::Create(MessageCenterController* controller,
notification_view = new NotificationView(controller, notification);
}
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- // Don't create shadows for notification toasts on linux wih aura.
+#if defined(OS_LINUX)
+ // Don't create shadows for notification toasts on Linux or CrOS.
if (top_level)
return notification_view;
#endif
diff --git a/chromium/ui/message_center/views/notification_view.cc b/chromium/ui/message_center/views/notification_view.cc
index cee41f03326..c7bdce47641 100644
--- a/chromium/ui/message_center/views/notification_view.cc
+++ b/chromium/ui/message_center/views/notification_view.cc
@@ -52,6 +52,9 @@ namespace {
// Dimensions.
const int kProgressBarBottomPadding = 0;
+constexpr int kCloseIconTopPadding = 5;
+constexpr int kCloseIconRightPadding = 5;
+
// static
std::unique_ptr<views::Border> MakeEmptyBorder(int top,
int left,
@@ -294,6 +297,16 @@ void NotificationView::Layout() {
settings_size.height());
}
+ // Close button.
+ if (close_button_) {
+ gfx::Rect content_bounds = GetContentsBounds();
+ gfx::Size close_size(close_button_->GetPreferredSize());
+ gfx::Rect close_rect(content_bounds.right() - close_size.width(),
+ content_bounds.y(), close_size.width(),
+ close_size.height());
+ close_button_->SetBoundsRect(close_rect);
+ }
+
bottom_view_->SetBounds(insets.left(), bottom_y,
content_width, bottom_height);
}
@@ -321,6 +334,7 @@ void NotificationView::UpdateWithNotification(
MessageView::UpdateWithNotification(notification);
CreateOrUpdateViews(notification);
+ CreateOrUpdateCloseButtonView(notification);
Layout();
SchedulePaint();
}
@@ -332,6 +346,13 @@ void NotificationView::ButtonPressed(views::Button* sender,
// TODO(dewittj): Remove this hack.
std::string id(notification_id());
+ if (close_button_ && sender == close_button_.get()) {
+ // Warning: This causes the NotificationView itself to be deleted, so don't
+ // do anything afterwards.
+ controller()->RemoveNotification(id, true /* by_user */);
+ return;
+ }
+
if (sender == settings_button_view_) {
controller()->ClickOnSettingsButton(id);
return;
@@ -344,11 +365,24 @@ void NotificationView::ButtonPressed(views::Button* sender,
return;
}
}
+}
+
+bool NotificationView::IsCloseButtonFocused() const {
+ if (!close_button_)
+ return false;
- // Let the superclass handle everything else.
- // Warning: This may cause the NotificationView itself to be deleted,
- // so don't do anything afterwards.
- MessageView::ButtonPressed(sender, event);
+ const views::FocusManager* focus_manager = GetFocusManager();
+ return focus_manager &&
+ focus_manager->GetFocusedView() == close_button_.get();
+}
+
+void NotificationView::RequestFocusOnCloseButton() {
+ if (close_button_)
+ close_button_->RequestFocus();
+}
+
+bool NotificationView::IsPinned() const {
+ return !close_button_;
}
void NotificationView::CreateOrUpdateTitleView(
@@ -630,6 +664,27 @@ void NotificationView::CreateOrUpdateActionButtonViews(
}
}
+void NotificationView::CreateOrUpdateCloseButtonView(
+ const Notification& notification) {
+ if (!notification.pinned() && !close_button_) {
+ PaddedButton* close = new PaddedButton(this);
+ close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding);
+ close->SetNormalImage(IDR_NOTIFICATION_CLOSE);
+ close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER);
+ close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED);
+ close->set_animate_on_state_change(false);
+ close->SetAccessibleName(l10n_util::GetStringUTF16(
+ IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
+ close->SetTooltipText(l10n_util::GetStringUTF16(
+ IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_TOOLTIP));
+ close->set_owned_by_client();
+ AddChildView(close);
+ close_button_.reset(close);
+ } else if (notification.pinned() && close_button_) {
+ close_button_.reset();
+ }
+}
+
int NotificationView::GetMessageLineLimit(int title_lines, int width) const {
// Image notifications require that the image must be kept flush against
// their icons, but we can allow more text if no image.
diff --git a/chromium/ui/message_center/views/notification_view.h b/chromium/ui/message_center/views/notification_view.h
index 6d54895ac8e..6ce79c2870c 100644
--- a/chromium/ui/message_center/views/notification_view.h
+++ b/chromium/ui/message_center/views/notification_view.h
@@ -11,6 +11,8 @@
#include "base/macros.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/views/message_view.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/image_button.h"
#include "ui/views/view_targeter_delegate.h"
namespace views {
@@ -29,6 +31,7 @@ class ProportionalImageView;
// returned by the Create() factory method below.
class MESSAGE_CENTER_EXPORT NotificationView
: public MessageView,
+ public views::ButtonListener,
public views::ViewTargeterDelegate {
public:
NotificationView(MessageCenterController* controller,
@@ -46,6 +49,12 @@ class MESSAGE_CENTER_EXPORT NotificationView
// Overridden from MessageView:
void UpdateWithNotification(const Notification& notification) override;
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+ bool IsCloseButtonFocused() const override;
+ void RequestFocusOnCloseButton() override;
+ bool IsPinned() const override;
+
+ protected:
+ views::ImageButton* close_button() { return close_button_.get(); }
private:
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, CreateOrUpdateTest);
@@ -75,6 +84,7 @@ class MESSAGE_CENTER_EXPORT NotificationView
void CreateOrUpdateIconView(const Notification& notification);
void CreateOrUpdateImageView(const Notification& notification);
void CreateOrUpdateActionButtonViews(const Notification& notification);
+ void CreateOrUpdateCloseButtonView(const Notification& notification);
int GetMessageLineLimit(int title_lines, int width) const;
int GetMessageHeight(int width, int limit) const;
@@ -102,6 +112,7 @@ class MESSAGE_CENTER_EXPORT NotificationView
views::ProgressBar* progress_bar_view_ = nullptr;
std::vector<NotificationButton*> action_buttons_;
std::vector<views::View*> separators_;
+ std::unique_ptr<views::ImageButton> close_button_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(NotificationView);
};
diff --git a/chromium/ui/message_center/views/notification_view_unittest.cc b/chromium/ui/message_center/views/notification_view_unittest.cc
index cbf4bac709f..930ccc094f1 100644
--- a/chromium/ui/message_center/views/notification_view_unittest.cc
+++ b/chromium/ui/message_center/views/notification_view_unittest.cc
@@ -167,11 +167,11 @@ class NotificationViewTest : public views::ViewsTestBase,
std::vector<views::View*>::iterator current = vertical_order.begin();
std::vector<views::View*>::iterator last = current++;
while (current != vertical_order.end()) {
- gfx::Point last_point = (*last)->bounds().origin();
+ gfx::Point last_point = (*last)->origin();
views::View::ConvertPointToTarget(
(*last), notification_view(), &last_point);
- gfx::Point current_point = (*current)->bounds().origin();
+ gfx::Point current_point = (*current)->origin();
views::View::ConvertPointToTarget(
(*current), notification_view(), &current_point);
diff --git a/chromium/ui/message_center/views/notifier_settings_view.cc b/chromium/ui/message_center/views/notifier_settings_view.cc
index e4ecb9887dd..f5794c9d4c9 100644
--- a/chromium/ui/message_center/views/notifier_settings_view.cc
+++ b/chromium/ui/message_center/views/notifier_settings_view.cc
@@ -231,17 +231,17 @@ base::string16 NotifierGroupComboboxModel::GetItemAt(int index) {
// showing 'icon'.
NotifierSettingsView::NotifierButton::NotifierButton(
NotifierSettingsProvider* provider,
- Notifier* notifier,
+ std::unique_ptr<Notifier> notifier,
views::ButtonListener* listener)
: views::CustomButton(listener),
provider_(provider),
- notifier_(notifier),
+ notifier_(std::move(notifier)),
icon_view_(new views::ImageView()),
name_view_(new views::Label(notifier_->name)),
checkbox_(new views::Checkbox(base::string16())),
learn_more_(nullptr) {
- DCHECK(provider);
- DCHECK(notifier);
+ DCHECK(provider_);
+ DCHECK(notifier_);
// Since there may never be an icon (but that could change at a later time),
// we own the icon view here.
@@ -442,13 +442,14 @@ NotifierSettingsView::NotifierSettingsView(NotifierSettingsProvider* provider)
scroller_ = new views::ScrollView();
scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false));
+ scroller_->SetHorizontalScrollBar(new views::OverlayScrollBar(true));
AddChildView(scroller_);
- std::vector<Notifier*> notifiers;
+ std::vector<std::unique_ptr<Notifier>> notifiers;
if (provider_)
provider_->GetNotifierList(&notifiers);
- UpdateContentsView(notifiers);
+ UpdateContentsView(std::move(notifiers));
}
NotifierSettingsView::~NotifierSettingsView() {
@@ -474,18 +475,18 @@ void NotifierSettingsView::UpdateIconImage(const NotifierId& notifier_id,
}
void NotifierSettingsView::NotifierGroupChanged() {
- std::vector<Notifier*> notifiers;
+ std::vector<std::unique_ptr<Notifier>> notifiers;
if (provider_)
provider_->GetNotifierList(&notifiers);
- UpdateContentsView(notifiers);
+ UpdateContentsView(std::move(notifiers));
}
void NotifierSettingsView::NotifierEnabledChanged(const NotifierId& notifier_id,
bool enabled) {}
void NotifierSettingsView::UpdateContentsView(
- const std::vector<Notifier*>& notifiers) {
+ std::vector<std::unique_ptr<Notifier>> notifiers) {
buttons_.clear();
views::View* contents_view = new views::View();
@@ -536,7 +537,8 @@ void NotifierSettingsView::UpdateContentsView(
size_t notifier_count = notifiers.size();
for (size_t i = 0; i < notifier_count; ++i) {
- NotifierButton* button = new NotifierButton(provider_, notifiers[i], this);
+ NotifierButton* button =
+ new NotifierButton(provider_, std::move(notifiers[i]), this);
EntryView* entry = new EntryView(button);
// This code emulates separators using borders. We will create an invisible
@@ -570,7 +572,7 @@ void NotifierSettingsView::Layout() {
int content_width = width();
int content_height = contents_view->GetHeightForWidth(content_width);
if (title_height + content_height > height()) {
- content_width -= scroller_->GetScrollBarWidth();
+ content_width -= scroller_->GetScrollBarLayoutWidth();
content_height = contents_view->GetHeightForWidth(content_width);
}
contents_view->SetBounds(0, 0, content_width, content_height);
@@ -582,7 +584,7 @@ gfx::Size NotifierSettingsView::GetMinimumSize() const {
int total_height = title_label_->GetPreferredSize().height() +
scroller_->contents()->GetPreferredSize().height();
if (total_height > kMinimumHeight)
- size.Enlarge(scroller_->GetScrollBarWidth(), 0);
+ size.Enlarge(scroller_->GetScrollBarLayoutWidth(), 0);
return size;
}
diff --git a/chromium/ui/message_center/views/notifier_settings_view.h b/chromium/ui/message_center/views/notifier_settings_view.h
index 6c4545ec0c8..1e23d5a0868 100644
--- a/chromium/ui/message_center/views/notifier_settings_view.h
+++ b/chromium/ui/message_center/views/notifier_settings_view.h
@@ -61,7 +61,7 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsView
public views::ButtonListener {
public:
NotifierButton(NotifierSettingsProvider* provider,
- Notifier* notifier,
+ std::unique_ptr<Notifier> notifier,
views::ButtonListener* listener);
~NotifierButton() override;
@@ -84,7 +84,7 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsView
void GridChanged(bool has_learn_more, bool has_icon_view);
NotifierSettingsProvider* provider_; // Weak.
- const std::unique_ptr<Notifier> notifier_;
+ std::unique_ptr<Notifier> notifier_;
// |icon_view_| is owned by us because sometimes we don't leave it
// in the view hierarchy.
std::unique_ptr<views::ImageView> icon_view_;
@@ -96,7 +96,7 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsView
};
// Given a new list of notifiers, updates the view to reflect it.
- void UpdateContentsView(const std::vector<Notifier*>& notifiers);
+ void UpdateContentsView(std::vector<std::unique_ptr<Notifier>> notifiers);
// Overridden from views::View:
void Layout() override;
diff --git a/chromium/ui/message_center/views/notifier_settings_view_unittest.cc b/chromium/ui/message_center/views/notifier_settings_view_unittest.cc
index 9be54ac5ac1..0fdd4875820 100644
--- a/chromium/ui/message_center/views/notifier_settings_view_unittest.cc
+++ b/chromium/ui/message_center/views/notifier_settings_view_unittest.cc
@@ -5,9 +5,10 @@
#include <stddef.h>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/message_center/fake_notifier_settings_provider.h"
+#include "ui/message_center/notifier_settings.h"
#include "ui/message_center/views/notifier_settings_view.h"
#include "ui/views/test/views_test_base.h"
@@ -15,28 +16,57 @@ namespace message_center {
namespace {
-Notifier* NewNotifier(const std::string& id,
- const std::string& title,
- bool enabled) {
- NotifierId notifier_id(NotifierId::APPLICATION, id);
- return new Notifier(notifier_id, base::UTF8ToUTF16(title), enabled);
-}
-
// A class used by NotifierSettingsView to integrate with a setting system
// for the clients of this module.
-class TestingNotifierSettingsProvider
- : public FakeNotifierSettingsProvider {
+class TestingNotifierSettingsProvider : public NotifierSettingsProvider {
public:
- TestingNotifierSettingsProvider(const std::vector<Notifier*>& notifiers,
- const NotifierId& settings_handler_id)
- : FakeNotifierSettingsProvider(notifiers),
- settings_handler_id_(settings_handler_id),
- request_count_(0u) {}
- ~TestingNotifierSettingsProvider() override {}
+ ~TestingNotifierSettingsProvider() override = default;
+
+ size_t request_count() const { return request_count_; }
+ const NotifierId* last_requested_notifier_id() const {
+ return last_notifier_id_settings_requested_.get();
+ }
+
+ // NotifierSettingsProvider
+
+ void AddObserver(NotifierSettingsObserver* observer) override {}
+ void RemoveObserver(NotifierSettingsObserver* observer) override {}
+
+ size_t GetNotifierGroupCount() const override { return 1; }
+
+ const message_center::NotifierGroup& GetNotifierGroupAt(
+ size_t index) const override {
+ DCHECK_EQ(0u, index);
+ return GetActiveNotifierGroup();
+ }
+
+ bool IsNotifierGroupActiveAt(size_t index) const override {
+ return index == 0;
+ }
+
+ void SwitchToNotifierGroup(size_t index) override { NOTREACHED(); }
+
+ const message_center::NotifierGroup& GetActiveNotifierGroup() const override {
+ static NotifierGroup group{base::UTF8ToUTF16("Fake name"),
+ base::UTF8ToUTF16("fake@email.com")};
+ return group;
+ }
+
+ void GetNotifierList(
+ std::vector<std::unique_ptr<Notifier>>* notifiers) override {
+ notifiers->clear();
+ notifiers->push_back(NewNotifier("id", "title", /*enabled=*/true));
+ notifiers->push_back(NewNotifier("id2", "other title", /*enabled=*/false));
+ }
+
+ void SetNotifierEnabled(const Notifier& notifier, bool enabled) override {}
+
+ // Called when the settings window is closed.
+ void OnNotifierSettingsClosing() override {}
bool NotifierHasAdvancedSettings(
const NotifierId& notifier_id) const override {
- return notifier_id == settings_handler_id_;
+ return notifier_id == NotifierId(NotifierId::APPLICATION, "id");
}
void OnNotifierAdvancedSettingsRequested(
@@ -46,14 +76,16 @@ class TestingNotifierSettingsProvider
last_notifier_id_settings_requested_.reset(new NotifierId(notifier_id));
}
- size_t request_count() const { return request_count_; }
- const NotifierId* last_requested_notifier_id() const {
- return last_notifier_id_settings_requested_.get();
+ private:
+ std::unique_ptr<Notifier> NewNotifier(const std::string& id,
+ const std::string& title,
+ bool enabled) {
+ NotifierId notifier_id(NotifierId::APPLICATION, id);
+ return base::MakeUnique<Notifier>(notifier_id, base::UTF8ToUTF16(title),
+ enabled);
}
- private:
- NotifierId settings_handler_id_;
- size_t request_count_;
+ size_t request_count_ = 0u;
std::unique_ptr<NotifierId> last_notifier_id_settings_requested_;
};
@@ -68,35 +100,29 @@ class NotifierSettingsViewTest : public views::ViewsTestBase {
void TearDown() override;
NotifierSettingsView* GetView() const;
- TestingNotifierSettingsProvider* settings_provider() const {
- return settings_provider_.get();
+ const TestingNotifierSettingsProvider* settings_provider() const {
+ return &settings_provider_;
}
private:
- std::unique_ptr<TestingNotifierSettingsProvider> settings_provider_;
+ TestingNotifierSettingsProvider settings_provider_;
std::unique_ptr<NotifierSettingsView> notifier_settings_view_;
DISALLOW_COPY_AND_ASSIGN(NotifierSettingsViewTest);
};
-NotifierSettingsViewTest::NotifierSettingsViewTest() {}
+NotifierSettingsViewTest::NotifierSettingsViewTest() = default;
-NotifierSettingsViewTest::~NotifierSettingsViewTest() {}
+NotifierSettingsViewTest::~NotifierSettingsViewTest() = default;
void NotifierSettingsViewTest::SetUp() {
views::ViewsTestBase::SetUp();
- std::vector<Notifier*> notifiers;
- notifiers.push_back(NewNotifier("id", "title", /*enabled=*/true));
- notifiers.push_back(NewNotifier("id2", "other title", /*enabled=*/false));
- settings_provider_.reset(new TestingNotifierSettingsProvider(
- notifiers, NotifierId(NotifierId::APPLICATION, "id")));
- notifier_settings_view_.reset(
- new NotifierSettingsView(settings_provider_.get()));
+ notifier_settings_view_ =
+ base::MakeUnique<NotifierSettingsView>(&settings_provider_);
}
void NotifierSettingsViewTest::TearDown() {
notifier_settings_view_.reset();
- settings_provider_.reset();
views::ViewsTestBase::TearDown();
}
@@ -105,16 +131,14 @@ NotifierSettingsView* NotifierSettingsViewTest::GetView() const {
}
TEST_F(NotifierSettingsViewTest, TestLearnMoreButton) {
- const std::set<NotifierSettingsView::NotifierButton*> buttons =
+ const std::set<NotifierSettingsView::NotifierButton*>& buttons =
GetView()->buttons_;
EXPECT_EQ(2u, buttons.size());
size_t number_of_settings_buttons = 0;
- std::set<NotifierSettingsView::NotifierButton*>::iterator iter =
- buttons.begin();
- for (; iter != buttons.end(); ++iter) {
- if ((*iter)->has_learn_more()) {
+ for (auto* button : buttons) {
+ if (button->has_learn_more()) {
++number_of_settings_buttons;
- (*iter)->SendLearnMorePressedForTest();
+ button->SendLearnMorePressedForTest();
}
}
@@ -122,7 +146,7 @@ TEST_F(NotifierSettingsViewTest, TestLearnMoreButton) {
EXPECT_EQ(1u, settings_provider()->request_count());
const NotifierId* last_settings_button_id =
settings_provider()->last_requested_notifier_id();
- ASSERT_FALSE(last_settings_button_id == NULL);
+ ASSERT_FALSE(last_settings_button_id == nullptr);
EXPECT_EQ(NotifierId(NotifierId::APPLICATION, "id"),
*last_settings_button_id);
}
diff --git a/chromium/ui/message_center/views/toast_contents_view.h b/chromium/ui/message_center/views/toast_contents_view.h
index 9af7185b501..f7d0cc21124 100644
--- a/chromium/ui/message_center/views/toast_contents_view.h
+++ b/chromium/ui/message_center/views/toast_contents_view.h
@@ -117,10 +117,9 @@ class ToastContentsView : public views::WidgetDelegateView,
// Immediately moves the toast without any sort of delay or animation.
void SetBoundsInstantly(gfx::Rect new_bounds);
- // Given the bounds of a toast on the screen, compute the bouds for that
+ // Given the bounds of a toast on the screen, compute the bounds for that
// toast in 'closed' node_data. The 'closed' node_data is used as
- // origin/destination
- // in reveal/closing animations.
+ // origin/destination in reveal/closing animations.
gfx::Rect GetClosedToastBounds(gfx::Rect bounds);
void StartFadeIn();