1 /*
2 * Copyright (c) 2023-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 "js_context_utils.h"
17
18 #include <iostream>
19 #include "hilog_tag_wrapper.h"
20 #include "js_application_context_utils.h"
21 #include "js_data_converter.h"
22 #include "js_runtime_utils.h"
23
24 namespace OHOS {
25 namespace AbilityRuntime {
26 namespace {
27 constexpr char BASE_CONTEXT_NAME[] = "__base_context_ptr__";
28
29 class JsBaseContext {
30 public:
JsBaseContext(std::weak_ptr<Context> && context)31 explicit JsBaseContext(std::weak_ptr<Context> &&context) : context_(std::move(context)) {}
32 virtual ~JsBaseContext() = default;
33
34 static void Finalizer(napi_env env, void *data, void *hint);
35 static napi_value CreateBundleContext(napi_env env, napi_callback_info info);
36 static napi_value GetApplicationContext(napi_env env, napi_callback_info info);
37 static napi_value SwitchArea(napi_env env, napi_callback_info info);
38 static napi_value GetArea(napi_env env, napi_callback_info info);
39 static napi_value CreateModuleContext(napi_env env, napi_callback_info info);
40 static napi_value CreateModuleResourceManager(napi_env env, napi_callback_info info);
41
42 static napi_value GetCacheDir(napi_env env, napi_callback_info info);
43 static napi_value GetTempDir(napi_env env, napi_callback_info info);
44 static napi_value GetResourceDir(napi_env env, napi_callback_info info);
45 static napi_value GetFilesDir(napi_env env, napi_callback_info info);
46 static napi_value GetDistributedFilesDir(napi_env env, napi_callback_info info);
47 static napi_value GetDatabaseDir(napi_env env, napi_callback_info info);
48 static napi_value GetPreferencesDir(napi_env env, napi_callback_info info);
49 static napi_value GetBundleCodeDir(napi_env env, napi_callback_info info);
50 static napi_value GetCloudFileDir(napi_env env, napi_callback_info info);
51
52 napi_value OnGetCacheDir(napi_env env, NapiCallbackInfo &info);
53 napi_value OnGetTempDir(napi_env env, NapiCallbackInfo &info);
54 napi_value OnGetResourceDir(napi_env env, NapiCallbackInfo &info);
55 napi_value OnGetFilesDir(napi_env env, NapiCallbackInfo &info);
56 napi_value OnGetDistributedFilesDir(napi_env env, NapiCallbackInfo &info);
57 napi_value OnGetDatabaseDir(napi_env env, NapiCallbackInfo &info);
58 napi_value OnGetPreferencesDir(napi_env env, NapiCallbackInfo &info);
59 napi_value OnGetBundleCodeDir(napi_env env, NapiCallbackInfo &info);
60 napi_value OnGetCloudFileDir(napi_env env, NapiCallbackInfo &info);
61 napi_value OnSwitchArea(napi_env env, NapiCallbackInfo &info);
62 napi_value OnGetArea(napi_env env, NapiCallbackInfo &info);
63 napi_value OnGetApplicationContext(napi_env env, NapiCallbackInfo &info);
64
65 protected:
66 std::weak_ptr<Context> context_;
67 };
68
Finalizer(napi_env env,void * data,void * hint)69 void JsBaseContext::Finalizer(napi_env env, void *data, void *hint)
70 {
71 TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
72 std::unique_ptr<JsBaseContext>(static_cast<JsBaseContext*>(data));
73 }
74
CreateBundleContext(napi_env env,napi_callback_info info)75 napi_value JsBaseContext::CreateBundleContext(napi_env env, napi_callback_info info)
76 {
77 return nullptr;
78 }
79
GetApplicationContext(napi_env env,napi_callback_info info)80 napi_value JsBaseContext::GetApplicationContext(napi_env env, napi_callback_info info)
81 {
82 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetApplicationContext, BASE_CONTEXT_NAME);
83 }
84
SwitchArea(napi_env env,napi_callback_info info)85 napi_value JsBaseContext::SwitchArea(napi_env env, napi_callback_info info)
86 {
87 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnSwitchArea, BASE_CONTEXT_NAME);
88 }
89
OnSwitchArea(napi_env env,NapiCallbackInfo & info)90 napi_value JsBaseContext::OnSwitchArea(napi_env env, NapiCallbackInfo &info)
91 {
92 if (info.argc == 0) {
93 TAG_LOGE(AAFwkTag::ABILITY_SIM, "invalid argc");
94 return CreateJsUndefined(env);
95 }
96
97 auto context = context_.lock();
98 if (!context) {
99 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
100 return CreateJsUndefined(env);
101 }
102
103 int mode = 0;
104 if (!ConvertFromJsValue(env, info.argv[0], mode)) {
105 TAG_LOGE(AAFwkTag::ABILITY_SIM, "Parse mode failed");
106 return CreateJsUndefined(env);
107 }
108
109 context->SwitchArea(mode);
110
111 napi_value object = info.thisVar;
112 if (object == nullptr) {
113 TAG_LOGE(AAFwkTag::ABILITY_SIM, "null object");
114 return CreateJsUndefined(env);
115 }
116 BindNativeProperty(env, object, "cacheDir", GetCacheDir);
117 BindNativeProperty(env, object, "tempDir", GetTempDir);
118 BindNativeProperty(env, object, "resourceDir", GetResourceDir);
119 BindNativeProperty(env, object, "filesDir", GetFilesDir);
120 BindNativeProperty(env, object, "distributedFilesDir", GetDistributedFilesDir);
121 BindNativeProperty(env, object, "databaseDir", GetDatabaseDir);
122 BindNativeProperty(env, object, "preferencesDir", GetPreferencesDir);
123 BindNativeProperty(env, object, "bundleCodeDir", GetBundleCodeDir);
124 BindNativeProperty(env, object, "cloudFileDir", GetCloudFileDir);
125 return CreateJsUndefined(env);
126 }
127
CreateModuleContext(napi_env env,napi_callback_info info)128 napi_value JsBaseContext::CreateModuleContext(napi_env env, napi_callback_info info)
129 {
130 return nullptr;
131 }
132
CreateModuleResourceManager(napi_env env,napi_callback_info info)133 napi_value JsBaseContext::CreateModuleResourceManager(napi_env env, napi_callback_info info)
134 {
135 return nullptr;
136 }
137
GetArea(napi_env env,napi_callback_info info)138 napi_value JsBaseContext::GetArea(napi_env env, napi_callback_info info)
139 {
140 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetArea, BASE_CONTEXT_NAME);
141 }
142
OnGetArea(napi_env env,NapiCallbackInfo & info)143 napi_value JsBaseContext::OnGetArea(napi_env env, NapiCallbackInfo &info)
144 {
145 auto context = context_.lock();
146 if (!context) {
147 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
148 return CreateJsUndefined(env);
149 }
150 int area = context->GetArea();
151 return CreateJsValue(env, area);
152 }
153
GetCacheDir(napi_env env,napi_callback_info info)154 napi_value JsBaseContext::GetCacheDir(napi_env env, napi_callback_info info)
155 {
156 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetCacheDir, BASE_CONTEXT_NAME);
157 }
158
OnGetCacheDir(napi_env env,NapiCallbackInfo & info)159 napi_value JsBaseContext::OnGetCacheDir(napi_env env, NapiCallbackInfo &info)
160 {
161 auto context = context_.lock();
162 if (!context) {
163 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
164 return CreateJsUndefined(env);
165 }
166 std::string path = context->GetCacheDir();
167 return CreateJsValue(env, path);
168 }
169
GetTempDir(napi_env env,napi_callback_info info)170 napi_value JsBaseContext::GetTempDir(napi_env env, napi_callback_info info)
171 {
172 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetTempDir, BASE_CONTEXT_NAME);
173 }
174
OnGetTempDir(napi_env env,NapiCallbackInfo & info)175 napi_value JsBaseContext::OnGetTempDir(napi_env env, NapiCallbackInfo &info)
176 {
177 auto context = context_.lock();
178 if (!context) {
179 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
180 return CreateJsUndefined(env);
181 }
182 std::string path = context->GetTempDir();
183 return CreateJsValue(env, path);
184 }
185
GetResourceDir(napi_env env,napi_callback_info info)186 napi_value JsBaseContext::GetResourceDir(napi_env env, napi_callback_info info)
187 {
188 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetResourceDir, BASE_CONTEXT_NAME);
189 }
190
OnGetResourceDir(napi_env env,NapiCallbackInfo & info)191 napi_value JsBaseContext::OnGetResourceDir(napi_env env, NapiCallbackInfo &info)
192 {
193 auto context = context_.lock();
194 if (!context) {
195 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
196 return CreateJsUndefined(env);
197 }
198 std::string path = context->GetResourceDir();
199 return CreateJsValue(env, path);
200 }
201
GetFilesDir(napi_env env,napi_callback_info info)202 napi_value JsBaseContext::GetFilesDir(napi_env env, napi_callback_info info)
203 {
204 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetFilesDir, BASE_CONTEXT_NAME);
205 }
206
OnGetFilesDir(napi_env env,NapiCallbackInfo & info)207 napi_value JsBaseContext::OnGetFilesDir(napi_env env, NapiCallbackInfo &info)
208 {
209 auto context = context_.lock();
210 if (!context) {
211 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
212 return CreateJsUndefined(env);
213 }
214 std::string path = context->GetFilesDir();
215 return CreateJsValue(env, path);
216 }
217
GetDistributedFilesDir(napi_env env,napi_callback_info info)218 napi_value JsBaseContext::GetDistributedFilesDir(napi_env env, napi_callback_info info)
219 {
220 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetDistributedFilesDir, BASE_CONTEXT_NAME);
221 }
222
OnGetDistributedFilesDir(napi_env env,NapiCallbackInfo & info)223 napi_value JsBaseContext::OnGetDistributedFilesDir(napi_env env, NapiCallbackInfo &info)
224 {
225 auto context = context_.lock();
226 if (!context) {
227 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
228 return CreateJsUndefined(env);
229 }
230 std::string path = context->GetDistributedFilesDir();
231 return CreateJsValue(env, path);
232 }
233
GetDatabaseDir(napi_env env,napi_callback_info info)234 napi_value JsBaseContext::GetDatabaseDir(napi_env env, napi_callback_info info)
235 {
236 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetDatabaseDir, BASE_CONTEXT_NAME);
237 }
238
OnGetDatabaseDir(napi_env env,NapiCallbackInfo & info)239 napi_value JsBaseContext::OnGetDatabaseDir(napi_env env, NapiCallbackInfo &info)
240 {
241 auto context = context_.lock();
242 if (!context) {
243 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
244 return CreateJsUndefined(env);
245 }
246 std::string path = context->GetDatabaseDir();
247 return CreateJsValue(env, path);
248 }
249
GetPreferencesDir(napi_env env,napi_callback_info info)250 napi_value JsBaseContext::GetPreferencesDir(napi_env env, napi_callback_info info)
251 {
252 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetPreferencesDir, BASE_CONTEXT_NAME);
253 }
254
OnGetPreferencesDir(napi_env env,NapiCallbackInfo & info)255 napi_value JsBaseContext::OnGetPreferencesDir(napi_env env, NapiCallbackInfo &info)
256 {
257 auto context = context_.lock();
258 if (!context) {
259 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
260 return CreateJsUndefined(env);
261 }
262 std::string path = context->GetPreferencesDir();
263 return CreateJsValue(env, path);
264 }
265
GetBundleCodeDir(napi_env env,napi_callback_info info)266 napi_value JsBaseContext::GetBundleCodeDir(napi_env env, napi_callback_info info)
267 {
268 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetBundleCodeDir, BASE_CONTEXT_NAME);
269 }
270
OnGetBundleCodeDir(napi_env env,NapiCallbackInfo & info)271 napi_value JsBaseContext::OnGetBundleCodeDir(napi_env env, NapiCallbackInfo &info)
272 {
273 auto context = context_.lock();
274 if (!context) {
275 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
276 return CreateJsUndefined(env);
277 }
278 std::string path = context->GetBundleCodeDir();
279 return CreateJsValue(env, path);
280 }
281
GetCloudFileDir(napi_env env,napi_callback_info info)282 napi_value JsBaseContext::GetCloudFileDir(napi_env env, napi_callback_info info)
283 {
284 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetCloudFileDir, BASE_CONTEXT_NAME);
285 }
286
OnGetCloudFileDir(napi_env env,NapiCallbackInfo & info)287 napi_value JsBaseContext::OnGetCloudFileDir(napi_env env, NapiCallbackInfo &info)
288 {
289 auto context = context_.lock();
290 if (!context) {
291 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
292 return CreateJsUndefined(env);
293 }
294 std::string path = context->GetCloudFileDir();
295 return CreateJsValue(env, path);
296 }
297
OnGetApplicationContext(napi_env env,NapiCallbackInfo & info)298 napi_value JsBaseContext::OnGetApplicationContext(napi_env env, NapiCallbackInfo &info)
299 {
300 TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
301 napi_value value = JsApplicationContextUtils::CreateJsApplicationContext(env, context_.lock());
302 auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.ApplicationContext", &value, 1);
303 if (systemModule == nullptr) {
304 return CreateJsUndefined(env);
305 }
306 auto contextObj = systemModule->GetNapiValue();
307 return contextObj;
308 }
309 } // namespace
310
CreateJsBaseContext(napi_env env,std::shared_ptr<Context> context,bool keepContext)311 napi_value CreateJsBaseContext(napi_env env, std::shared_ptr<Context> context, bool keepContext)
312 {
313 napi_value object = nullptr;
314 napi_create_object(env, &object);
315 if (object == nullptr) {
316 TAG_LOGW(AAFwkTag::ABILITY_SIM, "null object");
317 return object;
318 }
319
320 auto appInfo = context->GetApplicationInfo();
321 if (appInfo != nullptr) {
322 napi_set_named_property(env, object, "applicationInfo", CreateJsApplicationInfo(env, *appInfo));
323 }
324 auto hapModuleInfo = context->GetHapModuleInfo();
325 if (hapModuleInfo != nullptr) {
326 napi_set_named_property(env, object, "currentHapModuleInfo", CreateJsHapModuleInfo(env, *hapModuleInfo));
327 }
328
329 auto jsContext = std::make_unique<JsBaseContext>(context);
330 SetNamedNativePointer(env, object, BASE_CONTEXT_NAME, jsContext.release(), JsBaseContext::Finalizer);
331
332 BindNativeProperty(env, object, "cacheDir", JsBaseContext::GetCacheDir);
333 BindNativeProperty(env, object, "tempDir", JsBaseContext::GetTempDir);
334 BindNativeProperty(env, object, "resourceDir", JsBaseContext::GetResourceDir);
335 BindNativeProperty(env, object, "filesDir", JsBaseContext::GetFilesDir);
336 BindNativeProperty(env, object, "distributedFilesDir", JsBaseContext::GetDistributedFilesDir);
337 BindNativeProperty(env, object, "databaseDir", JsBaseContext::GetDatabaseDir);
338 BindNativeProperty(env, object, "preferencesDir", JsBaseContext::GetPreferencesDir);
339 BindNativeProperty(env, object, "bundleCodeDir", JsBaseContext::GetBundleCodeDir);
340 BindNativeProperty(env, object, "cloudFileDir", JsBaseContext::GetCloudFileDir);
341 BindNativeProperty(env, object, "area", JsBaseContext::GetArea);
342 const char *moduleName = "JsBaseContext";
343 BindNativeFunction(env, object, "createBundleContext", moduleName, JsBaseContext::CreateBundleContext);
344 BindNativeFunction(env, object, "getApplicationContext", moduleName, JsBaseContext::GetApplicationContext);
345 BindNativeFunction(env, object, "switchArea", moduleName, JsBaseContext::SwitchArea);
346 BindNativeFunction(env, object, "getArea", moduleName, JsBaseContext::GetArea);
347 BindNativeFunction(env, object, "createModuleContext", moduleName, JsBaseContext::CreateModuleContext);
348 BindNativeFunction(env, object, "createModuleResourceManager", moduleName,
349 JsBaseContext::CreateModuleResourceManager);
350
351 return object;
352 }
353 } // namespace AbilityRuntime
354 } // namespace OHOS
355