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/i18n/number_formatting.h" | |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
13 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
14 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
15 #include "chrome/browser/notifications/notification.h" | 16 #include "chrome/browser/notifications/notification.h" |
16 #include "chrome/browser/notifications/notification_test_util.h" | 17 #include "chrome/browser/notifications/notification_test_util.h" |
17 #include "content/public/test/test_browser_thread_bundle.h" | 18 #include "content/public/test/test_browser_thread_bundle.h" |
18 #include "content/public/test/test_utils.h" | 19 #include "content/public/test/test_utils.h" |
19 #include "dbus/mock_bus.h" | 20 #include "dbus/mock_bus.h" |
20 #include "dbus/mock_object_proxy.h" | 21 #include "dbus/mock_object_proxy.h" |
21 #include "testing/gmock/include/gmock/gmock.h" | 22 #include "testing/gmock/include/gmock/gmock.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
23 | 24 |
24 using testing::_; | 25 using testing::_; |
25 using testing::Return; | 26 using testing::Return; |
26 using testing::StrictMock; | 27 using testing::StrictMock; |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
30 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; | 31 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; |
31 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; | 32 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; |
32 | 33 |
33 ACTION_P(RegisterSignalCallback, callback_addr) { | 34 class NotificationBuilder { |
34 *callback_addr = arg2; | 35 public: |
35 arg3.Run("" /* interface_name */, "" /* signal_name */, true /* success */); | 36 explicit NotificationBuilder(const std::string& id) |
36 } | 37 : notification_(message_center::NOTIFICATION_TYPE_SIMPLE, |
38 base::string16(), | |
39 base::string16(), | |
40 gfx::Image(), | |
41 message_center::NotifierId(GURL()), | |
42 base::string16(), | |
43 GURL(), | |
44 id, | |
45 message_center::RichNotificationData(), | |
46 new MockNotificationDelegate(id)) {} | |
37 | 47 |
38 ACTION_P(OnGetCapabilities, capabilities) { | 48 Notification GetResult() { return notification_; } |
39 // MockObjectProxy::CallMethodAndBlock will wrap the return value in | |
40 // a unique_ptr. | |
41 dbus::Response* response = dbus::Response::CreateEmpty().release(); | |
42 dbus::MessageWriter writer(response); | |
43 writer.AppendArrayOfStrings(capabilities); | |
44 return response; | |
45 } | |
46 | 49 |
47 ACTION_P(OnGetServerInformation, spec_version) { | 50 NotificationBuilder& SetProgress(int progress) { |
48 dbus::Response* response = dbus::Response::CreateEmpty().release(); | 51 notification_.set_progress(progress); |
49 dbus::MessageWriter writer(response); | 52 return *this; |
50 writer.AppendString(""); // name | 53 } |
51 writer.AppendString(""); // vendor | |
52 writer.AppendString(""); // version | |
53 writer.AppendString(spec_version); | |
54 return response; | |
55 } | |
56 | 54 |
57 ACTION_P(OnNotify, id) { | 55 NotificationBuilder& SetTitle(const base::string16& title) { |
56 notification_.set_title(title); | |
57 return *this; | |
58 } | |
59 | |
60 NotificationBuilder& SetType(message_center::NotificationType type) { | |
61 notification_.set_type(type); | |
62 return *this; | |
63 } | |
64 | |
65 private: | |
66 Notification notification_; | |
67 }; | |
68 | |
69 struct NotificationRequest { | |
Lei Zhang
2017/05/10 20:45:28
Is this going to have more members later?
Tom (Use chromium acct)
2017/05/10 21:05:44
Yes:
https://codereview.chromium.org/2875443002/
| |
70 std::string summary; | |
71 }; | |
72 | |
73 NotificationRequest ParseRequest(dbus::MethodCall* method_call) { | |
58 // The "Notify" message must have type (susssasa{sv}i). | 74 // The "Notify" message must have type (susssasa{sv}i). |
59 // https://developer.gnome.org/notification-spec/#command-notify | 75 // https://developer.gnome.org/notification-spec/#command-notify |
60 dbus::MethodCall* method_call = arg0; | 76 NotificationRequest request; |
77 | |
61 dbus::MessageReader reader(method_call); | 78 dbus::MessageReader reader(method_call); |
62 std::string str; | 79 std::string str; |
63 uint32_t uint32; | 80 uint32_t uint32; |
64 int32_t int32; | 81 int32_t int32; |
65 EXPECT_TRUE(reader.PopString(&str)); | 82 EXPECT_TRUE(reader.PopString(&str)); // app_name |
66 EXPECT_TRUE(reader.PopUint32(&uint32)); | 83 EXPECT_TRUE(reader.PopUint32(&uint32)); // replaces_id |
67 EXPECT_TRUE(reader.PopString(&str)); | 84 EXPECT_TRUE(reader.PopString(&str)); // app_icon |
68 EXPECT_TRUE(reader.PopString(&str)); | 85 EXPECT_TRUE(reader.PopString(&request.summary)); // summary |
69 EXPECT_TRUE(reader.PopString(&str)); | 86 EXPECT_TRUE(reader.PopString(&str)); // body |
70 | 87 |
71 { | 88 { |
72 dbus::MessageReader actions_reader(nullptr); | 89 dbus::MessageReader actions_reader(nullptr); |
73 EXPECT_TRUE(reader.PopArray(&actions_reader)); | 90 EXPECT_TRUE(reader.PopArray(&actions_reader)); |
74 while (actions_reader.HasMoreData()) { | 91 while (actions_reader.HasMoreData()) { |
75 // Actions come in pairs. | 92 // Actions come in pairs. |
76 EXPECT_TRUE(actions_reader.PopString(&str)); | 93 EXPECT_TRUE(actions_reader.PopString(&str)); |
77 EXPECT_TRUE(actions_reader.PopString(&str)); | 94 EXPECT_TRUE(actions_reader.PopString(&str)); |
78 } | 95 } |
79 } | 96 } |
80 | 97 |
81 { | 98 { |
82 dbus::MessageReader hints_reader(nullptr); | 99 dbus::MessageReader hints_reader(nullptr); |
83 EXPECT_TRUE(reader.PopArray(&hints_reader)); | 100 EXPECT_TRUE(reader.PopArray(&hints_reader)); |
84 while (hints_reader.HasMoreData()) { | 101 while (hints_reader.HasMoreData()) { |
85 dbus::MessageReader dict_entry_reader(nullptr); | 102 dbus::MessageReader dict_entry_reader(nullptr); |
86 EXPECT_TRUE(hints_reader.PopDictEntry(&dict_entry_reader)); | 103 EXPECT_TRUE(hints_reader.PopDictEntry(&dict_entry_reader)); |
87 EXPECT_TRUE(dict_entry_reader.PopString(&str)); | 104 EXPECT_TRUE(dict_entry_reader.PopString(&str)); |
88 dbus::MessageReader variant_reader(nullptr); | 105 dbus::MessageReader variant_reader(nullptr); |
89 EXPECT_TRUE(dict_entry_reader.PopVariant(&variant_reader)); | 106 EXPECT_TRUE(dict_entry_reader.PopVariant(&variant_reader)); |
90 EXPECT_FALSE(dict_entry_reader.HasMoreData()); | 107 EXPECT_FALSE(dict_entry_reader.HasMoreData()); |
91 } | 108 } |
92 } | 109 } |
93 | 110 |
94 EXPECT_TRUE(reader.PopInt32(&int32)); | 111 EXPECT_TRUE(reader.PopInt32(&int32)); // expire_timeout |
95 EXPECT_FALSE(reader.HasMoreData()); | 112 EXPECT_FALSE(reader.HasMoreData()); |
96 | 113 |
114 return request; | |
115 } | |
116 | |
117 dbus::Response* GetIdResponse(uint32_t id) { | |
97 dbus::Response* response = dbus::Response::CreateEmpty().release(); | 118 dbus::Response* response = dbus::Response::CreateEmpty().release(); |
98 dbus::MessageWriter writer(response); | 119 dbus::MessageWriter writer(response); |
99 writer.AppendUint32(id); | 120 writer.AppendUint32(id); |
100 return response; | 121 return response; |
101 } | 122 } |
102 | 123 |
124 ACTION_P(RegisterSignalCallback, callback_addr) { | |
125 *callback_addr = arg2; | |
126 arg3.Run("" /* interface_name */, "" /* signal_name */, true /* success */); | |
127 } | |
128 | |
129 ACTION_P(OnGetCapabilities, capabilities) { | |
130 // MockObjectProxy::CallMethodAndBlock will wrap the return value in | |
131 // a unique_ptr. | |
132 dbus::Response* response = dbus::Response::CreateEmpty().release(); | |
133 dbus::MessageWriter writer(response); | |
134 writer.AppendArrayOfStrings(capabilities); | |
135 return response; | |
136 } | |
137 | |
138 ACTION_P(OnGetServerInformation, spec_version) { | |
139 dbus::Response* response = dbus::Response::CreateEmpty().release(); | |
140 dbus::MessageWriter writer(response); | |
141 writer.AppendString(""); // name | |
142 writer.AppendString(""); // vendor | |
143 writer.AppendString(""); // version | |
144 writer.AppendString(spec_version); | |
145 return response; | |
146 } | |
147 | |
148 ACTION_P(OnNotify, id) { | |
149 ParseRequest(arg0); | |
150 return GetIdResponse(id); | |
151 } | |
152 | |
103 ACTION(OnCloseNotification) { | 153 ACTION(OnCloseNotification) { |
104 // The "CloseNotification" message must have type (u). | 154 // The "CloseNotification" message must have type (u). |
105 // https://developer.gnome.org/notification-spec/#command-close-notification | 155 // https://developer.gnome.org/notification-spec/#command-close-notification |
106 dbus::MethodCall* method_call = arg0; | 156 dbus::MethodCall* method_call = arg0; |
107 dbus::MessageReader reader(method_call); | 157 dbus::MessageReader reader(method_call); |
108 uint32_t uint32; | 158 uint32_t uint32; |
109 EXPECT_TRUE(reader.PopUint32(&uint32)); | 159 EXPECT_TRUE(reader.PopUint32(&uint32)); |
110 EXPECT_FALSE(reader.HasMoreData()); | 160 EXPECT_FALSE(reader.HasMoreData()); |
111 | 161 |
112 return dbus::Response::CreateEmpty().release(); | 162 return dbus::Response::CreateEmpty().release(); |
113 } | 163 } |
114 | 164 |
115 // Matches a method call to the specified dbus target. | 165 // Matches a method call to the specified dbus target. |
116 MATCHER_P(Calls, member, "") { | 166 MATCHER_P(Calls, member, "") { |
117 return arg->GetMember() == member; | 167 return arg->GetMember() == member; |
118 } | 168 } |
119 | 169 |
120 Notification CreateNotification(const char* id, | |
121 const char* title, | |
122 const char* body, | |
123 const char* origin) { | |
124 message_center::RichNotificationData optional_fields; | |
125 GURL url = GURL(origin); | |
126 return Notification(message_center::NOTIFICATION_TYPE_SIMPLE, | |
127 base::UTF8ToUTF16(title), base::UTF8ToUTF16(body), | |
128 gfx::Image(), message_center::NotifierId(url), | |
129 base::UTF8ToUTF16("Notifier's Name"), url, id, | |
130 optional_fields, new MockNotificationDelegate(id)); | |
131 } | |
132 | |
133 } // namespace | 170 } // namespace |
134 | 171 |
135 class NotificationPlatformBridgeLinuxTest : public testing::Test { | 172 class NotificationPlatformBridgeLinuxTest : public testing::Test { |
136 public: | 173 public: |
137 NotificationPlatformBridgeLinuxTest() = default; | 174 NotificationPlatformBridgeLinuxTest() = default; |
138 ~NotificationPlatformBridgeLinuxTest() override = default; | 175 ~NotificationPlatformBridgeLinuxTest() override = default; |
139 | 176 |
140 void SetUp() override { | 177 void SetUp() override { |
141 mock_bus_ = new dbus::MockBus(dbus::Bus::Options()); | 178 mock_bus_ = new dbus::MockBus(dbus::Bus::Options()); |
142 mock_notification_proxy_ = new StrictMock<dbus::MockObjectProxy>( | 179 mock_notification_proxy_ = new StrictMock<dbus::MockObjectProxy>( |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 EXPECT_CALL(*mock_notification_proxy_.get(), | 241 EXPECT_CALL(*mock_notification_proxy_.get(), |
205 MockCallMethodAndBlock(Calls("Notify"), _)) | 242 MockCallMethodAndBlock(Calls("Notify"), _)) |
206 .WillOnce(OnNotify(1)); | 243 .WillOnce(OnNotify(1)); |
207 EXPECT_CALL(*mock_notification_proxy_.get(), | 244 EXPECT_CALL(*mock_notification_proxy_.get(), |
208 MockCallMethodAndBlock(Calls("CloseNotification"), _)) | 245 MockCallMethodAndBlock(Calls("CloseNotification"), _)) |
209 .WillOnce(OnCloseNotification()); | 246 .WillOnce(OnCloseNotification()); |
210 | 247 |
211 CreateNotificationBridgeLinux(); | 248 CreateNotificationBridgeLinux(); |
212 notification_bridge_linux_->Display(NotificationCommon::PERSISTENT, "", "", | 249 notification_bridge_linux_->Display(NotificationCommon::PERSISTENT, "", "", |
213 false, | 250 false, |
214 CreateNotification("id1", "", "", "")); | 251 NotificationBuilder("").GetResult()); |
215 notification_bridge_linux_->Close("", ""); | 252 notification_bridge_linux_->Close("", ""); |
216 } | 253 } |
254 | |
255 ACTION_P2(VerifySummary, summary, id) { | |
256 NotificationRequest request = ParseRequest(arg0); | |
257 EXPECT_EQ(summary, request.summary); | |
258 return GetIdResponse(id); | |
259 } | |
260 | |
261 TEST_F(NotificationPlatformBridgeLinuxTest, ProgressPercentageAddedToSummary) { | |
262 EXPECT_CALL(*mock_notification_proxy_.get(), | |
263 MockCallMethodAndBlock(Calls("Notify"), _)) | |
264 .WillOnce(VerifySummary( | |
265 base::UTF16ToUTF8(base::FormatPercent(42)) + " - The Title", 1)); | |
266 | |
267 CreateNotificationBridgeLinux(); | |
268 notification_bridge_linux_->Display( | |
269 NotificationCommon::PERSISTENT, "", "", false, | |
270 NotificationBuilder("") | |
271 .SetType(message_center::NOTIFICATION_TYPE_PROGRESS) | |
272 .SetProgress(42) | |
273 .SetTitle(base::UTF8ToUTF16("The Title")) | |
274 .GetResult()); | |
275 } | |
OLD | NEW |