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