• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_download_ani.h"
17 
18 #include "ani_utils.h"
19 #include "dfsu_access_token_helper.h"
20 #include "dfs_error.h"
21 #include "error_handler.h"
22 #include "utils_log.h"
23 
24 namespace OHOS::FileManagement::CloudSync {
25 using namespace arkts::ani_signature;
26 
CloudDownloadUnwrap(ani_env * env,ani_object object)27 static CloudFileCore *CloudDownloadUnwrap(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 cloudsyncCore err: %{public}d", static_cast<int32_t>(ret));
33         return nullptr;
34     }
35     std::uintptr_t ptrValue = static_cast<std::uintptr_t>(nativePtr);
36     CloudFileCore *cloudDownload = reinterpret_cast<CloudFileCore *>(ptrValue);
37     return cloudDownload;
38 }
39 
CheckPermissions(const string & permission,bool isSystemApp)40 static int32_t CheckPermissions(const string &permission, bool isSystemApp)
41 {
42     if (!permission.empty() && !DfsuAccessTokenHelper::CheckCallerPermission(permission)) {
43         LOGE("permission denied");
44         return JsErrCode::E_PERMISSION;
45     }
46     if (isSystemApp && !DfsuAccessTokenHelper::IsSystemApp()) {
47         LOGE("caller hap is not system hap");
48         return JsErrCode::E_PERMISSION_SYS;
49     }
50     return E_OK;
51 }
52 
DownloadConstructor(ani_env * env,ani_object object)53 void CloudDownloadAni::DownloadConstructor(ani_env *env, ani_object object)
54 {
55     ani_namespace ns {};
56     Namespace nsSign = Builder::BuildNamespace("@ohos.file.cloudSync.cloudSync");
57     ani_status ret = env->FindNamespace(nsSign.Descriptor().c_str(), &ns);
58     if (ret != ANI_OK) {
59         LOGE("find namespace failed. ret = %{public}d", static_cast<int32_t>(ret));
60         ErrorHandler::Throw(env, ENOMEM);
61         return;
62     }
63     Type clsName = Builder::BuildClass("Download");
64     ani_class cls;
65     ret = env->Namespace_FindClass(ns, clsName.Descriptor().c_str(), &cls);
66     if (ret != ANI_OK) {
67         LOGE("find class failed. ret = %{public}d", static_cast<int32_t>(ret));
68         ErrorHandler::Throw(env, ENOMEM);
69         return;
70     }
71 
72     ani_method bindNativePtr;
73     std::string bindSign = Builder::BuildSignatureDescriptor({Builder::BuildLong()});
74     ret = env->Class_FindMethod(cls, "bindNativePtr", bindSign.c_str(), &bindNativePtr);
75     if (ret != ANI_OK) {
76         LOGE("find class ctor. ret = %{public}d", static_cast<int32_t>(ret));
77         ErrorHandler::Throw(env, ENOMEM);
78         return;
79     }
80 
81     FsResult<CloudFileCore *> data = CloudFileCore::Constructor();
82     if (!data.IsSuccess()) {
83         LOGE("cloudfile constructor failed.");
84         const auto &err = data.GetError();
85         ErrorHandler::Throw(env, err);
86         return;
87     }
88 
89     auto cloudFile = data.GetData().value();
90     ret = env->Object_CallMethod_Void(object, bindNativePtr, reinterpret_cast<ani_long>(cloudFile));
91     if (ret != ANI_OK) {
92         LOGE("bindNativePtr failed.");
93         ErrorHandler::Throw(env, ENOMEM);
94         delete cloudFile;
95     }
96 }
97 
DownloadOn(ani_env * env,ani_object object,ani_string evt,ani_object fun)98 void CloudDownloadAni::DownloadOn(ani_env *env, ani_object object, ani_string evt, ani_object fun)
99 {
100     std::string event;
101     ani_status ret = ANIUtils::AniString2String(env, evt, event);
102     if (ret != ANI_OK) {
103         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
104         return;
105     }
106     if (event != "progress") {
107         LOGE("Invalid argument for event type.");
108         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
109         return;
110     }
111 
112     int32_t res = CheckPermissions(PERM_CLOUD_SYNC, true);
113     if (res != E_OK) {
114         LOGE("On get progress failed!");
115         ErrorHandler::Throw(env, res);
116         return;
117     }
118 
119     auto cloudDownload = CloudDownloadUnwrap(env, object);
120     if (cloudDownload == nullptr) {
121         LOGE("Cannot wrap cloudDownload.");
122         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
123         return;
124     }
125 
126     std::shared_ptr<CloudDownloadCallbackImplAni> callbackImpl = cloudDownload->GetCallbackImpl(true);
127     callbackImpl->InitVm(env);
128     auto status = callbackImpl->RegisterCallback(env, fun);
129     if (status != ANI_OK) {
130         LOGE("Failed to register callback, status: %{public}d.", status);
131         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
132         return;
133     }
134 }
135 
DownloadOff0(ani_env * env,ani_object object,ani_string evt,ani_object fun)136 void CloudDownloadAni::DownloadOff0(ani_env *env, ani_object object, ani_string evt, ani_object fun)
137 {
138     std::string event;
139     ani_status ret = ANIUtils::AniString2String(env, evt, event);
140     if (ret != ANI_OK) {
141         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
142         return;
143     }
144     if (event != "progress") {
145         LOGE("Invalid argument for event type.");
146         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
147         return;
148     }
149 
150     int32_t res = CheckPermissions(PERM_CLOUD_SYNC, true);
151     if (res != E_OK) {
152         LOGE("On get progress failed!");
153         ErrorHandler::Throw(env, res);
154         return;
155     }
156 
157     auto cloudDownload = CloudDownloadUnwrap(env, object);
158     if (cloudDownload == nullptr) {
159         LOGE("Cannot wrap cloudDownload.");
160         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
161         return;
162     }
163 
164     std::shared_ptr<CloudDownloadCallbackImplAni> callbackImpl = cloudDownload->GetCallbackImpl(false);
165     if (callbackImpl == nullptr || callbackImpl->UnregisterCallback(env, fun) != ANI_OK) {
166         LOGE("Failed to unregister callback");
167         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
168         return;
169     }
170 }
171 
DownloadOff1(ani_env * env,ani_object object,ani_string evt)172 void CloudDownloadAni::DownloadOff1(ani_env *env, ani_object object, ani_string evt)
173 {
174     DownloadOff0(env, object, evt, nullptr);
175 }
176 
DownloadStart(ani_env * env,ani_object object,ani_string uri)177 void CloudDownloadAni::DownloadStart(ani_env *env, ani_object object, ani_string uri)
178 {
179     std::string uriInput;
180     ani_status ret = ANIUtils::AniString2String(env, uri, uriInput);
181     if (ret != ANI_OK) {
182         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
183         return;
184     }
185 
186     auto cloudDownload = CloudDownloadUnwrap(env, object);
187     if (cloudDownload == nullptr) {
188         LOGE("Cannot wrap cloudDownload.");
189         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
190         return;
191     }
192     std::shared_ptr<CloudDownloadCallbackImplAni> callbackImpl = cloudDownload->GetCallbackImpl(true);
193     callbackImpl->InitVm(env);
194     auto data = cloudDownload->DoStart(uriInput);
195     if (!data.IsSuccess()) {
196         const auto &err = data.GetError();
197         LOGE("cloud download do start failed, ret = %{public}d", err.GetErrNo());
198         ErrorHandler::Throw(env, err);
199     }
200 }
201 
DownloadStop(ani_env * env,ani_object object,ani_string uri)202 void CloudDownloadAni::DownloadStop(ani_env *env, ani_object object, ani_string uri)
203 {
204     std::string uriInput;
205     ani_status ret = ANIUtils::AniString2String(env, uri, uriInput);
206     if (ret != ANI_OK) {
207         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
208         return;
209     }
210 
211     auto cloudDownload = CloudDownloadUnwrap(env, object);
212     if (cloudDownload == nullptr) {
213         LOGE("Cannot wrap cloudDownload.");
214         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
215         return;
216     }
217     std::shared_ptr<CloudDownloadCallbackImplAni> callbackImpl = cloudDownload->GetCallbackImpl(false);
218     if (callbackImpl == nullptr) {
219         LOGE("Cannot get callbackImpl before stop.");
220         ErrorHandler::Throw(env, JsErrCode::E_IPCSS);
221         return;
222     }
223 
224     auto data = cloudDownload->DoStop(uriInput);
225     if (!data.IsSuccess()) {
226         const auto &err = data.GetError();
227         LOGE("cloud download do stop failed, ret = %{public}d", err.GetErrNo());
228         ErrorHandler::Throw(env, err);
229     }
230 }
231 } // namespace OHOS::FileManagement::CloudSync