1 /*
2 * Copyright (c) 2025 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 "cloud_file_cache_ani.h"
17
18 #include "ani_utils.h"
19 #include "dfs_error.h"
20 #include "error_handler.h"
21 #include "utils_log.h"
22
23 namespace OHOS::FileManagement::CloudSync {
24
25 using namespace arkts::ani_signature;
26
CloudFileCacheUnwrap(ani_env * env,ani_object object)27 static CloudFileCacheCore *CloudFileCacheUnwrap(ani_env *env, ani_object object)
28 {
29 ani_long nativePtr;
30 auto ret = env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr);
31 if (ret != ANI_OK) {
32 LOGE("Unwrap cloudFileCacheCore err: %{public}d", static_cast<int32_t>(ret));
33 return nullptr;
34 }
35 std::uintptr_t ptrValue = static_cast<std::uintptr_t>(nativePtr);
36 CloudFileCacheCore *cloudFileCache = reinterpret_cast<CloudFileCacheCore *>(ptrValue);
37 return cloudFileCache;
38 }
39
CloudFileCacheConstructor(ani_env * env,ani_object object)40 void CloudFileCacheAni::CloudFileCacheConstructor(ani_env *env, ani_object object)
41 {
42 ani_namespace ns {};
43 Namespace nsSign = Builder::BuildNamespace("@ohos.file.cloudSync.cloudSync");
44 ani_status ret = env->FindNamespace(nsSign.Descriptor().c_str(), &ns);
45 if (ret != ANI_OK) {
46 LOGE("find namespace failed. ret = %{public}d", static_cast<int32_t>(ret));
47 ErrorHandler::Throw(env, ENOMEM);
48 return;
49 }
50 Type clsName = Builder::BuildClass("CloudFileCache");
51 ani_class cls;
52 ret = env->Namespace_FindClass(ns, clsName.Descriptor().c_str(), &cls);
53 if (ret != ANI_OK) {
54 LOGE("find class failed. ret = %{public}d", static_cast<int32_t>(ret));
55 ErrorHandler::Throw(env, ENOMEM);
56 return;
57 }
58
59 ani_method bindNativePtr;
60 std::string bindSign = Builder::BuildSignatureDescriptor({Builder::BuildLong()});
61 ret = env->Class_FindMethod(cls, "bindNativePtr", bindSign.c_str(), &bindNativePtr);
62 if (ret != ANI_OK) {
63 LOGE("find class ctor. ret = %{public}d", static_cast<int32_t>(ret));
64 ErrorHandler::Throw(env, ENOMEM);
65 return;
66 }
67
68 FsResult<CloudFileCacheCore *> data = CloudFileCacheCore::Constructor();
69 if (!data.IsSuccess()) {
70 LOGE("cloudFileCache constructor failed.");
71 const auto &err = data.GetError();
72 ErrorHandler::Throw(env, err);
73 return;
74 }
75
76 const CloudFileCacheCore *cloudFileCache = data.GetData().value();
77 ret = env->Object_CallMethod_Void(object, bindNativePtr, reinterpret_cast<ani_long>(cloudFileCache));
78 if (ret != ANI_OK) {
79 LOGE("bindNativePtr failed.");
80 delete cloudFileCache;
81 ErrorHandler::Throw(env, ENOMEM);
82 }
83 }
84
CloudFileCacheOn(ani_env * env,ani_object object,ani_string evt,ani_object fun)85 void CloudFileCacheAni::CloudFileCacheOn(ani_env *env, ani_object object, ani_string evt, ani_object fun)
86 {
87 std::string event;
88 ani_status ret = ANIUtils::AniString2String(env, evt, event);
89 if (ret != ANI_OK) {
90 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
91 return;
92 }
93
94 if (event == "multiProgress") {
95 event = MULTI_PROGRESS;
96 }
97 if (event != PROGRESS && event != MULTI_PROGRESS) {
98 LOGE("Invalid argument for event type.");
99 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
100 return;
101 }
102
103 auto cloudFileCache = CloudFileCacheUnwrap(env, object);
104 if (cloudFileCache == nullptr) {
105 LOGE("Cannot wrap cloudFileCache.");
106 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
107 return;
108 }
109
110 std::shared_ptr<CloudFileCacheCallbackImplAni> callbackImpl = cloudFileCache->GetCallbackImpl(event, true);
111 callbackImpl->InitVm(env);
112 auto status = callbackImpl->RegisterCallback(env, fun);
113 if (status != ANI_OK) {
114 LOGE("Failed to register callback, status: %{public}d.", status);
115 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
116 return;
117 }
118 }
119
CloudFileCacheOff0(ani_env * env,ani_object object,ani_string evt,ani_object fun)120 void CloudFileCacheAni::CloudFileCacheOff0(ani_env *env, ani_object object, ani_string evt, ani_object fun)
121 {
122 std::string event;
123 ani_status ret = ANIUtils::AniString2String(env, evt, event);
124 if (ret != ANI_OK) {
125 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
126 return;
127 }
128
129 if (event == "multiProgress") {
130 event = MULTI_PROGRESS;
131 }
132 if (event != PROGRESS && event != MULTI_PROGRESS) {
133 LOGE("Invalid argument for event type.");
134 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
135 return;
136 }
137
138 auto cloudFileCache = CloudFileCacheUnwrap(env, object);
139 if (cloudFileCache == nullptr) {
140 LOGE("Cannot wrap cloudFileCache.");
141 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
142 return;
143 }
144
145 std::shared_ptr<CloudFileCacheCallbackImplAni> callbackImpl = cloudFileCache->GetCallbackImpl(event, false);
146 if (callbackImpl == nullptr || callbackImpl->UnregisterCallback(env, fun) != ANI_OK) {
147 LOGE("Failed to unregister callback.");
148 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
149 return;
150 }
151 }
152
CloudFileCacheOff1(ani_env * env,ani_object object,ani_string evt)153 void CloudFileCacheAni::CloudFileCacheOff1(ani_env *env, ani_object object, ani_string evt)
154 {
155 CloudFileCacheOff0(env, object, evt, nullptr);
156 }
157
CloudFileCacheStart(ani_env * env,ani_object object,ani_string uri)158 void CloudFileCacheAni::CloudFileCacheStart(ani_env *env, ani_object object, ani_string uri)
159 {
160 std::string uriInput;
161 ani_status ret = ANIUtils::AniString2String(env, uri, uriInput);
162 if (ret != ANI_OK) {
163 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
164 return;
165 }
166
167 auto cloudFileCache = CloudFileCacheUnwrap(env, object);
168 if (cloudFileCache == nullptr) {
169 LOGE("Cannot wrap cloudFileCache.");
170 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
171 return;
172 }
173 auto data = cloudFileCache->DoStart(uriInput);
174 if (!data.IsSuccess()) {
175 const auto &err = data.GetError();
176 LOGE("cloudFileCache do start failed, ret = %{public}d", err.GetErrNo());
177 ErrorHandler::Throw(env, err);
178 }
179 }
180
CloudFileCacheStartBatch(ani_env * env,ani_object object,ani_array_ref uriList,ani_enum_item fileType)181 ani_double CloudFileCacheAni::CloudFileCacheStartBatch(ani_env *env,
182 ani_object object,
183 ani_array_ref uriList,
184 ani_enum_item fileType)
185 {
186 ani_double errResult = 0;
187 auto [ret, urisInput] = ANIUtils::AniToStringArray(env, uriList);
188 if (!ret) {
189 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
190 return errResult;
191 }
192
193 int32_t fieldKey = static_cast<int32_t>(FieldKey::FIELDKEY_CONTENT);
194 tie(ret, fieldKey) = ANIUtils::EnumToInt32(env, fileType);
195 if (!ret) {
196 LOGE("cloudFileCache get fileType failed");
197 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
198 return errResult;
199 }
200
201 auto cloudFileCache = CloudFileCacheUnwrap(env, object);
202 if (cloudFileCache == nullptr) {
203 LOGE("Cannot wrap cloudFileCache.");
204 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
205 return errResult;
206 }
207 auto data = cloudFileCache->DoStart(urisInput, fieldKey);
208 if (!data.IsSuccess()) {
209 const auto &err = data.GetError();
210 LOGE("cloudFileCache do start failed, ret = %{public}d", err.GetErrNo());
211 ErrorHandler::Throw(env, err);
212 return errResult;
213 }
214
215 return static_cast<ani_double>(data.GetData().value());
216 }
217
CloudFileCacheStop(ani_env * env,ani_object object,ani_string uri,ani_boolean needClean)218 void CloudFileCacheAni::CloudFileCacheStop(ani_env *env, ani_object object, ani_string uri, ani_boolean needClean)
219 {
220 std::string uriInput;
221 ani_status ret = ANIUtils::AniString2String(env, uri, uriInput);
222 if (ret != ANI_OK) {
223 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
224 return;
225 }
226
227 auto cloudFileCache = CloudFileCacheUnwrap(env, object);
228 if (cloudFileCache == nullptr) {
229 LOGE("Cannot wrap cloudFileCache.");
230 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
231 return;
232 }
233
234 bool needCleanInput = needClean;
235
236 auto data = cloudFileCache->DoStop(uriInput, needCleanInput);
237 if (!data.IsSuccess()) {
238 const auto &err = data.GetError();
239 LOGE("cloudFileCache do stop failed, ret = %{public}d", err.GetErrNo());
240 ErrorHandler::Throw(env, err);
241 }
242 }
243
CloudFileCacheStopBatch(ani_env * env,ani_object object,ani_double taskId,ani_boolean needClean)244 void CloudFileCacheAni::CloudFileCacheStopBatch(ani_env *env,
245 ani_object object,
246 ani_double taskId,
247 ani_boolean needClean)
248 {
249 auto cloudFileCache = CloudFileCacheUnwrap(env, object);
250 if (cloudFileCache == nullptr) {
251 LOGE("Cannot wrap cloudFileCache.");
252 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
253 return;
254 }
255
256 bool needCleanInput = needClean;
257
258 auto data = cloudFileCache->DoStop(static_cast<int64_t>(taskId), needCleanInput);
259 if (!data.IsSuccess()) {
260 const auto &err = data.GetError();
261 LOGE("cloudFileCache do stop failed, ret = %{public}d", err.GetErrNo());
262 ErrorHandler::Throw(env, err);
263 }
264 }
265
CloudFileCacheCleanCache(ani_env * env,ani_object object,ani_string uri)266 void CloudFileCacheAni::CloudFileCacheCleanCache(ani_env *env, ani_object object, ani_string uri)
267 {
268 std::string uriInput;
269 ani_status ret = ANIUtils::AniString2String(env, uri, uriInput);
270 if (ret != ANI_OK) {
271 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
272 return;
273 }
274
275 auto cloudFileCache = CloudFileCacheUnwrap(env, object);
276 if (cloudFileCache == nullptr) {
277 LOGE("Cannot wrap cloudFileCache.");
278 ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
279 return;
280 }
281 auto data = cloudFileCache->CleanCache(uriInput);
282 if (!data.IsSuccess()) {
283 const auto &err = data.GetError();
284 LOGE("cloudFileCache do cleanCache failed, ret = %{public}d", err.GetErrNo());
285 ErrorHandler::Throw(env, err);
286 }
287 }
288 } // namespace OHOS::FileManagement::CloudSync