OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "chrome/browser/notifications/notification_platform_bridge_linux.h" | 5 #include "chrome/browser/notifications/notification_platform_bridge_linux.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/files/file_util.h" |
11 #include "base/i18n/number_formatting.h" | 12 #include "base/i18n/number_formatting.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
14 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
16 #include "chrome/browser/notifications/notification.h" | 17 #include "chrome/browser/notifications/notification.h" |
17 #include "chrome/browser/notifications/notification_test_util.h" | 18 #include "chrome/browser/notifications/notification_test_util.h" |
18 #include "content/public/test/test_browser_thread_bundle.h" | 19 #include "content/public/test/test_browser_thread_bundle.h" |
19 #include "content/public/test/test_utils.h" | 20 #include "content/public/test/test_utils.h" |
20 #include "dbus/mock_bus.h" | 21 #include "dbus/mock_bus.h" |
21 #include "dbus/mock_object_proxy.h" | 22 #include "dbus/mock_object_proxy.h" |
22 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
23 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 25 #include "third_party/re2/src/re2/re2.h" |
| 26 #include "ui/gfx/image/image_skia.h" |
24 | 27 |
25 using testing::_; | 28 using testing::_; |
26 using testing::Return; | 29 using testing::Return; |
27 using testing::StrictMock; | 30 using testing::StrictMock; |
28 | 31 |
29 namespace { | 32 namespace { |
30 | 33 |
31 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; | 34 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; |
32 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; | 35 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; |
33 | 36 |
34 class NotificationBuilder { | 37 class NotificationBuilder { |
35 public: | 38 public: |
36 explicit NotificationBuilder(const std::string& id) | 39 explicit NotificationBuilder(const std::string& id) |
37 : notification_(message_center::NOTIFICATION_TYPE_SIMPLE, | 40 : notification_(message_center::NOTIFICATION_TYPE_SIMPLE, |
38 base::string16(), | 41 base::string16(), |
39 base::string16(), | 42 base::string16(), |
40 gfx::Image(), | 43 gfx::Image(), |
41 message_center::NotifierId(GURL()), | 44 message_center::NotifierId(GURL()), |
42 base::string16(), | 45 base::string16(), |
43 GURL(), | 46 GURL(), |
44 id, | 47 id, |
45 message_center::RichNotificationData(), | 48 message_center::RichNotificationData(), |
46 new MockNotificationDelegate(id)) {} | 49 new MockNotificationDelegate(id)) {} |
47 | 50 |
48 Notification GetResult() { return notification_; } | 51 Notification GetResult() { return notification_; } |
49 | 52 |
| 53 NotificationBuilder& SetImage(const gfx::Image& image) { |
| 54 notification_.set_image(image); |
| 55 return *this; |
| 56 } |
| 57 |
50 NotificationBuilder& SetItems( | 58 NotificationBuilder& SetItems( |
51 const std::vector<message_center::NotificationItem>& items) { | 59 const std::vector<message_center::NotificationItem>& items) { |
52 notification_.set_items(items); | 60 notification_.set_items(items); |
53 return *this; | 61 return *this; |
54 } | 62 } |
55 | 63 |
56 NotificationBuilder& SetNeverTimeout(bool never_timeout) { | 64 NotificationBuilder& SetNeverTimeout(bool never_timeout) { |
57 notification_.set_never_timeout(never_timeout); | 65 notification_.set_never_timeout(never_timeout); |
58 return *this; | 66 return *this; |
59 } | 67 } |
(...skipping 16 matching lines...) Expand all Loading... |
76 private: | 84 private: |
77 Notification notification_; | 85 Notification notification_; |
78 }; | 86 }; |
79 | 87 |
80 struct NotificationRequest { | 88 struct NotificationRequest { |
81 std::string summary; | 89 std::string summary; |
82 std::string body; | 90 std::string body; |
83 int32_t expire_timeout = 0; | 91 int32_t expire_timeout = 0; |
84 }; | 92 }; |
85 | 93 |
| 94 const SkBitmap CreateBitmap(int width, int height) { |
| 95 SkBitmap bitmap; |
| 96 bitmap.allocN32Pixels(width, height); |
| 97 bitmap.eraseARGB(255, 0, 255, 0); |
| 98 return bitmap; |
| 99 } |
| 100 |
| 101 gfx::ImageSkia CreateImageSkia(int width, int height) { |
| 102 return gfx::ImageSkia::CreateFrom1xBitmap(CreateBitmap(width, height)); |
| 103 } |
| 104 |
86 NotificationRequest ParseRequest(dbus::MethodCall* method_call) { | 105 NotificationRequest ParseRequest(dbus::MethodCall* method_call) { |
87 // The "Notify" message must have type (susssasa{sv}i). | 106 // The "Notify" message must have type (susssasa{sv}i). |
88 // https://developer.gnome.org/notification-spec/#command-notify | 107 // https://developer.gnome.org/notification-spec/#command-notify |
89 NotificationRequest request; | 108 NotificationRequest request; |
90 | 109 |
91 dbus::MessageReader reader(method_call); | 110 dbus::MessageReader reader(method_call); |
92 std::string str; | 111 std::string str; |
93 uint32_t uint32; | 112 uint32_t uint32; |
94 EXPECT_TRUE(reader.PopString(&str)); // app_name | 113 EXPECT_TRUE(reader.PopString(&str)); // app_name |
95 EXPECT_TRUE(reader.PopUint32(&uint32)); // replaces_id | 114 EXPECT_TRUE(reader.PopUint32(&uint32)); // replaces_id |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 mock_bus_.get(), kFreedesktopNotificationsName, | 211 mock_bus_.get(), kFreedesktopNotificationsName, |
193 dbus::ObjectPath(kFreedesktopNotificationsPath)); | 212 dbus::ObjectPath(kFreedesktopNotificationsPath)); |
194 | 213 |
195 EXPECT_CALL(*mock_bus_.get(), | 214 EXPECT_CALL(*mock_bus_.get(), |
196 GetObjectProxy(kFreedesktopNotificationsName, | 215 GetObjectProxy(kFreedesktopNotificationsName, |
197 dbus::ObjectPath(kFreedesktopNotificationsPath))) | 216 dbus::ObjectPath(kFreedesktopNotificationsPath))) |
198 .WillOnce(Return(mock_notification_proxy_.get())); | 217 .WillOnce(Return(mock_notification_proxy_.get())); |
199 | 218 |
200 EXPECT_CALL(*mock_notification_proxy_.get(), | 219 EXPECT_CALL(*mock_notification_proxy_.get(), |
201 MockCallMethodAndBlock(Calls("GetCapabilities"), _)) | 220 MockCallMethodAndBlock(Calls("GetCapabilities"), _)) |
202 .WillOnce(OnGetCapabilities(std::vector<std::string>{"body"})); | 221 .WillOnce( |
| 222 OnGetCapabilities(std::vector<std::string>{"body", "body-images"})); |
203 | 223 |
204 EXPECT_CALL(*mock_notification_proxy_.get(), | 224 EXPECT_CALL(*mock_notification_proxy_.get(), |
205 MockCallMethodAndBlock(Calls("GetServerInformation"), _)) | 225 MockCallMethodAndBlock(Calls("GetServerInformation"), _)) |
206 .WillOnce(OnGetServerInformation("1.2")); | 226 .WillOnce(OnGetServerInformation("1.2")); |
207 | 227 |
208 EXPECT_CALL( | 228 EXPECT_CALL( |
209 *mock_notification_proxy_.get(), | 229 *mock_notification_proxy_.get(), |
210 ConnectToSignal(kFreedesktopNotificationsName, "ActionInvoked", _, _)) | 230 ConnectToSignal(kFreedesktopNotificationsName, "ActionInvoked", _, _)) |
211 .WillOnce(RegisterSignalCallback(&action_invoked_callback_)); | 231 .WillOnce(RegisterSignalCallback(&action_invoked_callback_)); |
212 | 232 |
213 EXPECT_CALL(*mock_notification_proxy_.get(), | 233 EXPECT_CALL(*mock_notification_proxy_.get(), |
214 ConnectToSignal(kFreedesktopNotificationsName, | 234 ConnectToSignal(kFreedesktopNotificationsName, |
215 "NotificationClosed", _, _)) | 235 "NotificationClosed", _, _)) |
216 .WillOnce(RegisterSignalCallback(¬ification_closed_callback_)); | 236 .WillOnce(RegisterSignalCallback(¬ification_closed_callback_)); |
217 } | 237 } |
218 | 238 |
219 void TearDown() override { | 239 void TearDown() override { |
220 EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()); | 240 EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()); |
221 notification_bridge_linux_->CleanUp(); | 241 notification_bridge_linux_->CleanUp(); |
222 content::RunAllBlockingPoolTasksUntilIdle(); | 242 content::RunAllBlockingPoolTasksUntilIdle(); |
223 notification_bridge_linux_.reset(); | 243 notification_bridge_linux_.reset(); |
224 mock_notification_proxy_ = nullptr; | 244 mock_notification_proxy_ = nullptr; |
225 mock_bus_ = nullptr; | 245 mock_bus_ = nullptr; |
226 } | 246 } |
227 | 247 |
228 protected: | 248 protected: |
229 void CreateNotificationBridgeLinux() { | 249 void CreateNotificationBridgeLinux() { |
230 notification_bridge_linux_ = | 250 notification_bridge_linux_ = |
231 base::WrapUnique(new NotificationPlatformBridgeLinux(mock_bus_)); | 251 base::WrapUnique(new NotificationPlatformBridgeLinux(mock_bus_)); |
| 252 content::RunAllBlockingPoolTasksUntilIdle(); |
232 } | 253 } |
233 | 254 |
234 content::TestBrowserThreadBundle thread_bundle_; | 255 content::TestBrowserThreadBundle thread_bundle_; |
235 | 256 |
236 scoped_refptr<dbus::MockBus> mock_bus_; | 257 scoped_refptr<dbus::MockBus> mock_bus_; |
237 scoped_refptr<dbus::MockObjectProxy> mock_notification_proxy_; | 258 scoped_refptr<dbus::MockObjectProxy> mock_notification_proxy_; |
238 | 259 |
239 base::Callback<void(dbus::Signal*)> action_invoked_callback_; | 260 base::Callback<void(dbus::Signal*)> action_invoked_callback_; |
240 base::Callback<void(dbus::Signal*)> notification_closed_callback_; | 261 base::Callback<void(dbus::Signal*)> notification_closed_callback_; |
241 | 262 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 2)); | 343 2)); |
323 | 344 |
324 CreateNotificationBridgeLinux(); | 345 CreateNotificationBridgeLinux(); |
325 notification_bridge_linux_->Display( | 346 notification_bridge_linux_->Display( |
326 NotificationCommon::PERSISTENT, "", "", false, | 347 NotificationCommon::PERSISTENT, "", "", false, |
327 NotificationBuilder("1").SetNeverTimeout(false).GetResult()); | 348 NotificationBuilder("1").SetNeverTimeout(false).GetResult()); |
328 notification_bridge_linux_->Display( | 349 notification_bridge_linux_->Display( |
329 NotificationCommon::PERSISTENT, "", "", false, | 350 NotificationCommon::PERSISTENT, "", "", false, |
330 NotificationBuilder("2").SetNeverTimeout(true).GetResult()); | 351 NotificationBuilder("2").SetNeverTimeout(true).GetResult()); |
331 } | 352 } |
| 353 |
| 354 TEST_F(NotificationPlatformBridgeLinuxTest, NotificationImages) { |
| 355 const int kMaxImageWidth = 200; |
| 356 const int kMaxImageHeight = 100; |
| 357 |
| 358 const int original_width = kMaxImageWidth * 2; |
| 359 const int original_height = kMaxImageHeight; |
| 360 const int expected_width = kMaxImageWidth; |
| 361 const int expected_height = kMaxImageHeight / 2; |
| 362 |
| 363 gfx::Image original_image = |
| 364 gfx::Image(CreateImageSkia(original_width, original_height)); |
| 365 |
| 366 EXPECT_CALL(*mock_notification_proxy_.get(), |
| 367 MockCallMethodAndBlock(Calls("Notify"), _)) |
| 368 .WillOnce(OnNotify( |
| 369 [=](const NotificationRequest& request) { |
| 370 std::string file_name; |
| 371 EXPECT_TRUE(RE2::FullMatch( |
| 372 request.body, "\\<img src=\\\"(.+)\\\" alt=\\\".*\\\"/\\>", |
| 373 &file_name)); |
| 374 std::string file_contents; |
| 375 EXPECT_TRUE(base::ReadFileToString(base::FilePath(file_name), |
| 376 &file_contents)); |
| 377 gfx::Image image = gfx::Image::CreateFrom1xPNGBytes( |
| 378 reinterpret_cast<const unsigned char*>(file_contents.c_str()), |
| 379 file_contents.size()); |
| 380 EXPECT_EQ(expected_width, image.Width()); |
| 381 EXPECT_EQ(expected_height, image.Height()); |
| 382 }, |
| 383 1)); |
| 384 |
| 385 CreateNotificationBridgeLinux(); |
| 386 notification_bridge_linux_->Display( |
| 387 NotificationCommon::PERSISTENT, "", "", false, |
| 388 NotificationBuilder("") |
| 389 .SetType(message_center::NOTIFICATION_TYPE_IMAGE) |
| 390 .SetImage(original_image) |
| 391 .GetResult()); |
| 392 } |
OLD | NEW |