diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-04-05 14:08:31 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-04-11 07:46:53 +0000 |
commit | 6a4cabb866f66d4128a97cdc6d9d08ce074f1247 (patch) | |
tree | ab00f70a5e89278d6a0d16ff0c42578dc4d84a2d /chromium/ui/message_center | |
parent | e733310db58160074f574c429d48f8308c0afe17 (diff) | |
download | qtwebengine-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')
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_[¬ifier] = 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_[¬ifier]; -} - -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(), ¤t_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(¬ifiers); - 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(¬ifiers); - 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(); |