Merge lp:~phablet-team/messaging-framework/catch-all-possible-exceptions into lp:messaging-framework
- catch-all-possible-exceptions
- Merge into trunk
Proposed by
Roberto Mier Escandon
Status: | Merged |
---|---|
Approved by: | Gustavo Pichorim Boiko |
Approved revision: | 45 |
Merged at revision: | 44 |
Proposed branch: | lp:~phablet-team/messaging-framework/catch-all-possible-exceptions |
Merge into: | lp:messaging-framework |
Diff against target: |
849 lines (+403/-170) 4 files modified
debian/changelog (+6/-0) src/messaging/member.cpp (+2/-2) src/messaging/qt/tp/connection.cpp (+169/-43) src/messaging/qt/tp/text_channel.cpp (+226/-125) |
To merge this branch: | bzr merge lp:~phablet-team/messaging-framework/catch-all-possible-exceptions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gustavo Pichorim Boiko (community) | Approve | ||
system-apps-ci-bot | continuous-integration | Approve | |
PS Jenkins bot | continuous-integration | Pending | |
Review via email: mp+299907@code.launchpad.net |
Commit message
Catched all plugin possible exceptions in messaging-fw
Description of the change
Catched all plugin possible exceptions in messaging-fw
To post a comment you must log in.
Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
review:
Approve
(continuous-integration)
Revision history for this message
Gustavo Pichorim Boiko (boiko) wrote : | # |
Looks good!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2016-07-08 13:55:33 +0000 |
3 | +++ debian/changelog 2016-07-13 04:54:46 +0000 |
4 | @@ -1,3 +1,9 @@ |
5 | +messaging-framework (0.1-1ubuntu20) vivid; urgency=medium |
6 | + |
7 | + * Controlling any plugin exception to avoid fw crashing |
8 | + |
9 | + -- Roberto Mier Escandon <roberto.escandon@canonical.com> Wed, 13 Jul 2016 12:48:54 +0800 |
10 | + |
11 | messaging-framework (0.1-1ubuntu19) vivid; urgency=medium |
12 | |
13 | * Set group title on creation |
14 | |
15 | === modified file 'src/messaging/member.cpp' |
16 | --- src/messaging/member.cpp 2016-07-05 13:47:29 +0000 |
17 | +++ src/messaging/member.cpp 2016-07-13 04:54:46 +0000 |
18 | @@ -2,7 +2,7 @@ |
19 | |
20 | struct messaging::Member::Private |
21 | { |
22 | - messaging::PendingStatus pending_list; |
23 | + messaging::PendingStatus pending_status; |
24 | }; |
25 | |
26 | messaging::Member::Member(std::string id, |
27 | @@ -15,7 +15,7 @@ |
28 | |
29 | messaging::PendingStatus messaging::Member::pending_status() const |
30 | { |
31 | - return impl->pending_list; |
32 | + return impl->pending_status; |
33 | } |
34 | |
35 | |
36 | |
37 | === modified file 'src/messaging/qt/tp/connection.cpp' |
38 | --- src/messaging/qt/tp/connection.cpp 2016-07-08 03:32:33 +0000 |
39 | +++ src/messaging/qt/tp/connection.cpp 2016-07-13 04:54:46 +0000 |
40 | @@ -193,14 +193,24 @@ |
41 | |
42 | // read the statuses supported by the plugin, and expose them to telepathy |
43 | Tp::SimpleStatusSpecMap statusMap; |
44 | - auto statuses = connection->presence_manager()->get_valid_statuses(); |
45 | - for (auto it = statuses.begin(); it != statuses.end(); ++it) |
46 | - { |
47 | - statusMap.insert(QString::fromStdString(it->first), |
48 | - Tp::SimpleStatusSpec{messaging_presence_type_to_telepathy(it->second.type), |
49 | - (it->second.flags & StatusSpec::Flags::may_set_on_self) == StatusSpec::Flags::may_set_on_self, |
50 | - (it->second.flags & StatusSpec::Flags::can_have_message) == StatusSpec::Flags::can_have_message}); |
51 | - } |
52 | + |
53 | + try |
54 | + { |
55 | + auto statuses = connection->presence_manager()->get_valid_statuses(); |
56 | + for (auto it = statuses.begin(); it != statuses.end(); ++it) |
57 | + { |
58 | + statusMap.insert(QString::fromStdString(it->first), |
59 | + Tp::SimpleStatusSpec{messaging_presence_type_to_telepathy(it->second.type), |
60 | + (it->second.flags & StatusSpec::Flags::may_set_on_self) == StatusSpec::Flags::may_set_on_self, |
61 | + (it->second.flags & StatusSpec::Flags::can_have_message) == StatusSpec::Flags::can_have_message}); |
62 | + } |
63 | + } |
64 | + catch (...) |
65 | + { |
66 | + LOG(ERROR) << "PresenceManager::get_valid_statuses() implementation throws exception. Please review. " \ |
67 | + "Providing empty valid statuses map to presence interface"; |
68 | + } |
69 | + |
70 | |
71 | simplePresenceIface->setStatuses(statusMap); |
72 | plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(simplePresenceIface)); |
73 | @@ -215,15 +225,30 @@ |
74 | |
75 | mqt::tp::Connection::~Connection() |
76 | { |
77 | - dbusConnection().unregisterObject(objectPath(), QDBusConnection::UnregisterTree); |
78 | - dbusConnection().unregisterService(busName()); |
79 | + try |
80 | + { |
81 | + dbusConnection().unregisterObject(objectPath(), QDBusConnection::UnregisterTree); |
82 | + dbusConnection().unregisterService(busName()); |
83 | + } |
84 | + catch (...) |
85 | + { |
86 | + LOG(ERROR) << "An exception has been thrown when unregistering telepathy connection object and service"; |
87 | + } |
88 | } |
89 | |
90 | void mqt::tp::Connection::onDisconnected() |
91 | { |
92 | setStatus(Tp::ConnectionStatusDisconnected, Tp::ConnectionStatusReasonRequested); |
93 | - connection->disconnect(); |
94 | - deleteLater(); |
95 | + |
96 | + try |
97 | + { |
98 | + connection->disconnect(); |
99 | + deleteLater(); |
100 | + } |
101 | + catch (...) |
102 | + { |
103 | + LOG(ERROR) << "An exception has been thrown when disconnecting framework connection implementation"; |
104 | + } |
105 | } |
106 | |
107 | void mqt::tp::Connection::on_message_without_chat_received(const Recipient::shared_ptr& recipient, const messaging::Message &message) |
108 | @@ -233,8 +258,8 @@ |
109 | return; |
110 | } |
111 | |
112 | - int handle = request_handles(Tp::HandleTypeContact, QStringList() << QString::fromStdString(recipient->id()), NULL)[0]; |
113 | Tp::DBusError error; |
114 | + int handle = request_handles(Tp::HandleTypeContact, QStringList() << QString::fromStdString(recipient->id()), &error)[0]; |
115 | QVariantMap request; |
116 | request[TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")] = TP_QT_IFACE_CHANNEL_TYPE_TEXT; |
117 | request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")] = Tp::HandleTypeContact; |
118 | @@ -257,8 +282,17 @@ |
119 | setStatus(static_cast<uint>(new_status), static_cast<uint>(reason)); |
120 | Tp::SimpleContactPresences presences; |
121 | Tp::SimplePresence presence; |
122 | + PresenceManager::StatusMap statuses; |
123 | |
124 | - auto statuses = connection->presence_manager()->get_valid_statuses(); |
125 | + try |
126 | + { |
127 | + statuses = connection->presence_manager()->get_valid_statuses(); |
128 | + } |
129 | + catch (...) |
130 | + { |
131 | + LOG(ERROR) << "PresenceManager::get_valid_statuses() implementation throws exception. Please review it. " \ |
132 | + "Providing empty valid statuses map to presence interface"; |
133 | + } |
134 | |
135 | if (static_cast<Tp::ConnectionStatus>(new_status) == Tp::ConnectionStatusConnected) |
136 | { |
137 | @@ -295,13 +329,22 @@ |
138 | return; |
139 | } |
140 | |
141 | - auto valid_statuses = connection->presence_manager()->get_valid_statuses(); |
142 | - if (valid_statuses.find(presence.status) == valid_statuses.end()) { |
143 | - LOG(ERROR) << "trying to set presence to " << presence.status << " that is not a valid presence status"; |
144 | - return; |
145 | + try |
146 | + { |
147 | + auto valid_statuses = connection->presence_manager()->get_valid_statuses(); |
148 | + if (valid_statuses.find(presence.status) == valid_statuses.end()) { |
149 | + LOG(ERROR) << "trying to set presence to " << presence.status << " that is not a valid presence status"; |
150 | + return; |
151 | + } |
152 | + } |
153 | + catch (...) |
154 | + { |
155 | + LOG(ERROR) << "PresenceManager::get_valid_statuses() implementation throws exception. Please review it. " \ |
156 | + "Providing empty valid statuses map to presence interface"; |
157 | } |
158 | |
159 | - int handle = request_handles(Tp::HandleTypeContact, QStringList() << QString::fromStdString(recipient->id()), NULL)[0]; |
160 | + Tp::DBusError error; |
161 | + int handle = request_handles(Tp::HandleTypeContact, QStringList() << QString::fromStdString(recipient->id()), &error)[0]; |
162 | Tp::SimpleContactPresences presences; |
163 | Tp::SimplePresence tpPresence = Tp::SimplePresence{messaging_presence_type_to_telepathy(presence.type), |
164 | QString::fromStdString(presence.status), |
165 | @@ -321,7 +364,16 @@ |
166 | |
167 | Tp::DBusError error; |
168 | int handle = request_handles(Tp::HandleTypeRoom, QStringList() << QString::fromStdString(new_group->id()), &error)[0]; |
169 | - QString initiator_normalized_id = QString::fromStdString(connection->normalize_identifier(initiator->id())); |
170 | + |
171 | + QString initiator_normalized_id = QString::fromStdString(initiator->id()); |
172 | + try |
173 | + { |
174 | + initiator_normalized_id = QString::fromStdString(connection->normalize_identifier(initiator->id())); |
175 | + } |
176 | + catch (...) |
177 | + { |
178 | + LOG(ERROR) << "An exception has been thrown when normalizing group initiator identifier. Using not normalized one"; |
179 | + } |
180 | int initiator_handle = request_handles(Tp::HandleTypeContact, QStringList() << initiator_normalized_id, &error)[0]; |
181 | |
182 | // if there is an error requesting handles, reject the group creation |
183 | @@ -337,6 +389,11 @@ |
184 | LOG(ERROR) << "Group rejection failed, " << e.what(); |
185 | error.set(TP_QT_ERROR_CANCELLED, "Group rejection failed"); |
186 | } |
187 | + catch (...) |
188 | + { |
189 | + LOG(ERROR) << "Group rejection failed"; |
190 | + error.set(TP_QT_ERROR_CANCELLED, "Group rejection failed"); |
191 | + } |
192 | return; |
193 | } |
194 | |
195 | @@ -409,26 +466,55 @@ |
196 | { |
197 | for (auto id : identifiers) |
198 | { |
199 | - QString normalizedId = connection->normalize_identifier(id.toStdString()).c_str(); |
200 | + QString normalizedId = id; |
201 | + try |
202 | + { |
203 | + normalizedId = connection->normalize_identifier(id.toStdString()).c_str(); |
204 | + } |
205 | + catch (...) |
206 | + { |
207 | + LOG(ERROR) << "An exception has been thrown when normalizing identifier. Using not normalized one"; |
208 | + return Tp::UIntList(); |
209 | + } |
210 | + |
211 | + |
212 | if (handles_.right.count(normalizedId)) |
213 | { |
214 | handles.append(handles_.right.at(normalizedId)); |
215 | } |
216 | else |
217 | { |
218 | - // before creating the handle, check that the id is valid |
219 | - if (!connection->is_valid_identifier(normalizedId.toStdString())) { |
220 | - if (error) { |
221 | - error->set(TP_QT_ERROR_INVALID_HANDLE, "Identifier not valid."); |
222 | + try |
223 | + { |
224 | + // before creating the handle, check that the id is valid |
225 | + if (!connection->is_valid_identifier(normalizedId.toStdString())) { |
226 | + if (error) { |
227 | + error->set(TP_QT_ERROR_INVALID_HANDLE, "Identifier not valid."); |
228 | + } |
229 | + return Tp::UIntList(); |
230 | } |
231 | + } |
232 | + catch (...) |
233 | + { |
234 | + LOG(ERROR) << "An exception has been thrown when evaluating messaging::Connection::is_valid_identifier() " \ |
235 | + "for identifier: " << normalizedId.toStdString() << " ,please review its implementation"; |
236 | return Tp::UIntList(); |
237 | } |
238 | |
239 | auto sample = ++counter; |
240 | handles_.insert(HandleIdPair(sample, normalizedId)); |
241 | handles.append(sample); |
242 | + |
243 | // request the presence status of the new handle |
244 | - connection->presence_manager()->request_presence(recipient_from_identifier(normalizedId.toStdString())); |
245 | + try |
246 | + { |
247 | + connection->presence_manager()->request_presence(recipient_from_identifier(normalizedId.toStdString())); |
248 | + } |
249 | + catch (...) |
250 | + { |
251 | + LOG(ERROR) << "An exception has been thrown when requesting presence for " << normalizedId.toStdString(); |
252 | + return Tp::UIntList(); |
253 | + } |
254 | } |
255 | } |
256 | } |
257 | @@ -475,7 +561,8 @@ |
258 | if (request.contains(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetID"))) |
259 | { |
260 | QString identifier = request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetID")].toString(); |
261 | - final_handle = request_handles(target_handle_type, QStringList() << identifier, NULL)[0]; |
262 | + Tp::DBusError error; |
263 | + final_handle = request_handles(target_handle_type, QStringList() << identifier, &error)[0]; |
264 | } |
265 | |
266 | return create_text_channel(target_handle_type, final_handle, request, error); |
267 | @@ -498,10 +585,10 @@ |
268 | |
269 | if (target_handle_type == Tp::HandleTypeRoom) |
270 | { |
271 | - std::shared_ptr<GroupStarter> group_starter = connection->group_starter(); |
272 | - messaging::Group::shared_ptr group = std::dynamic_pointer_cast<messaging::Group>(recipient); |
273 | try |
274 | { |
275 | + std::shared_ptr<GroupStarter> group_starter = connection->group_starter(); |
276 | + messaging::Group::shared_ptr group = std::dynamic_pointer_cast<messaging::Group>(recipient); |
277 | group_manager = group_starter->accept_group(group); |
278 | |
279 | // update recipient with id, title and members |
280 | @@ -518,6 +605,12 @@ |
281 | error->set(TP_QT_ERROR_CANCELLED, "Group creation rejected"); |
282 | return Tp::BaseChannelPtr{}; |
283 | } |
284 | + catch (...) |
285 | + { |
286 | + LOG(ERROR) << "Group creation rejected"; |
287 | + error->set(TP_QT_ERROR_CANCELLED, "Group creation rejected"); |
288 | + return Tp::BaseChannelPtr{}; |
289 | + } |
290 | } |
291 | } |
292 | // channel is created from app |
293 | @@ -533,10 +626,10 @@ |
294 | recipient = std::make_shared<messaging::Group>( |
295 | group_handles_.left.find(target_handle)->second.toLatin1().data()); |
296 | |
297 | - std::shared_ptr<GroupStarter> group_starter = connection->group_starter(); |
298 | - messaging::Group::shared_ptr group = std::dynamic_pointer_cast<messaging::Group>(recipient); |
299 | try |
300 | { |
301 | + std::shared_ptr<GroupStarter> group_starter = connection->group_starter(); |
302 | + messaging::Group::shared_ptr group = std::dynamic_pointer_cast<messaging::Group>(recipient); |
303 | group_manager = group_starter->rejoin_group(group); |
304 | |
305 | // update recipient with id, title and members |
306 | @@ -552,6 +645,12 @@ |
307 | error->set(TP_QT_ERROR_CANCELLED, "Group rejoin rejected"); |
308 | return Tp::BaseChannelPtr{}; |
309 | } |
310 | + catch (...) |
311 | + { |
312 | + LOG(ERROR) << "Group rejoin rejected"; |
313 | + error->set(TP_QT_ERROR_CANCELLED, "Group rejoin rejected"); |
314 | + return Tp::BaseChannelPtr{}; |
315 | + } |
316 | break; |
317 | } |
318 | case Tp::HandleTypeNone: { |
319 | @@ -566,7 +665,17 @@ |
320 | hints[TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeIDs")].toStringList(); |
321 | for (QString initial_invitee_id : initial_invitees_ids) |
322 | { |
323 | - std::string normalized_id = connection->normalize_identifier(initial_invitee_id.toStdString()); |
324 | + std::string normalized_id = initial_invitee_id.toStdString(); |
325 | + try |
326 | + { |
327 | + normalized_id = connection->normalize_identifier(normalized_id); |
328 | + } |
329 | + catch (...) |
330 | + { |
331 | + LOG(ERROR) << "An exception has been thrown when normalizing identifier " << normalized_id |
332 | + << " using not normalized version"; |
333 | + } |
334 | + |
335 | //FIXME: get contact attribute display name for the user second param |
336 | initial_invitees.push_back(std::make_shared<Member>(normalized_id, PendingStatus::Remote, std::string{}/* display_name*/ )); |
337 | } |
338 | @@ -590,10 +699,10 @@ |
339 | initial_invitees, |
340 | title); |
341 | |
342 | - std::shared_ptr<GroupStarter> group_starter = connection->group_starter(); |
343 | - messaging::Group::shared_ptr group = std::dynamic_pointer_cast<messaging::Group>(recipient); |
344 | try |
345 | { |
346 | + std::shared_ptr<GroupStarter> group_starter = connection->group_starter(); |
347 | + messaging::Group::shared_ptr group = std::dynamic_pointer_cast<messaging::Group>(recipient); |
348 | group_manager = group_starter->create_group(group); |
349 | |
350 | // update recipient with id, title and members |
351 | @@ -608,9 +717,16 @@ |
352 | error->set(TP_QT_ERROR_CANCELLED, "Group creation rejected"); |
353 | return Tp::BaseChannelPtr{}; |
354 | } |
355 | + catch (...) |
356 | + { |
357 | + LOG(ERROR) << "Group creation rejected"; |
358 | + error->set(TP_QT_ERROR_CANCELLED, "Group creation rejected"); |
359 | + return Tp::BaseChannelPtr{}; |
360 | + } |
361 | |
362 | // request handle from group_manager id, filled with the group id after calling start_group() |
363 | - target_handle = request_handles(Tp::HandleTypeRoom, QStringList() << QString::fromStdString(group_manager->group_id()), NULL)[0]; |
364 | + Tp::DBusError error; |
365 | + target_handle = request_handles(Tp::HandleTypeRoom, QStringList() << QString::fromStdString(group_manager->group_id()), &error)[0]; |
366 | break; |
367 | } |
368 | default: |
369 | @@ -619,14 +735,24 @@ |
370 | } |
371 | } |
372 | |
373 | - return Tp::BaseChannelPtr{mqt::tp::TextChannel::create( |
374 | - this, |
375 | - target_handle, |
376 | - target_handle_type, |
377 | - runtime, |
378 | - connection->messenger(), |
379 | - recipient, |
380 | - group_manager)}; |
381 | + Tp::BaseChannelPtr text_channel; |
382 | + |
383 | + try |
384 | + { |
385 | + text_channel = Tp::BaseChannelPtr{mqt::tp::TextChannel::create(this, |
386 | + target_handle, |
387 | + target_handle_type, |
388 | + runtime, |
389 | + connection->messenger(), |
390 | + recipient, |
391 | + group_manager)}; |
392 | + } |
393 | + catch (...) |
394 | + { |
395 | + LOG(ERROR) << "An exception has been thrown when creating the text channel"; |
396 | + } |
397 | + |
398 | + return text_channel; |
399 | } |
400 | |
401 | Tp::ContactAttributesMap mqt::tp::Connection::get_contact_attributes(const Tp::UIntList &handles, const QStringList &ifaces, Tp::DBusError *error) |
402 | |
403 | === modified file 'src/messaging/qt/tp/text_channel.cpp' |
404 | --- src/messaging/qt/tp/text_channel.cpp 2016-07-05 13:47:29 +0000 |
405 | +++ src/messaging/qt/tp/text_channel.cpp 2016-07-13 04:54:46 +0000 |
406 | @@ -87,21 +87,29 @@ |
407 | |
408 | QByteArray read_file_content(const std::string& filename) |
409 | { |
410 | - std::ifstream fin(filename, std::ifstream::binary); |
411 | - std::ostringstream ostrm; |
412 | - ostrm << fin.rdbuf(); |
413 | - std::string data(ostrm.str()); |
414 | - return QByteArray(data.data(), data.size()); |
415 | + try |
416 | + { |
417 | + std::ifstream fin(filename, std::ifstream::binary); |
418 | + std::ostringstream ostrm; |
419 | + ostrm << fin.rdbuf(); |
420 | + std::string data(ostrm.str()); |
421 | + return QByteArray(data.data(), data.size()); |
422 | + } |
423 | + catch (...) |
424 | + { |
425 | + LOG(ERROR) << "An exception has been thrown when reading file " << filename; |
426 | + return QByteArray(); |
427 | + } |
428 | } |
429 | |
430 | messaging::Message make_message(const Tp::MessagePartList &message) |
431 | { |
432 | using namespace messaging::qt::tp; |
433 | messaging::Message mf_message{boost::uuids::to_string(boost::uuids::random_generator()()), |
434 | - std::string(), // sender can be empty on outgoing messages |
435 | - std::string(), // actual message will be filled below |
436 | - std::chrono::system_clock::now(), |
437 | - std::vector<messaging::Attachment>()}; |
438 | + std::string(), // sender can be empty on outgoing messages |
439 | + std::string(), // actual message will be filled below |
440 | + std::chrono::system_clock::now(), |
441 | + std::vector<messaging::Attachment>()}; |
442 | for (auto part : message) |
443 | { |
444 | messaging::Attachment attachment; |
445 | @@ -293,8 +301,25 @@ |
446 | } |
447 | |
448 | // is this needed, or should we use same observer than the used for the chat when plugged as chat interface? |
449 | - group_manager->set_observer(observer); |
450 | - chat->plug_interface(group_manager); |
451 | + try |
452 | + { |
453 | + group_manager->set_observer(observer); |
454 | + } |
455 | + catch (...) |
456 | + { |
457 | + LOG(ERROR) << "An exception has been thrown when setting group manager observer"; |
458 | + return; |
459 | + } |
460 | + |
461 | + try |
462 | + { |
463 | + chat->plug_interface(group_manager); |
464 | + } |
465 | + catch (...) |
466 | + { |
467 | + LOG(ERROR) << "An exception has been thrown when pluging in group manager as chat interface"; |
468 | + return; |
469 | + } |
470 | |
471 | // initialize the telepathy room interface |
472 | messaging::Group::shared_ptr group = std::dynamic_pointer_cast<messaging::Group>(recipient); |
473 | @@ -308,15 +333,38 @@ |
474 | /* creatorHandle */ 0, |
475 | /* creationTimestamp */ QDateTime()); |
476 | room_config_interface = Tp::BaseChannelRoomConfigInterface::create(); |
477 | - room_config_interface->setTitle(QString::fromStdString(group_manager->group_title())); |
478 | + |
479 | + try |
480 | + { |
481 | + room_config_interface->setTitle(QString::fromStdString(group_manager->group_title())); |
482 | + } |
483 | + catch (...) |
484 | + { |
485 | + LOG(ERROR) << "An exception has been thrown when setting group title"; |
486 | + return; |
487 | + } |
488 | + |
489 | room_config_interface->setConfigurationRetrieved(true); |
490 | room_config_interface->setCanUpdateConfiguration(true); |
491 | |
492 | // FIXME: check what flags we want by default |
493 | - Tp::ChannelGroupFlags groupFlags = Tp::ChannelGroupFlagCanAdd|Tp::ChannelGroupFlagCanRemove|Tp::ChannelGroupFlagHandleOwnersNotAvailable|Tp::ChannelGroupFlagMembersChangedDetailed|Tp::ChannelGroupFlagProperties; |
494 | + Tp::ChannelGroupFlags groupFlags = Tp::ChannelGroupFlagCanAdd | |
495 | + Tp::ChannelGroupFlagCanRemove | |
496 | + Tp::ChannelGroupFlagHandleOwnersNotAvailable | |
497 | + Tp::ChannelGroupFlagMembersChangedDetailed | |
498 | + Tp::ChannelGroupFlagProperties; |
499 | group_interface = Tp::BaseChannelGroupInterface::create(); |
500 | group_interface->setGroupFlags(groupFlags); |
501 | - group_interface->setSelfHandle(tp_connection->selfHandle()); |
502 | + |
503 | + try |
504 | + { |
505 | + group_interface->setSelfHandle(tp_connection->selfHandle()); |
506 | + } |
507 | + catch (...) |
508 | + { |
509 | + LOG(ERROR) << "An exception has been thrown when setting group self handle"; |
510 | + return; |
511 | + } |
512 | |
513 | // we need to plug this interface here to avoid a crash |
514 | plug_interface_if_available(group_interface); |
515 | @@ -350,60 +398,69 @@ |
516 | |
517 | void mqt::tp::TextChannel::on_message_received(const messaging::Message& message) |
518 | { |
519 | - auto time = std::chrono::system_clock::now(); |
520 | - |
521 | - Tp::MessagePartList parts; |
522 | - Tp::MessagePart header; |
523 | - header["message-token"] = QDBusVariant(QString::fromStdString(message.id)); |
524 | - header["message-received"] = QDBusVariant(static_cast<uint>(std::chrono::system_clock::to_time_t(time))); |
525 | - if (targetHandleType() == Tp::HandleTypeContact) { |
526 | - header["message-sender"] = QDBusVariant((qulonglong)targetHandle()); |
527 | - } else { |
528 | - uint id = tp_connection->requestHandles(Tp::HandleTypeContact, QStringList() << QString::fromStdString(message.sender), 0)[0]; |
529 | - header["message-sender"] = QDBusVariant(id); |
530 | - } |
531 | - header["message-type"] = QDBusVariant(Tp::ChannelTextMessageTypeNormal); |
532 | - |
533 | - parts << header; |
534 | - |
535 | - bool has_pending_file_transfer = false; |
536 | - for (auto attachment : message.attachments) { |
537 | - Tp::MessagePart part; |
538 | - QString contentType; |
539 | - QByteArray content(attachment.content->as_data(), attachment.content->data_size()); |
540 | - if (attachment.content_type.empty()) { |
541 | - contentType = guess_content_type(content); |
542 | - } else { |
543 | - contentType = QString::fromStdString(attachment.content_type); |
544 | - } |
545 | - part[message::keys::content_type] = QDBusVariant(contentType); |
546 | - part[message::keys::content] = QDBusVariant(content); |
547 | - part[message::keys::identifier] = QDBusVariant(QString::fromStdString(attachment.id)); |
548 | - if (attachment.status == messaging::AttachmentStatus::AttachmentPending) { |
549 | - has_pending_file_transfer = true; |
550 | - part[message::keys::size] = QDBusVariant(QVariant::fromValue(attachment.size)); |
551 | - part[message::keys::needs_retrieval] = QDBusVariant(true); |
552 | - // for now we trigger the download ourselves, but we need to |
553 | - // allow clients to do that |
554 | - part[message::keys::filename] = QDBusVariant(QString::fromStdString((chat->download_file(attachment.id)))); |
555 | - } |
556 | - parts << part; |
557 | - } |
558 | - |
559 | - // check if comes text into message.message and add a text plain part if so |
560 | - if (!message.message.empty()) { |
561 | - Tp::MessagePart text_part; |
562 | - text_part[message::keys::content_type] = QDBusVariant("text/plain"); |
563 | - text_part[message::keys::identifier] = QDBusVariant("text_0.txt"); |
564 | - text_part[message::keys::content] = QDBusVariant(QString::fromStdString(message.message)); |
565 | - text_part[message::keys::size] = QDBusVariant(QVariant::fromValue((qulonglong)message.message.length())); |
566 | - parts << text_part; |
567 | - } |
568 | - |
569 | - if (has_pending_file_transfer) { |
570 | - pending_messages[message.id] = parts; |
571 | - } else { |
572 | - text_type_interface->addReceivedMessage(parts); |
573 | + try |
574 | + { |
575 | + auto time = std::chrono::system_clock::now(); |
576 | + |
577 | + Tp::MessagePartList parts; |
578 | + Tp::MessagePart header; |
579 | + header["message-token"] = QDBusVariant(QString::fromStdString(message.id)); |
580 | + header["message-received"] = QDBusVariant(static_cast<uint>(std::chrono::system_clock::to_time_t(time))); |
581 | + if (targetHandleType() == Tp::HandleTypeContact) { |
582 | + header["message-sender"] = QDBusVariant((qulonglong)targetHandle()); |
583 | + } else { |
584 | + Tp::DBusError error; |
585 | + uint id = tp_connection->requestHandles(Tp::HandleTypeContact, QStringList() << QString::fromStdString(message.sender), &error)[0]; |
586 | + header["message-sender"] = QDBusVariant(id); |
587 | + } |
588 | + header["message-type"] = QDBusVariant(Tp::ChannelTextMessageTypeNormal); |
589 | + |
590 | + parts << header; |
591 | + |
592 | + bool has_pending_file_transfer = false; |
593 | + for (auto attachment : message.attachments) { |
594 | + Tp::MessagePart part; |
595 | + QString contentType; |
596 | + QByteArray content(attachment.content->as_data(), attachment.content->data_size()); |
597 | + if (attachment.content_type.empty()) { |
598 | + contentType = guess_content_type(content); |
599 | + } else { |
600 | + contentType = QString::fromStdString(attachment.content_type); |
601 | + } |
602 | + part[message::keys::content_type] = QDBusVariant(contentType); |
603 | + part[message::keys::content] = QDBusVariant(content); |
604 | + part[message::keys::identifier] = QDBusVariant(QString::fromStdString(attachment.id)); |
605 | + if (attachment.status == messaging::AttachmentStatus::AttachmentPending) { |
606 | + has_pending_file_transfer = true; |
607 | + part[message::keys::size] = QDBusVariant(QVariant::fromValue(attachment.size)); |
608 | + part[message::keys::needs_retrieval] = QDBusVariant(true); |
609 | + // for now we trigger the download ourselves, but we need to |
610 | + // allow clients to do that |
611 | + part[message::keys::filename] = QDBusVariant(QString::fromStdString((chat->download_file(attachment.id)))); |
612 | + } |
613 | + parts << part; |
614 | + } |
615 | + |
616 | + // check if comes text into message.message and add a text plain part if so |
617 | + if (!message.message.empty()) { |
618 | + Tp::MessagePart text_part; |
619 | + text_part[message::keys::content_type] = QDBusVariant("text/plain"); |
620 | + text_part[message::keys::identifier] = QDBusVariant("text_0.txt"); |
621 | + text_part[message::keys::content] = QDBusVariant(QString::fromStdString(message.message)); |
622 | + text_part[message::keys::size] = QDBusVariant(QVariant::fromValue((qulonglong)message.message.length())); |
623 | + parts << text_part; |
624 | + } |
625 | + |
626 | + if (has_pending_file_transfer) { |
627 | + pending_messages[message.id] = parts; |
628 | + } else { |
629 | + text_type_interface->addReceivedMessage(parts); |
630 | + } |
631 | + |
632 | + } |
633 | + catch (...) |
634 | + { |
635 | + LOG(ERROR) << "An exception has happened when evaluating a received message"; |
636 | } |
637 | } |
638 | |
639 | @@ -633,61 +690,85 @@ |
640 | catch (const std::exception& e) |
641 | { |
642 | error->set(TP_QT_ERROR_NOT_AVAILABLE, QString::fromStdString(e.what())); |
643 | + LOG(ERROR) << "An exception has been thrown when sending a message: " << e.what(); |
644 | return the_invalid_id; |
645 | } |
646 | catch (...) |
647 | { |
648 | + LOG(ERROR) << "An exception has been thrown when sending a message"; |
649 | + error->set(TP_QT_ERROR_NOT_AVAILABLE, ""); |
650 | + return the_invalid_id; |
651 | } |
652 | - |
653 | - error->set(TP_QT_ERROR_NOT_AVAILABLE, ""); |
654 | - return the_invalid_id; |
655 | } |
656 | |
657 | void mqt::tp::TextChannel::message_acknowledged(const QString &id) |
658 | { |
659 | std::cout << __PRETTY_FUNCTION__ << std::endl; |
660 | - chat->mark_message_as_read(id.toStdString()); |
661 | + try |
662 | + { |
663 | + chat->mark_message_as_read(id.toStdString()); |
664 | + } |
665 | + catch (...) |
666 | + { |
667 | + LOG(ERROR) << "An exception has been thrown when marking message as read"; |
668 | + } |
669 | } |
670 | |
671 | void mqt::tp::TextChannel::add_members(const Tp::UIntList& handles, const QString& message, Tp::DBusError* error) |
672 | { |
673 | Q_UNUSED(message); |
674 | - std::shared_ptr<messaging::GroupManager> group_manager = chat->interface<GroupManager>(); |
675 | - |
676 | - if (!group_manager) { |
677 | - error->set(TP_QT_ERROR_NOT_AVAILABLE, "Text channel is not a room"); |
678 | - return; |
679 | - } |
680 | - |
681 | - QStringList ids = tp_connection->inspectHandles(Tp::HandleTypeContact, handles, 0); |
682 | - messaging::Members members; |
683 | - for (QString id : ids) |
684 | - { |
685 | - members.push_back(std::make_shared<messaging::Member>(id.toStdString())); |
686 | - } |
687 | - |
688 | - group_manager->add_members(members); |
689 | + |
690 | + try |
691 | + { |
692 | + std::shared_ptr<messaging::GroupManager> group_manager = chat->interface<GroupManager>(); |
693 | + |
694 | + if (!group_manager) { |
695 | + error->set(TP_QT_ERROR_NOT_AVAILABLE, "Text channel is not a room"); |
696 | + return; |
697 | + } |
698 | + |
699 | + QStringList ids = tp_connection->inspectHandles(Tp::HandleTypeContact, handles, 0); |
700 | + messaging::Members members; |
701 | + for (QString id : ids) |
702 | + { |
703 | + members.push_back(std::make_shared<messaging::Member>(id.toStdString())); |
704 | + } |
705 | + |
706 | + group_manager->add_members(members); |
707 | + } |
708 | + catch (...) |
709 | + { |
710 | + LOG(ERROR) << "An exception has been thrown when trying to add members to a group"; |
711 | + } |
712 | } |
713 | |
714 | void mqt::tp::TextChannel::remove_members(const Tp::UIntList& handles, const QString& message, uint reason, Tp::DBusError* error) |
715 | { |
716 | Q_UNUSED(message); |
717 | Q_UNUSED(reason); |
718 | - std::shared_ptr<messaging::GroupManager> group_manager = chat->interface<GroupManager>(); |
719 | - |
720 | - if (!group_manager) { |
721 | - error->set(TP_QT_ERROR_NOT_AVAILABLE, "Text channel is not a room"); |
722 | - return; |
723 | - } |
724 | - |
725 | - QStringList ids = tp_connection->inspectHandles(Tp::HandleTypeContact, handles, 0); |
726 | - messaging::Members members; |
727 | - for (QString id : ids) |
728 | - { |
729 | - members.push_back(std::make_shared<messaging::Member>(id.toStdString())); |
730 | - } |
731 | - |
732 | - group_manager->remove_members(members); |
733 | + |
734 | + try |
735 | + { |
736 | + std::shared_ptr<messaging::GroupManager> group_manager = chat->interface<GroupManager>(); |
737 | + |
738 | + if (!group_manager) { |
739 | + error->set(TP_QT_ERROR_NOT_AVAILABLE, "Text channel is not a room"); |
740 | + return; |
741 | + } |
742 | + |
743 | + QStringList ids = tp_connection->inspectHandles(Tp::HandleTypeContact, handles, 0); |
744 | + messaging::Members members; |
745 | + for (QString id : ids) |
746 | + { |
747 | + members.push_back(std::make_shared<messaging::Member>(id.toStdString())); |
748 | + } |
749 | + |
750 | + group_manager->remove_members(members); |
751 | + } |
752 | + catch (...) |
753 | + { |
754 | + LOG(ERROR) << "An exception has been thrown when trying to remove members from a group"; |
755 | + } |
756 | } |
757 | |
758 | |
759 | @@ -695,17 +776,24 @@ |
760 | { |
761 | Q_UNUSED(error); |
762 | |
763 | - switch (state) { |
764 | - case Tp::ChannelChatStateComposing: |
765 | - chat->start_typing(); |
766 | - break; |
767 | - case Tp::ChannelChatStateActive: |
768 | - case Tp::ChannelChatStateGone: |
769 | - case Tp::ChannelChatStateInactive: |
770 | - case Tp::ChannelChatStatePaused: |
771 | - default: |
772 | - chat->end_typing(); |
773 | - break; |
774 | + try |
775 | + { |
776 | + switch (state) { |
777 | + case Tp::ChannelChatStateComposing: |
778 | + chat->start_typing(); |
779 | + break; |
780 | + case Tp::ChannelChatStateActive: |
781 | + case Tp::ChannelChatStateGone: |
782 | + case Tp::ChannelChatStateInactive: |
783 | + case Tp::ChannelChatStatePaused: |
784 | + default: |
785 | + chat->end_typing(); |
786 | + break; |
787 | + } |
788 | + } |
789 | + catch (...) |
790 | + { |
791 | + LOG(ERROR) << "An exception has been thrown when updating typing signal"; |
792 | } |
793 | } |
794 | |
795 | @@ -717,30 +805,43 @@ |
796 | return; |
797 | } |
798 | |
799 | - std::shared_ptr<messaging::GroupManager> group_manager = chat->interface<GroupManager>(); |
800 | - if (!group_manager) { |
801 | - error->set(TP_QT_ERROR_NOT_AVAILABLE, "Text channel is not a room"); |
802 | - return; |
803 | - } |
804 | + try |
805 | + { |
806 | + std::shared_ptr<messaging::GroupManager> group_manager = chat->interface<GroupManager>(); |
807 | + if (!group_manager) { |
808 | + error->set(TP_QT_ERROR_NOT_AVAILABLE, "Text channel is not a room"); |
809 | + return; |
810 | + } |
811 | |
812 | - group_manager->change_group_title(properties["Title"].toString().toStdString()); |
813 | + group_manager->change_group_title(properties["Title"].toString().toStdString()); |
814 | + } |
815 | + catch (...) |
816 | + { |
817 | + LOG(ERROR) << "An exception has been thrown when updating group configuration"; |
818 | + } |
819 | } |
820 | |
821 | void mqt::tp::TextChannel::destroy(Tp::DBusError* error) |
822 | { |
823 | - std::shared_ptr<messaging::GroupManager> group_manager = chat->interface<GroupManager>(); |
824 | - if (!group_manager) { |
825 | - error->set(TP_QT_ERROR_NOT_AVAILABLE, "Text channel is not a room"); |
826 | - return; |
827 | - } |
828 | - |
829 | try |
830 | { |
831 | + std::shared_ptr<messaging::GroupManager> group_manager = chat->interface<GroupManager>(); |
832 | + if (!group_manager) { |
833 | + error->set(TP_QT_ERROR_NOT_AVAILABLE, "Text channel is not a room"); |
834 | + return; |
835 | + } |
836 | + |
837 | group_manager->dissolve_group(); |
838 | } |
839 | catch (const std::exception& e) |
840 | { |
841 | error->set(TP_QT_ERROR_RESOURCE_UNAVAILABLE, QString("Failed to destroy: %1").arg(e.what())); |
842 | + LOG(ERROR) << "An exception has been thrown when destroying a group: " << e.what(); |
843 | + } |
844 | + catch (...) |
845 | + { |
846 | + error->set(TP_QT_ERROR_RESOURCE_UNAVAILABLE, QString("Failed to destroy")); |
847 | + LOG(ERROR) << "An exception has been thrown when destroying a group"; |
848 | } |
849 | } |
850 |
PASSED: Continuous integration, rev:45 /jenkins. canonical. com/system- apps/job/ lp-messaging- framework- ci/17/ /jenkins. canonical. com/system- apps/job/ build/956 /jenkins. canonical. com/system- apps/job/ test-0- autopkgtest/ label=phone- armhf,release= vivid+overlay, testname= default/ 171 /jenkins. canonical. com/system- apps/job/ build-0- fetch/956 /jenkins. canonical. com/system- apps/job/ build-1- sourcepkg/ release= vivid+overlay/ 860 /jenkins. canonical. com/system- apps/job/ build-1- sourcepkg/ release= xenial+ overlay/ 860 /jenkins. canonical. com/system- apps/job/ build-1- sourcepkg/ release= yakkety/ 860 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 857/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 857/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 857/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 857/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 857/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 857/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 857/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 857/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= yakkety/ 857 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= yakkety/ 857/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/system- apps/job/ lp-messaging- framework- ci/17/rebuild
https:/