• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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