OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <gmock/gmock.h> | 5 #include "chrome/browser/chromeos/extensions/file_browser_notifications.h" |
| 6 |
6 #include <gtest/gtest.h> | 7 #include <gtest/gtest.h> |
7 #include <string> | 8 #include <string> |
8 | 9 |
9 #include "chrome/browser/browser_process.h" | 10 #include "chrome/browser/browser_process.h" |
10 #include "chrome/browser/ui/browser.h" | 11 #include "chrome/browser/ui/browser.h" |
11 #include "chrome/browser/chromeos/extensions/file_browser_notifications.h" | |
12 #include "chrome/browser/chromeos/notifications/balloon_collection_impl.h" | |
13 #include "chrome/browser/notifications/balloon.h" | 12 #include "chrome/browser/notifications/balloon.h" |
| 13 #include "chrome/browser/notifications/balloon_collection.h" |
14 #include "chrome/browser/notifications/notification.h" | 14 #include "chrome/browser/notifications/notification.h" |
15 #include "chrome/browser/notifications/notification_ui_manager.h" | 15 #include "chrome/browser/notifications/notification_ui_manager.h" |
16 #include "chrome/test/base/in_process_browser_test.h" | 16 #include "chrome/test/base/in_process_browser_test.h" |
17 #include "chrome/test/base/ui_test_utils.h" | 17 #include "chrome/test/base/ui_test_utils.h" |
18 | 18 |
19 using ::testing::_; | |
20 using ::testing::InSequence; | |
21 using ::testing::Return; | |
22 using ::testing::StrEq; | |
23 | |
24 namespace chromeos { | 19 namespace chromeos { |
25 | 20 |
26 class MockNotificationUI : public BalloonCollectionImpl::NotificationUI { | |
27 public: | |
28 virtual ~MockNotificationUI() {} | |
29 | |
30 MOCK_METHOD1(Add, void(Balloon* balloon)); | |
31 MOCK_METHOD1(Update, bool(Balloon* balloon)); | |
32 MOCK_METHOD1(Remove, void(Balloon* balloon)); | |
33 MOCK_METHOD1(Show, void(Balloon* balloon)); | |
34 | |
35 virtual void ResizeNotification(Balloon* balloon, const gfx::Size& size) | |
36 OVERRIDE { | |
37 } | |
38 virtual void SetActiveView(BalloonViewImpl* view) OVERRIDE {} | |
39 }; | |
40 | |
41 class MockFileBrowserNotifications : public FileBrowserNotifications { | 21 class MockFileBrowserNotifications : public FileBrowserNotifications { |
42 public: | 22 public: |
43 explicit MockFileBrowserNotifications(Profile* profile) | 23 explicit MockFileBrowserNotifications(Profile* profile) |
44 : FileBrowserNotifications(profile) { | 24 : FileBrowserNotifications(profile) { |
45 } | 25 } |
46 virtual ~MockFileBrowserNotifications() {} | 26 virtual ~MockFileBrowserNotifications() {} |
47 | 27 |
| 28 // Records the notification so we can force it to show later. |
48 virtual void PostDelayedShowNotificationTask( | 29 virtual void PostDelayedShowNotificationTask( |
49 const std::string& notification_id, | 30 const std::string& notification_id, |
50 NotificationType type, | 31 NotificationType type, |
51 const string16& message, | 32 const string16& message, |
52 size_t delay_ms) { | 33 size_t delay_ms) OVERRIDE { |
53 show_callback_data_.id = notification_id; | 34 show_callback_data_.id = notification_id; |
54 show_callback_data_.type = type; | 35 show_callback_data_.type = type; |
55 show_callback_data_.message = message; | 36 show_callback_data_.message = message; |
56 } | 37 } |
57 | 38 |
| 39 // Records the notification so we can force it to hide later. |
58 virtual void PostDelayedHideNotificationTask(NotificationType type, | 40 virtual void PostDelayedHideNotificationTask(NotificationType type, |
59 const std::string path, | 41 const std::string path, |
60 size_t delay_ms) { | 42 size_t delay_ms) OVERRIDE { |
61 hide_callback_data_.type = type; | 43 hide_callback_data_.type = type; |
62 hide_callback_data_.path = path; | 44 hide_callback_data_.path = path; |
63 } | 45 } |
64 | 46 |
65 void ExecuteShow() { | 47 void ExecuteShow() { |
66 FileBrowserNotifications::ShowNotificationDelayedTask( | 48 FileBrowserNotifications::ShowNotificationDelayedTask( |
67 show_callback_data_.id, show_callback_data_.type, | 49 show_callback_data_.id, show_callback_data_.type, |
68 show_callback_data_.message, AsWeakPtr()); | 50 show_callback_data_.message, AsWeakPtr()); |
69 } | 51 } |
70 | 52 |
(...skipping 14 matching lines...) Expand all Loading... |
85 struct HideCallbackData { | 67 struct HideCallbackData { |
86 NotificationType type; | 68 NotificationType type; |
87 std::string path; | 69 std::string path; |
88 }; | 70 }; |
89 | 71 |
90 HideCallbackData hide_callback_data_; | 72 HideCallbackData hide_callback_data_; |
91 }; | 73 }; |
92 | 74 |
93 class FileBrowserNotificationsTest : public InProcessBrowserTest { | 75 class FileBrowserNotificationsTest : public InProcessBrowserTest { |
94 public: | 76 public: |
95 FileBrowserNotificationsTest() {} | 77 FileBrowserNotificationsTest() : collection_(NULL) {} |
96 | 78 |
97 protected: | 79 protected: |
98 void ChangeNotificationUIMock() { | 80 // This must be initialized late in test startup. |
99 // collection will take ownership of the mock. | 81 void InitNotifications() { |
100 mock_notification_ui_ = new MockNotificationUI(); | 82 Profile* profile = browser()->profile(); |
101 collection_->set_notification_ui(mock_notification_ui_); | 83 notifications_.reset(new MockFileBrowserNotifications(profile)); |
102 } | 84 collection_ = |
103 | 85 g_browser_process->notification_ui_manager()->balloon_collection(); |
104 void InitNotificationUIMock() { | |
105 collection_ = static_cast<BalloonCollectionImpl*>( | |
106 g_browser_process->notification_ui_manager()->balloon_collection()); | |
107 ChangeNotificationUIMock(); | |
108 } | 86 } |
109 | 87 |
110 bool FindNotification(const std::string& id) { | 88 bool FindNotification(const std::string& id) { |
111 return notifications_->notifications().find(id) != | 89 return notifications_->notifications().find(id) != |
112 notifications_->notifications().end(); | 90 notifications_->notifications().end(); |
113 } | 91 } |
114 | 92 |
115 BalloonCollectionImpl* collection_; | 93 bool FindBalloon(const std::string& id) { |
116 MockNotificationUI* mock_notification_ui_; | 94 const std::deque<Balloon*>& balloons = collection_->GetActiveBalloons(); |
117 scoped_ptr<FileBrowserNotifications> notifications_; | 95 for (std::deque<Balloon*>::const_iterator it = balloons.begin(); |
| 96 it != balloons.end(); |
| 97 ++it) { |
| 98 Balloon* balloon = *it; |
| 99 if (balloon->notification().notification_id() == id) |
| 100 return true; |
| 101 } |
| 102 return false; |
| 103 } |
| 104 |
| 105 BalloonCollection* collection_; |
| 106 scoped_ptr<MockFileBrowserNotifications> notifications_; |
118 }; | 107 }; |
119 | 108 |
120 MATCHER_P(BalloonNotificationMatcher, expected_id, "") { | 109 #if defined(USE_AURA) |
121 return arg->notification().notification_id() == expected_id; | 110 // TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented |
122 } | 111 // chromeos::SystemNotification yet. http://crbug.com/104471 |
| 112 #define MAYBE_TestBasic FAILS_TestBasic |
| 113 #else |
| 114 #define MAYBE_TestBasic TestBasic |
| 115 #endif |
| 116 IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_TestBasic) { |
| 117 InitNotifications(); |
| 118 // We start with no balloons. |
| 119 EXPECT_EQ(0u, collection_->GetActiveBalloons().size()); |
123 | 120 |
124 IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, TestBasic) { | 121 // Showing a notification both updates our data and shows a balloon. |
125 InitNotificationUIMock(); | |
126 notifications_.reset(new MockFileBrowserNotifications(browser()->profile())); | |
127 | |
128 EXPECT_CALL(*mock_notification_ui_, | |
129 Add(BalloonNotificationMatcher("Dpath"))); | |
130 notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path"); | 122 notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path"); |
131 | |
132 EXPECT_CALL(*mock_notification_ui_, | |
133 Update(BalloonNotificationMatcher("Dpath"))) | |
134 .WillOnce(Return(true)); | |
135 notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path"); | |
136 | |
137 EXPECT_EQ(1u, notifications_->notifications().size()); | 123 EXPECT_EQ(1u, notifications_->notifications().size()); |
138 EXPECT_TRUE(FindNotification("Dpath")); | 124 EXPECT_TRUE(FindNotification("Dpath")); |
| 125 EXPECT_EQ(1u, collection_->GetActiveBalloons().size()); |
| 126 EXPECT_TRUE(FindBalloon("Dpath")); |
139 | 127 |
140 EXPECT_CALL(*mock_notification_ui_, | 128 // Updating the same notification maintains the same balloon. |
141 Add(BalloonNotificationMatcher("DFpath"))); | 129 notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path"); |
| 130 EXPECT_EQ(1u, notifications_->notifications().size()); |
| 131 EXPECT_TRUE(FindNotification("Dpath")); |
| 132 EXPECT_EQ(1u, collection_->GetActiveBalloons().size()); |
| 133 EXPECT_TRUE(FindBalloon("Dpath")); |
| 134 |
| 135 // A new notification adds a new balloon. |
142 notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL, | 136 notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL, |
143 "path"); | 137 "path"); |
144 EXPECT_EQ(2u, notifications_->notifications().size()); | 138 EXPECT_EQ(2u, notifications_->notifications().size()); |
145 EXPECT_TRUE(FindNotification("DFpath")); | 139 EXPECT_TRUE(FindNotification("DFpath")); |
| 140 EXPECT_TRUE(FindNotification("Dpath")); |
| 141 EXPECT_EQ(2u, collection_->GetActiveBalloons().size()); |
| 142 EXPECT_TRUE(FindBalloon("DFpath")); |
| 143 EXPECT_TRUE(FindBalloon("Dpath")); |
146 | 144 |
147 EXPECT_CALL(*mock_notification_ui_, | 145 // Hiding a notification removes it from our data. |
148 Remove(BalloonNotificationMatcher("DFpath"))); | |
149 notifications_->HideNotification(FileBrowserNotifications::DEVICE_FAIL, | 146 notifications_->HideNotification(FileBrowserNotifications::DEVICE_FAIL, |
150 "path"); | 147 "path"); |
151 | |
152 EXPECT_EQ(1u, notifications_->notifications().size()); | 148 EXPECT_EQ(1u, notifications_->notifications().size()); |
153 EXPECT_FALSE(FindNotification("DFpath")); | 149 EXPECT_FALSE(FindNotification("DFpath")); |
| 150 EXPECT_TRUE(FindNotification("Dpath")); |
154 | 151 |
| 152 // Balloons don't go away until we run the message loop. |
| 153 EXPECT_EQ(2u, collection_->GetActiveBalloons().size()); |
| 154 EXPECT_TRUE(FindBalloon("DFpath")); |
| 155 EXPECT_TRUE(FindBalloon("Dpath")); |
| 156 |
| 157 // Running the message loop allows the balloon to disappear. |
155 ui_test_utils::RunAllPendingInMessageLoop(); | 158 ui_test_utils::RunAllPendingInMessageLoop(); |
156 | 159 EXPECT_EQ(1u, collection_->GetActiveBalloons().size()); |
157 ChangeNotificationUIMock(); | 160 EXPECT_FALSE(FindBalloon("DFpath")); |
158 | 161 EXPECT_TRUE(FindBalloon("Dpath")); |
159 EXPECT_CALL(*mock_notification_ui_, Remove(_)) | |
160 .Times(1); | |
161 }; | 162 }; |
162 | 163 |
163 IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, ShowDelayedTest) { | 164 #if defined(USE_AURA) |
164 InitNotificationUIMock(); | 165 // TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented |
165 MockFileBrowserNotifications* mocked_notifications = | 166 // chromeos::SystemNotification yet. http://crbug.com/104471 |
166 new MockFileBrowserNotifications(browser()->profile()); | 167 #define MAYBE_ShowDelayedTest FAILS_ShowDelayedTest |
167 notifications_.reset(mocked_notifications); | 168 #else |
168 | 169 // TODO(jamescook): This test is flaky on linux_chromeos, occasionally causing |
169 EXPECT_CALL(*mock_notification_ui_, | 170 // this assertion failure inside Gtk: |
170 Add(BalloonNotificationMatcher("Dpath"))); | 171 // "murrine_style_draw_box: assertion `height >= -1' failed" |
| 172 // There may be an underlying bug in the ChromeOS notification code. |
| 173 // I'm not marking it as FLAKY because this doesn't happen on the bots. |
| 174 #define MAYBE_ShowDelayedTest ShowDelayedTest |
| 175 #endif |
| 176 IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_ShowDelayedTest) { |
| 177 InitNotifications(); |
| 178 // Adding a delayed notification does not show a balloon. |
171 notifications_->ShowNotificationDelayed(FileBrowserNotifications::DEVICE, | 179 notifications_->ShowNotificationDelayed(FileBrowserNotifications::DEVICE, |
172 "path", 3000); | 180 "path", 3000); |
173 mocked_notifications->ExecuteShow(); | 181 EXPECT_EQ(0u, collection_->GetActiveBalloons().size()); |
174 | 182 |
175 EXPECT_CALL(*mock_notification_ui_, | 183 // Forcing the show to happen makes the balloon appear. |
176 Add(BalloonNotificationMatcher("DFpath"))); | 184 notifications_->ExecuteShow(); |
| 185 ui_test_utils::RunAllPendingInMessageLoop(); |
| 186 EXPECT_EQ(1u, collection_->GetActiveBalloons().size()); |
| 187 EXPECT_TRUE(FindBalloon("Dpath")); |
| 188 |
| 189 // Showing a notification both immediately and delayed results in one |
| 190 // additional balloon. |
177 notifications_->ShowNotificationDelayed(FileBrowserNotifications::DEVICE_FAIL, | 191 notifications_->ShowNotificationDelayed(FileBrowserNotifications::DEVICE_FAIL, |
178 "path", 3000); | 192 "path", 3000); |
179 notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL, | 193 notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL, |
180 "path"); | 194 "path"); |
| 195 EXPECT_EQ(2u, collection_->GetActiveBalloons().size()); |
| 196 EXPECT_TRUE(FindBalloon("Dpath")); |
| 197 EXPECT_TRUE(FindBalloon("DFpath")); |
181 | 198 |
182 ChangeNotificationUIMock(); | 199 // When the delayed notification arrives, it's an update, so we still only |
183 EXPECT_CALL(*mock_notification_ui_, | 200 // have two balloons. |
184 Update(BalloonNotificationMatcher("DFpath"))); | 201 notifications_->ExecuteShow(); |
185 mocked_notifications->ExecuteShow(); | 202 ui_test_utils::RunAllPendingInMessageLoop(); |
| 203 EXPECT_EQ(2u, collection_->GetActiveBalloons().size()); |
| 204 EXPECT_TRUE(FindBalloon("Dpath")); |
| 205 EXPECT_TRUE(FindBalloon("DFpath")); |
186 | 206 |
187 EXPECT_CALL(*mock_notification_ui_, | 207 // If we schedule a show for later, then hide before it becomes visible, |
188 Remove(BalloonNotificationMatcher("Fpath"))) | 208 // the balloon should not be added. |
189 .Times(0); | |
190 EXPECT_CALL(*mock_notification_ui_, | |
191 Add(BalloonNotificationMatcher("Fpath"))) | |
192 .Times(0); | |
193 notifications_->ShowNotificationDelayed( | 209 notifications_->ShowNotificationDelayed( |
194 FileBrowserNotifications::FORMAT_FAIL, "path", 3000); | 210 FileBrowserNotifications::FORMAT_FAIL, "path", 3000); |
195 notifications_->HideNotification(FileBrowserNotifications::FORMAT_FAIL, | 211 notifications_->HideNotification(FileBrowserNotifications::FORMAT_FAIL, |
196 "path"); | 212 "path"); |
| 213 EXPECT_EQ(2u, collection_->GetActiveBalloons().size()); |
| 214 EXPECT_TRUE(FindBalloon("Dpath")); |
| 215 EXPECT_TRUE(FindBalloon("DFpath")); |
| 216 EXPECT_FALSE(FindBalloon("Fpath")); |
| 217 |
| 218 // Even when we try to force the show, nothing appears, because the balloon |
| 219 // was explicitly hidden. |
| 220 notifications_->ExecuteShow(); |
197 ui_test_utils::RunAllPendingInMessageLoop(); | 221 ui_test_utils::RunAllPendingInMessageLoop(); |
198 | 222 EXPECT_EQ(2u, collection_->GetActiveBalloons().size()); |
199 mocked_notifications->ExecuteShow(); | 223 EXPECT_TRUE(FindBalloon("Dpath")); |
200 | 224 EXPECT_TRUE(FindBalloon("DFpath")); |
201 ChangeNotificationUIMock(); | 225 EXPECT_FALSE(FindBalloon("Fpath")); |
202 EXPECT_CALL(*mock_notification_ui_, Remove(_)) | |
203 .Times(2); | |
204 | |
205 ui_test_utils::RunAllPendingInMessageLoop(); | |
206 } | 226 } |
207 | 227 |
208 IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, HideDelayedTest) { | 228 #if defined(USE_AURA) |
209 InitNotificationUIMock(); | 229 // TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented |
210 MockFileBrowserNotifications* mocked_notifications = | 230 // chromeos::SystemNotification yet. http://crbug.com/104471 |
211 new MockFileBrowserNotifications(browser()->profile()); | 231 #define MAYBE_HideDelayedTest FAILS_HideDelayedTest |
212 notifications_.reset(mocked_notifications); | 232 #else |
213 | 233 #define MAYBE_HideDelayedTest HideDelayedTest |
214 EXPECT_CALL(*mock_notification_ui_, | 234 #endif |
215 Add(BalloonNotificationMatcher("Dpath"))); | 235 IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_HideDelayedTest) { |
| 236 InitNotifications(); |
| 237 // Showing now, and scheduling a hide for later, results in one balloon. |
216 notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path"); | 238 notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path"); |
217 | |
218 notifications_->HideNotificationDelayed(FileBrowserNotifications::DEVICE, | 239 notifications_->HideNotificationDelayed(FileBrowserNotifications::DEVICE, |
219 "path", 3000); | 240 "path", 3000); |
220 ChangeNotificationUIMock(); | 241 EXPECT_EQ(1u, collection_->GetActiveBalloons().size()); |
221 EXPECT_CALL(*mock_notification_ui_, | 242 EXPECT_TRUE(FindBalloon("Dpath")); |
222 Remove(BalloonNotificationMatcher("Dpath"))); | |
223 mocked_notifications->ExecuteHide(); | |
224 | 243 |
| 244 // Forcing the hide removes the balloon. |
| 245 notifications_->ExecuteHide(); |
225 ui_test_utils::RunAllPendingInMessageLoop(); | 246 ui_test_utils::RunAllPendingInMessageLoop(); |
| 247 EXPECT_EQ(0u, collection_->GetActiveBalloons().size()); |
226 | 248 |
227 EXPECT_CALL(*mock_notification_ui_, | 249 // Immediate show then hide results in no balloons. |
228 Add(BalloonNotificationMatcher("DFpath"))); | |
229 EXPECT_CALL(*mock_notification_ui_, | |
230 Remove(BalloonNotificationMatcher("DFpath"))); | |
231 notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL, | 250 notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL, |
232 "path"); | 251 "path"); |
233 notifications_->HideNotification(FileBrowserNotifications::DEVICE_FAIL, | 252 notifications_->HideNotification(FileBrowserNotifications::DEVICE_FAIL, |
234 "path"); | 253 "path"); |
235 ui_test_utils::RunAllPendingInMessageLoop(); | 254 ui_test_utils::RunAllPendingInMessageLoop(); |
| 255 EXPECT_EQ(0u, collection_->GetActiveBalloons().size()); |
236 | 256 |
| 257 // Delayed hide for a notification that doesn't exist does nothing. |
237 notifications_->HideNotificationDelayed(FileBrowserNotifications::DEVICE_FAIL, | 258 notifications_->HideNotificationDelayed(FileBrowserNotifications::DEVICE_FAIL, |
238 "path", 3000); | 259 "path", 3000); |
239 ChangeNotificationUIMock(); | 260 notifications_->ExecuteHide(); |
240 EXPECT_CALL(*mock_notification_ui_, | |
241 Remove(BalloonNotificationMatcher("DFpath"))) | |
242 .Times(0); | |
243 mocked_notifications->ExecuteHide(); | |
244 | |
245 ui_test_utils::RunAllPendingInMessageLoop(); | 261 ui_test_utils::RunAllPendingInMessageLoop(); |
| 262 EXPECT_EQ(0u, collection_->GetActiveBalloons().size()); |
246 } | 263 } |
247 | 264 |
248 } // namespace chromeos. | 265 } // namespace chromeos. |
249 | |
OLD | NEW |