1 /*
2 * Copyright (C) 2024 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 "ringtone_restore_napi.h"
17
18 #include "application_context.h"
19 #include "js_native_api.h"
20 #include "ringtone_db_const.h"
21 #include "ringtone_errno.h"
22 #include "ringtone_log.h"
23 #include "ringtone_restore_factory.h"
24 #include "ringtone_restore_type.h"
25
26 #define MLOG_TAG "Common"
27
28 namespace OHOS {
29 namespace Media {
30 using namespace std;
31
32 using RestoreBlock = struct {
33 napi_env env;
34 int32_t sceneCode;
35 std::string baseBackupPath;
36 int32_t resultSet;
37 napi_deferred nativeDeferred;
38 };
39
Init(napi_env env,napi_value exports)40 napi_value RingtoneRestoreNapi::Init(napi_env env, napi_value exports)
41 {
42 RINGTONE_INFO_LOG("Init");
43 napi_property_descriptor ringtone_restore_properties[] = {
44 DECLARE_NAPI_FUNCTION("startRestore", JSStartRestore)
45 };
46
47 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(ringtone_restore_properties) /
48 sizeof(ringtone_restore_properties[0]), ringtone_restore_properties));
49 return exports;
50 }
51
GetIntFromParams(napi_env env,const napi_value args[],size_t index)52 static int32_t GetIntFromParams(napi_env env, const napi_value args[], size_t index)
53 {
54 int32_t result = -1;
55 napi_valuetype valueType = napi_undefined;
56 if (napi_typeof(env, args[index], &valueType) != napi_ok || valueType != napi_number) {
57 // NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
58 RINGTONE_ERR_LOG("GetIntFromParams invalid parameter");
59 return result;
60 }
61 napi_get_value_int32(env, args[index], &result);
62 return result;
63 }
64
GetStringFromParams(napi_env env,const napi_value args[],size_t index)65 static std::string GetStringFromParams(napi_env env, const napi_value args[], size_t index)
66 {
67 napi_valuetype valueType = napi_undefined;
68 if (napi_typeof(env, args[index], &valueType) != napi_ok || valueType != napi_string) {
69 // NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
70 return "";
71 }
72
73 size_t resultLength;
74 napi_get_value_string_utf8(env, args[index], nullptr, 0, &resultLength);
75 std::string result(resultLength, '\0');
76 napi_get_value_string_utf8(env, args[index], &result[0], resultLength + 1, &resultLength);
77 return result;
78 }
79
CheckPermission(void)80 static int32_t CheckPermission(void)
81 {
82 auto context = AbilityRuntime::Context::GetApplicationContext();
83 if (context == nullptr) {
84 RINGTONE_ERR_LOG("CheckPermission context nullptr");
85 return E_FAIL;
86 }
87 std::string bundleName = context->GetBundleName();
88 if (bundleName.compare(RINGTONE_BUNDLE_NAME) != 0) {
89 RINGTONE_ERR_LOG("bundle name is invalid: %{public}s", bundleName.c_str());
90 return E_FAIL;
91 }
92 RINGTONE_INFO_LOG("CheckPermission success");
93 return E_OK;
94 }
95
RingtoneRestore(std::unique_ptr<RestoreInterface> & restore,string backupPath)96 static int32_t RingtoneRestore(std::unique_ptr<RestoreInterface> &restore, string backupPath)
97 {
98 int32_t ret = E_OK;
99 if ((restore != nullptr) && (restore->Init(backupPath)) == Media::E_OK) {
100 RINGTONE_INFO_LOG("start restore....");
101 ret = restore->StartRestore();
102 RINGTONE_INFO_LOG("restore finished");
103 } else {
104 RINGTONE_ERR_LOG("ringtone-restore failed on init");
105 ret = E_HAS_DB_ERROR;
106 }
107
108 return ret;
109 }
110
UvQueueWork(uv_loop_s * loop,uv_work_t * work)111 void RingtoneRestoreNapi::UvQueueWork(uv_loop_s *loop, uv_work_t *work)
112 {
113 if (loop == nullptr) {
114 RINGTONE_ERR_LOG("Failed to uv_loop");
115 return;
116 }
117 if (work == nullptr || work->data == nullptr) {
118 RINGTONE_ERR_LOG("Failed to uv_work");
119 return;
120 }
121 uv_queue_work(loop, work, [](uv_work_t *work) {
122 RestoreBlock *block = reinterpret_cast<RestoreBlock *> (work->data);
123 if (block == nullptr) {
124 RINGTONE_ERR_LOG("Failed to new block");
125 return;
126 }
127 auto restore = RingtoneRestoreFactory::CreateObj(RestoreSceneType(block->sceneCode));
128 if (restore == nullptr) {
129 RINGTONE_ERR_LOG("Failed to new restore");
130 block->resultSet = E_FAIL;
131 return;
132 }
133 block->resultSet = RingtoneRestore(restore, block->baseBackupPath);
134 }, [](uv_work_t *work, int _status) {
135 RestoreBlock *block = reinterpret_cast<RestoreBlock *> (work->data);
136 if (block == nullptr) {
137 RINGTONE_ERR_LOG("Failed to new block");
138 delete work;
139 return;
140 }
141 napi_handle_scope scope = nullptr;
142 napi_open_handle_scope(block->env, &scope);
143 if (scope == nullptr) {
144 RINGTONE_ERR_LOG("Failed to new scope");
145 delete block;
146 delete work;
147 return;
148 }
149 napi_value restoreExResult = nullptr;
150 RINGTONE_INFO_LOG("resultSet, %{public}d", block->resultSet);
151 napi_create_int32(block->env, block->resultSet, &restoreExResult);
152 napi_resolve_deferred(block->env, block->nativeDeferred, restoreExResult);
153 napi_close_handle_scope(block->env, scope);
154 delete block;
155 delete work;
156 });
157 }
158
JSStartRestore(napi_env env,napi_callback_info info)159 napi_value RingtoneRestoreNapi::JSStartRestore(napi_env env, napi_callback_info info)
160 {
161 napi_value result = nullptr;
162 RINGTONE_INFO_LOG("JSStartRestore start");
163 napi_get_undefined(env, &result);
164 if (CheckPermission() != E_OK) {
165 RINGTONE_ERR_LOG("check permission failed");
166 return result;
167 }
168
169 size_t argc = 2;
170 napi_value argv[2] = {0};
171 napi_value thisVar = nullptr;
172
173 void *data;
174 const int32_t param = 2;
175 napi_get_cb_info(env, info, &(argc), argv, &(thisVar), &(data));
176 if (argc != param) {
177 RINGTONE_ERR_LOG("require 2 parameters");
178 return result;
179 }
180 napi_get_undefined(env, &result);
181 int32_t sceneCode = GetIntFromParams(env, argv, 0);
182 std::string baseBackupPath = GetStringFromParams(env, argv, 1);
183 RINGTONE_INFO_LOG("sceneCode: %{public}d, backupPath: %{private}s", sceneCode, baseBackupPath.c_str());
184
185 uv_loop_s *loop = nullptr;
186 napi_get_uv_event_loop(env, &loop);
187 if (loop == nullptr) {
188 RINGTONE_ERR_LOG("Failed to new uv_loop");
189 return result;
190 }
191 uv_work_t *work = new (std::nothrow) uv_work_t;
192 if (work == nullptr) {
193 RINGTONE_ERR_LOG("Failed to new uv_work");
194 return result;
195 }
196 int32_t resultSet = E_OK;
197 napi_deferred nativeDeferred = nullptr;
198 napi_create_promise(env, &nativeDeferred, &result);
199 RestoreBlock *block = new (std::nothrow) RestoreBlock {
200 env, sceneCode, baseBackupPath, resultSet, nativeDeferred };
201 if (block == nullptr) {
202 RINGTONE_ERR_LOG("Failed to new block");
203 delete work;
204 return result;
205 }
206 work->data = reinterpret_cast<void *>(block);
207 UvQueueWork(loop, work);
208 RINGTONE_INFO_LOG("JSStartRestore end");
209 return result;
210 }
211 } // namespace Media
212 } // namespace OHOS