1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "notification_content.h"
17 #include "ans_log_wrapper.h"
18 #include "notification_local_live_view_content.h"
19
20 namespace OHOS {
21 namespace Notification {
22 std::map<std::string, NotificationContent::Type> NotificationContent::convertStrToContentType_;
23
NotificationContent(const std::shared_ptr<NotificationNormalContent> & normalContent)24 NotificationContent::NotificationContent(const std::shared_ptr<NotificationNormalContent> &normalContent)
25 {
26 if (!normalContent) {
27 ANS_LOGE("NotificationNormalContent can not be null");
28 return;
29 }
30
31 contentType_ = NotificationContent::Type::BASIC_TEXT;
32 content_ = normalContent;
33 }
34
NotificationContent(const std::shared_ptr<NotificationLongTextContent> & longTextContent)35 NotificationContent::NotificationContent(const std::shared_ptr<NotificationLongTextContent> &longTextContent)
36 {
37 if (!longTextContent) {
38 ANS_LOGE("NotificationLongTextContent can not be null");
39 return;
40 }
41
42 contentType_ = NotificationContent::Type::LONG_TEXT;
43 content_ = longTextContent;
44 }
45
NotificationContent(const std::shared_ptr<NotificationPictureContent> & pictureContent)46 NotificationContent::NotificationContent(const std::shared_ptr<NotificationPictureContent> &pictureContent)
47 {
48 if (!pictureContent) {
49 ANS_LOGE("NotificationPictureContent can not be null");
50 return;
51 }
52
53 contentType_ = NotificationContent::Type::PICTURE;
54 content_ = pictureContent;
55 }
56
NotificationContent(const std::shared_ptr<NotificationConversationalContent> & conversationContent)57 NotificationContent::NotificationContent(const std::shared_ptr<NotificationConversationalContent> &conversationContent)
58 {
59 if (!conversationContent) {
60 ANS_LOGE("NotificationConversationalContent can not be null");
61 return;
62 }
63
64 contentType_ = NotificationContent::Type::CONVERSATION;
65 content_ = conversationContent;
66 }
67
NotificationContent(const std::shared_ptr<NotificationMultiLineContent> & multiLineContent)68 NotificationContent::NotificationContent(const std::shared_ptr<NotificationMultiLineContent> &multiLineContent)
69 {
70 if (!multiLineContent) {
71 ANS_LOGE("NotificationMultiLineContent can not be null");
72 return;
73 }
74
75 contentType_ = NotificationContent::Type::MULTILINE;
76 content_ = multiLineContent;
77 }
78
NotificationContent(const std::shared_ptr<NotificationMediaContent> & mediaContent)79 NotificationContent::NotificationContent(const std::shared_ptr<NotificationMediaContent> &mediaContent)
80 {
81 if (!mediaContent) {
82 ANS_LOGE("NotificationMediaContent can not be null");
83 return;
84 }
85
86 contentType_ = NotificationContent::Type::MEDIA;
87 content_ = mediaContent;
88 }
89
NotificationContent(const std::shared_ptr<NotificationLocalLiveViewContent> & localLiveViewContent)90 NotificationContent::NotificationContent(const std::shared_ptr<NotificationLocalLiveViewContent> &localLiveViewContent)
91 {
92 if (!localLiveViewContent) {
93 ANS_LOGE("NotificationLocalLiveViewContent can not be null");
94 return;
95 }
96
97 contentType_ = NotificationContent::Type::LOCAL_LIVE_VIEW;
98 content_ = localLiveViewContent;
99 content_->SetContentType(static_cast<int32_t>(NotificationContent::Type::LOCAL_LIVE_VIEW));
100 }
101
NotificationContent(const std::shared_ptr<NotificationLiveViewContent> & liveViewContent)102 NotificationContent::NotificationContent(const std::shared_ptr<NotificationLiveViewContent> &liveViewContent)
103 {
104 if (!liveViewContent) {
105 ANS_LOGE("NotificationLiveViewContent can not be null");
106 return;
107 }
108
109 contentType_ = NotificationContent::Type::LIVE_VIEW;
110 content_ = liveViewContent;
111 }
112
~NotificationContent()113 NotificationContent::~NotificationContent()
114 {}
115
GetContentType() const116 NotificationContent::Type NotificationContent::GetContentType() const
117 {
118 return contentType_;
119 }
120
GetNotificationContent() const121 std::shared_ptr<NotificationBasicContent> NotificationContent::GetNotificationContent() const
122 {
123 return content_;
124 }
125
Dump()126 std::string NotificationContent::Dump()
127 {
128 std::string contentTypeStr = (contentType_ == NotificationContent::Type::BASIC_TEXT) ? "BASIC_TEXT"
129 : (contentType_ == NotificationContent::Type::CONVERSATION) ? "CONVERSATION"
130 : (contentType_ == NotificationContent::Type::LONG_TEXT) ? "LONG_TEXT"
131 : (contentType_ == NotificationContent::Type::MEDIA) ? "MEDIA"
132 : (contentType_ == NotificationContent::Type::MULTILINE) ? "MULTILINE"
133 : (contentType_ == NotificationContent::Type::PICTURE) ? "PICTURE"
134 : (contentType_ == NotificationContent::Type::LOCAL_LIVE_VIEW) ? "LOCAL_LIVE_VIEW"
135 : (contentType_ == NotificationContent::Type::LIVE_VIEW) ? "LIVE_VIEW"
136 : "NONE";
137 return "NotificationContent{ "
138 "contentType = " + contentTypeStr +
139 ", content = " + (content_ ? content_->Dump() : "null") +
140 " }";
141 }
142
ToJson(nlohmann::json & jsonObject) const143 bool NotificationContent::ToJson(nlohmann::json &jsonObject) const
144 {
145 jsonObject["contentType"] = static_cast<int32_t>(contentType_);
146 jsonObject["notificationContentType"] = static_cast<int32_t>(contentType_);
147
148 if (!content_) {
149 ANS_LOGE("Invalid content. Cannot convert to JSON.");
150 return false;
151 }
152
153 nlohmann::json contentObj;
154 if (!NotificationJsonConverter::ConvertToJson(content_.get(), contentObj)) {
155 ANS_LOGE("Cannot convert content to JSON");
156 return false;
157 }
158 jsonObject["content"] = contentObj;
159
160 return true;
161 }
162
FromJson(const nlohmann::json & jsonObject)163 NotificationContent *NotificationContent::FromJson(const nlohmann::json &jsonObject)
164 {
165 if (jsonObject.is_null() or !jsonObject.is_object()) {
166 ANS_LOGE("Invalid JSON object");
167 return nullptr;
168 }
169 const auto &jsonEnd = jsonObject.cend();
170 if ((jsonObject.find("contentType") == jsonEnd) || (jsonObject.find("content") == jsonEnd)) {
171 ANS_LOGE("Incomplete NotificationContent json object. Cannot convert content from JSON.");
172 return nullptr;
173 }
174
175 auto pContent = new (std::nothrow) NotificationContent();
176 if (pContent == nullptr) {
177 ANS_LOGE("Failed to create NotificationContent instance");
178 return nullptr;
179 }
180
181 if (!ConvertJsonToContent(pContent, jsonObject)) {
182 delete pContent;
183 pContent = nullptr;
184 return nullptr;
185 }
186
187 return pContent;
188 }
189
Marshalling(Parcel & parcel) const190 bool NotificationContent::Marshalling(Parcel &parcel) const
191 {
192 if (!parcel.WriteInt32(static_cast<int32_t>(contentType_))) {
193 ANS_LOGE("Failed to write contentType");
194 return false;
195 }
196
197 auto valid = content_ ? true : false;
198 if (!parcel.WriteBool(valid)) {
199 ANS_LOGE("Failed to write the flag which indicate whether content is null");
200 return false;
201 }
202
203 if (valid) {
204 if (!parcel.WriteParcelable(content_.get())) {
205 ANS_LOGE("Failed to write content");
206 return false;
207 }
208 }
209
210 return true;
211 }
212
Unmarshalling(Parcel & parcel)213 NotificationContent *NotificationContent::Unmarshalling(Parcel &parcel)
214 {
215 auto pContent = new (std::nothrow) NotificationContent();
216 if ((pContent != nullptr) && !pContent->ReadFromParcel(parcel)) {
217 delete pContent;
218 pContent = nullptr;
219 }
220
221 return pContent;
222 }
223
ReadFromParcel(Parcel & parcel)224 bool NotificationContent::ReadFromParcel(Parcel &parcel)
225 {
226 contentType_ = static_cast<NotificationContent::Type>(parcel.ReadInt32());
227
228 if (!parcel.ReadBool()) {
229 return true;
230 }
231
232 switch (contentType_) {
233 case NotificationContent::Type::BASIC_TEXT:
234 content_ = std::static_pointer_cast<NotificationBasicContent>(
235 std::shared_ptr<NotificationNormalContent>(parcel.ReadParcelable<NotificationNormalContent>()));
236 break;
237 case NotificationContent::Type::CONVERSATION:
238 content_ =
239 std::static_pointer_cast<NotificationBasicContent>(std::shared_ptr<NotificationConversationalContent>(
240 parcel.ReadParcelable<NotificationConversationalContent>()));
241 break;
242 case NotificationContent::Type::LONG_TEXT:
243 content_ = std::static_pointer_cast<NotificationBasicContent>(
244 std::shared_ptr<NotificationLongTextContent>(parcel.ReadParcelable<NotificationLongTextContent>()));
245 break;
246 case NotificationContent::Type::MEDIA:
247 content_ = std::static_pointer_cast<NotificationBasicContent>(
248 std::shared_ptr<NotificationMediaContent>(parcel.ReadParcelable<NotificationMediaContent>()));
249 break;
250 case NotificationContent::Type::MULTILINE:
251 content_ = std::static_pointer_cast<NotificationBasicContent>(
252 std::shared_ptr<NotificationMultiLineContent>(parcel.ReadParcelable<NotificationMultiLineContent>()));
253 break;
254 case NotificationContent::Type::PICTURE:
255 content_ = std::static_pointer_cast<NotificationBasicContent>(
256 std::shared_ptr<NotificationPictureContent>(parcel.ReadParcelable<NotificationPictureContent>()));
257 break;
258 case NotificationContent::Type::LOCAL_LIVE_VIEW:
259 content_ = std::static_pointer_cast<NotificationBasicContent>(
260 std::shared_ptr<NotificationLocalLiveViewContent>(
261 parcel.ReadParcelable<NotificationLocalLiveViewContent>()));
262 break;
263 case NotificationContent::Type::LIVE_VIEW:
264 content_ = std::static_pointer_cast<NotificationBasicContent>(
265 std::shared_ptr<NotificationLiveViewContent>(parcel.ReadParcelable<NotificationLiveViewContent>()));
266 break;
267 default:
268 ANS_LOGE("Invalid contentType");
269 return false;
270 }
271 if (!content_) {
272 ANS_LOGE("Failed to read content");
273 return false;
274 }
275
276 return true;
277 }
278
ConvertJsonToContent(NotificationContent * target,const nlohmann::json & jsonObject)279 bool NotificationContent::ConvertJsonToContent(NotificationContent *target, const nlohmann::json &jsonObject)
280 {
281 if (target == nullptr) {
282 ANS_LOGE("Invalid input parameter");
283 return false;
284 }
285
286 auto contentType = jsonObject.at("contentType");
287 if (!contentType.is_number_integer()) {
288 ANS_LOGE("ContentType is not integer");
289 return false;
290 }
291 target->contentType_ = static_cast<NotificationContent::Type>(contentType.get<int32_t>());
292
293 auto contentObj = jsonObject.at("content");
294 if (contentObj.is_null()) {
295 ANS_LOGE("Invalid json object. Cannot convert content from JSON.");
296 return false;
297 }
298
299 NotificationBasicContent *pBasicContent {nullptr};
300 switch (target->contentType_) {
301 case NotificationContent::Type::BASIC_TEXT:
302 pBasicContent = NotificationJsonConverter::ConvertFromJson<NotificationNormalContent>(contentObj);
303 break;
304 case NotificationContent::Type::CONVERSATION:
305 pBasicContent = NotificationJsonConverter::ConvertFromJson<NotificationConversationalContent>(contentObj);
306 break;
307 case NotificationContent::Type::LONG_TEXT:
308 pBasicContent = NotificationJsonConverter::ConvertFromJson<NotificationLongTextContent>(contentObj);
309 break;
310 case NotificationContent::Type::MULTILINE:
311 pBasicContent = NotificationJsonConverter::ConvertFromJson<NotificationMultiLineContent>(contentObj);
312 break;
313 case NotificationContent::Type::PICTURE:
314 pBasicContent = NotificationJsonConverter::ConvertFromJson<NotificationPictureContent>(contentObj);
315 break;
316 case NotificationContent::Type::LOCAL_LIVE_VIEW:
317 pBasicContent = NotificationJsonConverter::ConvertFromJson<NotificationLocalLiveViewContent>(contentObj);
318 break;
319 case NotificationContent::Type::LIVE_VIEW:
320 pBasicContent = NotificationJsonConverter::ConvertFromJson<NotificationLiveViewContent>(contentObj);
321 break;
322 default:
323 ANS_LOGE("Invalid contentType");
324 break;
325 }
326 if (pBasicContent == nullptr) {
327 ANS_LOGE("Parse content error!");
328 return false;
329 }
330 target->content_ = std::shared_ptr<NotificationBasicContent>(pBasicContent);
331
332 return true;
333 }
334
GetContentTypeByString(const std::string & strContentType,NotificationContent::Type & contentType)335 bool NotificationContent::GetContentTypeByString(
336 const std::string &strContentType, NotificationContent::Type &contentType)
337 {
338 if (convertStrToContentType_.size() <= 0) {
339 convertStrToContentType_[CONTENT_TYPE_NONE] = NotificationContent::Type::NONE;
340 convertStrToContentType_[CONTENT_TYPE_BASIC_TEXT] = NotificationContent::Type::BASIC_TEXT;
341 convertStrToContentType_[CONTENT_TYPE_CONVERSATION] = NotificationContent::Type::CONVERSATION;
342 convertStrToContentType_[CONTENT_TYPE_LONG_TEXT] = NotificationContent::Type::LONG_TEXT;
343 convertStrToContentType_[CONTENT_TYPE_MEDIA] = NotificationContent::Type::MEDIA;
344 convertStrToContentType_[CONTENT_TYPE_MULTILINE] = NotificationContent::Type::MULTILINE;
345 convertStrToContentType_[CONTENT_TYPE_PICTURE] = NotificationContent::Type::PICTURE;
346 convertStrToContentType_[CONTENT_TYPE_LOCAL_LIVE_VIEW] = NotificationContent::Type::LOCAL_LIVE_VIEW;
347 convertStrToContentType_[CONTENT_TYPE_LIVE_VIEW] = NotificationContent::Type::LIVE_VIEW;
348 }
349 auto iterContentType = convertStrToContentType_.find(strContentType);
350 if (iterContentType != convertStrToContentType_.end()) {
351 contentType = iterContentType->second;
352 return true;
353 }
354 ANS_LOGE("GetContentTypeByString failed as Invalid strContentType.");
355 return false;
356 }
357 } // namespace Notification
358 } // namespace OHOS
359