1 /*
2 * Copyright (c) 2021-2022 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 "form_provider_data.h"
17
18 #include <cinttypes>
19 #include <fstream>
20 #include <iostream>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "hilog_wrapper.h"
25 #include "message_parcel.h"
26 #include "string_ex.h"
27
28 namespace OHOS {
29 namespace AppExecFwk {
30 const std::string JSON_EMPTY_STRING = "{}";
31 const std::string JSON_IMAGES_STRING = "formImages";
32
33 /**
34 * @brief Constructor.
35 */
FormProviderData()36 FormProviderData::FormProviderData()
37 {
38 jsonFormProviderData_.clear();
39 }
40
41 /**
42 * @brief A constructor used to create a {@code FormProviderData} instance with data of
43 * the {@code nlohmann::json} type specified.
44 * @param jsonData Indicates the data to be carried in the new {@code FormProviderData} instance,
45 * in {@code nlohmann::json} format.
46 */
FormProviderData(nlohmann::json & jsonData)47 FormProviderData::FormProviderData(nlohmann::json &jsonData)
48 {
49 jsonFormProviderData_ = jsonData;
50 ParseImagesData();
51 }
52
53 /**
54 * @brief A constructor used to create a {@code FormProviderData} instance with data of the {@code String} type
55 * specified.
56 * @param jsonDataString Indicates the data to be carried in the new {@code FormProviderData} instance,
57 * in JSON string format.
58 */
FormProviderData(std::string jsonDataString)59 FormProviderData::FormProviderData(std::string jsonDataString)
60 {
61 if (jsonDataString.empty()) {
62 jsonDataString = JSON_EMPTY_STRING;
63 }
64 nlohmann::json jsonObject = nlohmann::json::parse(jsonDataString, nullptr, false);
65 if (jsonObject.is_discarded()) {
66 HILOG_ERROR("failed to parse jsonDataString: %{public}s.", jsonDataString.c_str());
67 return;
68 }
69 jsonFormProviderData_ = jsonObject;
70 ParseImagesData();
71 }
72
73 /**
74 * @brief Updates form data in this {@code FormProviderData} object.
75 * @param jsonData Indicates the new data to use, in {@code ZSONObject} format.
76 */
UpdateData(nlohmann::json & jsonData)77 void FormProviderData::UpdateData(nlohmann::json &jsonData)
78 {
79 jsonFormProviderData_ = jsonData;
80 }
81 /**
82 * @brief Obtains the form data stored in this {@code FormProviderData} object.
83 * @return Returns json data
84 */
GetData() const85 nlohmann::json FormProviderData::GetData() const
86 {
87 return jsonFormProviderData_;
88 }
89 /**
90 * @brief Obtains the form data stored in this {@code FormProviderData} object.
91 * @return Returns json string format
92 */
GetDataString() const93 std::string FormProviderData::GetDataString() const
94 {
95 HILOG_INFO("%{public}s called", __func__);
96 std::string dataStr = jsonFormProviderData_.empty() ? "" : jsonFormProviderData_.dump();
97 HILOG_INFO("%{public}s, data: %{public}s", __func__, dataStr.c_str());
98 return dataStr;
99 }
100
101 /**
102 * @brief Adds an image to this {@code FormProviderData} instance.
103 * @param picName Indicates the name of the image to add.
104 * @param data Indicates the binary data of the image content.
105 */
AddImageData(std::string picName,char * data,int32_t size)106 void FormProviderData::AddImageData(std::string picName, char *data, int32_t size)
107 {
108 if ((picName.length() == 0) || (sizeof(data) == 0)) {
109 HILOG_ERROR("input param is NULL!");
110 return;
111 }
112
113 auto iterator = rawImageBytesMap_.find(picName);
114 if (iterator != rawImageBytesMap_.end()) {
115 delete[] iterator->second.first;
116 }
117 rawImageBytesMap_[picName] = std::make_pair(data, size);
118
119 imageDataState_ = IMAGE_DATA_STATE_ADDED;
120 }
121
122 /**
123 * @brief Adds an image to this {@code FormProviderData} instance.
124 * @param picName Indicates the name of the image to add.
125 * @param data Indicates the binary data of the image content.
126 */
AddImageData(std::string picName,int fd)127 void FormProviderData::AddImageData(std::string picName, int fd)
128 {
129 HILOG_INFO("%{public}s called. fd is %{public}d", __func__, fd);
130 if (fd < 0) {
131 HILOG_ERROR("fd is invalid.");
132 return;
133 }
134
135 int32_t size = lseek(fd, 0L, SEEK_END);
136 if (size <= 0) {
137 HILOG_ERROR("Get file size failed, errno is %{public}d", errno);
138 return;
139 }
140 HILOG_INFO("File size is %{public}d", size);
141 if (lseek(fd, 0L, SEEK_SET) == -1) {
142 return;
143 }
144 char *data = new char[size];
145 if (data == nullptr) {
146 HILOG_ERROR("New data failed, size is %{public}d", size);
147 return;
148 }
149 if (read(fd, data, size) < 0) {
150 delete[] data;
151 HILOG_ERROR("Read failed, errno is %{public}d", errno);
152 return;
153 }
154 AddImageData(picName, data, size);
155 HILOG_INFO("%{public}s called end.", __func__);
156 }
157
ParseImagesData()158 void FormProviderData::ParseImagesData()
159 {
160 if (jsonFormProviderData_ == nullptr) {
161 HILOG_ERROR("Form provider json data is nullptr.");
162 return;
163 }
164 if (!jsonFormProviderData_.contains(JSON_IMAGES_STRING)) {
165 return;
166 }
167 nlohmann::json jsonImages = jsonFormProviderData_.at(JSON_IMAGES_STRING);
168 for (auto iter = jsonImages.begin(); iter != jsonImages.end(); iter++) {
169 if (iter->is_number_integer()) {
170 AddImageData(iter.key(), iter.value());
171 } else {
172 HILOG_ERROR("fd is not number integer.");
173 }
174 }
175 }
176
177 /**
178 * @brief Removes data of an image with the specified {@code picName} from this {@code FormProviderData} instance.
179 * @param picName Indicates the name of the image to remove.
180 */
RemoveImageData(std::string picName)181 void FormProviderData::RemoveImageData(std::string picName)
182 {
183 rawImageBytesMap_.erase(picName);
184 }
185
186 /**
187 * @brief Set the form data stored from string string.
188 * @param Returns string string.
189 */
SetDataString(std::string & jsonDataString)190 void FormProviderData::SetDataString(std::string &jsonDataString)
191 {
192 HILOG_INFO("%{public}s called", __func__);
193 if (jsonDataString.empty()) {
194 jsonDataString = JSON_EMPTY_STRING;
195 }
196 nlohmann::json jsonObject = nlohmann::json::parse(jsonDataString, nullptr, false);
197 if (jsonObject.is_discarded()) {
198 HILOG_ERROR("failed to parse jsonDataString: %{public}s.", jsonDataString.c_str());
199 return;
200 }
201 jsonFormProviderData_ = jsonObject;
202 }
203 /**
204 * @brief Merge new data to FormProviderData.
205 * @param addJsonData data to merge to FormProviderData
206 */
MergeData(nlohmann::json & addJsonData)207 void FormProviderData::MergeData(nlohmann::json &addJsonData)
208 {
209 HILOG_INFO("%{public}s called", __func__);
210 if (addJsonData.empty()) {
211 return;
212 }
213
214 if (jsonFormProviderData_.empty()) {
215 jsonFormProviderData_ = addJsonData;
216 return;
217 }
218
219 for (auto && [key, value] : addJsonData.items()) {
220 jsonFormProviderData_[key] = value;
221 }
222 }
223
224 /**
225 * @brief Obtains the imageDataMap stored in this {@code FormProviderData} object.
226 * @return Returns the map that contains shared image data.
227 */
GetImageDataMap() const228 std::map<std::string, std::pair<sptr<FormAshmem>, int32_t>> FormProviderData::GetImageDataMap() const
229 {
230 return imageDataMap_;
231 }
232
233 /**
234 * @brief Obtains the add/remove state stored in this {@code FormProviderData} object.
235 * @return Returns the add/remove state of shared image data.
236 */
GetImageDataState() const237 int32_t FormProviderData::GetImageDataState() const
238 {
239 return imageDataState_;
240 }
241
242 /**
243 * @brief Updates imageDataState in this {@code FormProviderData} object.
244 * @param imageDataState Indicates the imageDataState to update.
245 */
SetImageDataState(int32_t imageDataState)246 void FormProviderData::SetImageDataState(int32_t imageDataState)
247 {
248 imageDataState_ = imageDataState;
249 }
250
251 /**
252 * @brief Updates imageDataMap in this {@code FormProviderData} object.
253 * @param imageDataMap Indicates the imageDataMap to update.
254 */
SetImageDataMap(std::map<std::string,std::pair<sptr<FormAshmem>,int32_t>> imageDataMap)255 void FormProviderData::SetImageDataMap(std::map<std::string, std::pair<sptr<FormAshmem>, int32_t>> imageDataMap)
256 {
257 imageDataMap_ = imageDataMap;
258 if (!imageDataMap.empty()) {
259 imageDataState_ = IMAGE_DATA_STATE_ADDED;
260 } else {
261 imageDataState_ = IMAGE_DATA_STATE_NO_OPERATION;
262 }
263 }
264
265 /**
266 * Read this {@code FormProviderData} object from a Parcel.
267 * @param parcel the parcel
268 * eturn Returns {@code true} if the marshalling is successful; returns {@code false} otherwise.
269 */
ReadFromParcel(Parcel & parcel)270 bool FormProviderData::ReadFromParcel(Parcel &parcel)
271 {
272 auto jsonDataString = Str16ToStr8(parcel.ReadString16());
273 nlohmann::json jsonObject = nlohmann::json::parse(jsonDataString, nullptr, false);
274 if (jsonObject.is_discarded()) {
275 HILOG_ERROR("failed to parse jsonDataString: %{public}s.", jsonDataString.c_str());
276 return false;
277 }
278 jsonFormProviderData_ = jsonObject;
279
280 imageDataState_ = parcel.ReadInt32();
281 HILOG_INFO("%{public}s imageDateState is %{public}d", __func__, imageDataState_);
282 switch (imageDataState_) {
283 case IMAGE_DATA_STATE_ADDED: {
284 int32_t imageDataNum = parcel.ReadInt32();
285 for (int32_t i = 0; i < imageDataNum; i++) {
286 sptr<FormAshmem> formAshmem = parcel.ReadParcelable<FormAshmem>();
287 if (formAshmem == nullptr) {
288 HILOG_ERROR("%{public}s failed, ashmem is nullptr", __func__);
289 return false;
290 }
291 int32_t len = parcel.ReadInt32();
292 std::pair<sptr<FormAshmem>, int32_t> imageDataRecord = std::make_pair(formAshmem, len);
293 auto picName = Str16ToStr8(parcel.ReadString16());
294 imageDataMap_[picName] = imageDataRecord;
295 }
296 break;
297 }
298 case IMAGE_DATA_STATE_NO_OPERATION:
299 case IMAGE_DATA_STATE_REMOVED:
300 break;
301 default:
302 HILOG_WARN("%{public}s failed, unexpected imageDataState_ %{public}d", __func__, imageDataState_);
303 break;
304 }
305 return true;
306 }
307
308 /**
309 * @brief Marshals this {@code FormProviderData} object into a {@link ohos.utils.Parcel} object.
310 * @param parcel Indicates the {@code Parcel} object for marshalling.
311 * @return Returns {@code true} if the marshalling is successful; returns {@code false} otherwise.
312 */
Marshalling(Parcel & parcel) const313 bool FormProviderData::Marshalling(Parcel &parcel) const
314 {
315 HILOG_INFO("%{public}s called, jsonFormProviderData_: %{public}s", __func__, jsonFormProviderData_.dump().c_str());
316 if (!parcel.WriteString16(Str8ToStr16(jsonFormProviderData_.empty() ? JSON_EMPTY_STRING : jsonFormProviderData_.dump()))) {
317 return false;
318 }
319
320 parcel.WriteInt32(imageDataState_);
321 HILOG_INFO("%{public}s imageDateState is %{public}d", __func__, imageDataState_);
322 switch (imageDataState_) {
323 case IMAGE_DATA_STATE_ADDED: {
324 parcel.WriteInt32(rawImageBytesMap_.size()); // firstly write the number of shared image to add
325 for (auto &entry : rawImageBytesMap_) {
326 if (!WriteImageDataToParcel(parcel, entry.first, entry.second.first, entry.second.second)) {
327 HILOG_ERROR("%{public}s failed, the picture name is %{public}s", __func__, entry.first.c_str());
328 return false;
329 }
330 parcel.WriteInt32(sizeof(entry.second));
331 parcel.WriteString16(Str8ToStr16(entry.first));
332 }
333 break;
334 }
335 case IMAGE_DATA_STATE_NO_OPERATION:
336 case IMAGE_DATA_STATE_REMOVED:
337 break;
338 default:
339 HILOG_WARN("%{public}s failed, unexpected imageDataState_ %{public}d", __func__, imageDataState_);
340 break;
341 }
342 return true;
343 }
344
345 /**
346 * @brief Unmarshals this {@code FormProviderData} object from a {@link ohos.utils.Parcel} object.
347 * @param parcel Indicates the {@code Parcel} object for unmarshalling.
348 * @return FormProviderData.
349 */
Unmarshalling(Parcel & parcel)350 FormProviderData* FormProviderData::Unmarshalling(Parcel &parcel)
351 {
352 std::unique_ptr<FormProviderData> formProviderData = std::make_unique<FormProviderData>();
353 if (formProviderData && !formProviderData->ReadFromParcel(parcel)) {
354 formProviderData = nullptr;
355 }
356 return formProviderData.release();
357 }
358
359 /**
360 * @brief Clear imageDataMap, rawImageBytesMap_, imageDataState_ and jsonFormProviderData_.
361 */
ClearData()362 void FormProviderData::ClearData()
363 {
364 jsonFormProviderData_.clear();
365 }
366
WriteImageDataToParcel(Parcel & parcel,std::string picName,char * data,int32_t size) const367 bool FormProviderData::WriteImageDataToParcel(Parcel &parcel, std::string picName, char *data, int32_t size) const
368 {
369 FormAshmem formAshmem;
370 if (!formAshmem.WriteToAshmem(picName, data, size)) {
371 return false;
372 }
373 // write formAshmem
374 if (!parcel.WriteParcelable(&formAshmem)) {
375 HILOG_ERROR("write FormAshmem fail, the picture name is %{public}s", picName.c_str());
376 return false;
377 }
378 return true;
379 }
380 } // namespace AppExecFwk
381 } // namespace OHOS
382