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
20 #include "ability_runtime_error_util.h"
21 #include "context_impl.h"
22 #include "hilog_tag_wrapper.h"
23 #include "js_application_context_utils.h"
24 #include "js_data_converter.h"
25 #include "js_error_utils.h"
26 #include "js_resource_manager_utils.h"
27 #include "js_runtime_utils.h"
28
29 namespace OHOS {
30 namespace AbilityRuntime {
31 namespace {
32 constexpr char BASE_CONTEXT_NAME[] = "__base_context_ptr__";
33
DetachNewBaseContext(napi_env,void * nativeObject,void *)34 void *DetachNewBaseContext(napi_env, void *nativeObject, void *)
35 {
36 auto *origContext = static_cast<std::weak_ptr<Context> *>(nativeObject);
37 if (origContext == nullptr) {
38 TAG_LOGE(AAFwkTag::ABILITY_SIM, "origContext is null");
39 return nullptr;
40 }
41 TAG_LOGD(AAFwkTag::ABILITY_SIM, "New detached base context");
42 auto *detachNewContext = new (std::nothrow) std::weak_ptr<Context>(*origContext);
43 return detachNewContext;
44 }
45
DetachFinalizeBaseContext(void * detachedObject,void *)46 void DetachFinalizeBaseContext(void *detachedObject, void *)
47 {
48 TAG_LOGD(AAFwkTag::ABILITY_SIM, "Finalizer detached base context");
49 delete static_cast<std::weak_ptr<Context> *>(detachedObject);
50 }
51
52 class JsBaseContext {
53 public:
JsBaseContext(std::weak_ptr<Context> && context)54 explicit JsBaseContext(std::weak_ptr<Context> &&context) : context_(std::move(context)) {}
55 virtual ~JsBaseContext() = default;
56
57 static void Finalizer(napi_env env, void *data, void *hint);
58 static napi_value CreateBundleContext(napi_env env, napi_callback_info info);
59 static napi_value GetApplicationContext(napi_env env, napi_callback_info info);
60 static napi_value SwitchArea(napi_env env, napi_callback_info info);
61 static napi_value GetArea(napi_env env, napi_callback_info info);
62 static napi_value CreateModuleContext(napi_env env, napi_callback_info info);
63 static napi_value CreateModuleResourceManager(napi_env env, napi_callback_info info);
64
65 static napi_value GetCacheDir(napi_env env, napi_callback_info info);
66 static napi_value GetTempDir(napi_env env, napi_callback_info info);
67 static napi_value GetResourceDir(napi_env env, napi_callback_info info);
68 static napi_value GetFilesDir(napi_env env, napi_callback_info info);
69 static napi_value GetDistributedFilesDir(napi_env env, napi_callback_info info);
70 static napi_value GetDatabaseDir(napi_env env, napi_callback_info info);
71 static napi_value GetPreferencesDir(napi_env env, napi_callback_info info);
72 static napi_value GetBundleCodeDir(napi_env env, napi_callback_info info);
73 static napi_value GetCloudFileDir(napi_env env, napi_callback_info info);
74
75 napi_value OnGetCacheDir(napi_env env, NapiCallbackInfo &info);
76 napi_value OnGetTempDir(napi_env env, NapiCallbackInfo &info);
77 napi_value OnGetResourceDir(napi_env env, NapiCallbackInfo &info);
78 napi_value OnGetFilesDir(napi_env env, NapiCallbackInfo &info);
79 napi_value OnGetDistributedFilesDir(napi_env env, NapiCallbackInfo &info);
80 napi_value OnGetDatabaseDir(napi_env env, NapiCallbackInfo &info);
81 napi_value OnGetPreferencesDir(napi_env env, NapiCallbackInfo &info);
82 napi_value OnGetBundleCodeDir(napi_env env, NapiCallbackInfo &info);
83 napi_value OnGetCloudFileDir(napi_env env, NapiCallbackInfo &info);
84 napi_value OnSwitchArea(napi_env env, NapiCallbackInfo &info);
85 napi_value OnGetArea(napi_env env, NapiCallbackInfo &info);
86 napi_value OnGetApplicationContext(napi_env env, NapiCallbackInfo &info);
87
88 protected:
89 std::weak_ptr<Context> context_;
90
91 private:
92 napi_value CreateJsModuleContext(napi_env env, const std::shared_ptr<Context> &moduleContext);
93 napi_value OnCreateModuleContext(napi_env env, NapiCallbackInfo &info);
94 bool CheckCallerIsSystemApp();
95 };
96
Finalizer(napi_env env,void * data,void * hint)97 void JsBaseContext::Finalizer(napi_env env, void *data, void *hint)
98 {
99 TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
100 std::unique_ptr<JsBaseContext>(static_cast<JsBaseContext*>(data));
101 }
102
CreateBundleContext(napi_env env,napi_callback_info info)103 napi_value JsBaseContext::CreateBundleContext(napi_env env, napi_callback_info info)
104 {
105 return nullptr;
106 }
107
GetApplicationContext(napi_env env,napi_callback_info info)108 napi_value JsBaseContext::GetApplicationContext(napi_env env, napi_callback_info info)
109 {
110 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetApplicationContext, BASE_CONTEXT_NAME);
111 }
112
SwitchArea(napi_env env,napi_callback_info info)113 napi_value JsBaseContext::SwitchArea(napi_env env, napi_callback_info info)
114 {
115 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnSwitchArea, BASE_CONTEXT_NAME);
116 }
117
OnSwitchArea(napi_env env,NapiCallbackInfo & info)118 napi_value JsBaseContext::OnSwitchArea(napi_env env, NapiCallbackInfo &info)
119 {
120 if (info.argc == 0) {
121 TAG_LOGE(AAFwkTag::ABILITY_SIM, "invalid argc");
122 return CreateJsUndefined(env);
123 }
124
125 auto context = context_.lock();
126 if (!context) {
127 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
128 return CreateJsUndefined(env);
129 }
130
131 int mode = 0;
132 if (!ConvertFromJsValue(env, info.argv[0], mode)) {
133 TAG_LOGE(AAFwkTag::ABILITY_SIM, "Parse mode failed");
134 return CreateJsUndefined(env);
135 }
136
137 context->SwitchArea(mode);
138
139 napi_value object = info.thisVar;
140 if (object == nullptr) {
141 TAG_LOGE(AAFwkTag::ABILITY_SIM, "null object");
142 return CreateJsUndefined(env);
143 }
144 BindNativeProperty(env, object, "cacheDir", GetCacheDir);
145 BindNativeProperty(env, object, "tempDir", GetTempDir);
146 BindNativeProperty(env, object, "resourceDir", GetResourceDir);
147 BindNativeProperty(env, object, "filesDir", GetFilesDir);
148 BindNativeProperty(env, object, "distributedFilesDir", GetDistributedFilesDir);
149 BindNativeProperty(env, object, "databaseDir", GetDatabaseDir);
150 BindNativeProperty(env, object, "preferencesDir", GetPreferencesDir);
151 BindNativeProperty(env, object, "bundleCodeDir", GetBundleCodeDir);
152 BindNativeProperty(env, object, "cloudFileDir", GetCloudFileDir);
153 return CreateJsUndefined(env);
154 }
155
CreateModuleContext(napi_env env,napi_callback_info info)156 napi_value JsBaseContext::CreateModuleContext(napi_env env, napi_callback_info info)
157 {
158 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnCreateModuleContext, BASE_CONTEXT_NAME);
159 }
OnCreateModuleContext(napi_env env,NapiCallbackInfo & info)160 napi_value JsBaseContext::OnCreateModuleContext(napi_env env, NapiCallbackInfo &info)
161 {
162 auto context = context_.lock();
163 if (!context) {
164 TAG_LOGW(AAFwkTag::ABILITY_SIM, "null context");
165 AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER);
166 return CreateJsUndefined(env);
167 }
168 std::shared_ptr<Context> moduleContext = nullptr;
169 std::string moduleName;
170 if (!ConvertFromJsValue(env, info.argv[1], moduleName)) {
171 TAG_LOGD(AAFwkTag::ABILITY_SIM, "Parse inner module name");
172 if (!ConvertFromJsValue(env, info.argv[0], moduleName)) {
173 TAG_LOGE(AAFwkTag::ABILITY_SIM, "Parse moduleName failed");
174 ThrowInvalidParamError(env, "Parse param moduleName failed, moduleName must be string.");
175 return CreateJsUndefined(env);
176 }
177 moduleContext = context->CreateModuleContext(moduleName);
178 } else {
179 std::string bundleName;
180 if (!ConvertFromJsValue(env, info.argv[0], bundleName)) {
181 TAG_LOGE(AAFwkTag::ABILITY_SIM, "Parse bundleName failed");
182 ThrowInvalidParamError(env, "Parse param bundleName failed, bundleName must be string.");
183 return CreateJsUndefined(env);
184 }
185 if (!CheckCallerIsSystemApp()) {
186 TAG_LOGE(AAFwkTag::ABILITY_SIM, "not system-app");
187 AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_NOT_SYSTEM_APP);
188 return CreateJsUndefined(env);
189 }
190 TAG_LOGD(AAFwkTag::ABILITY_SIM, "Parse outer module name");
191 moduleContext = context->CreateModuleContext(bundleName, moduleName);
192 }
193 if (!moduleContext) {
194 TAG_LOGE(AAFwkTag::ABILITY_SIM, "null moduleContext");
195 AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER);
196 return CreateJsUndefined(env);
197 }
198 return CreateJsModuleContext(env, moduleContext);
199 }
200
CreateJsModuleContext(napi_env env,const std::shared_ptr<Context> & moduleContext)201 napi_value JsBaseContext::CreateJsModuleContext(napi_env env, const std::shared_ptr<Context> &moduleContext)
202 {
203 napi_value value = CreateJsBaseContext(env, moduleContext, true);
204
205 auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.Context", &value, 1);
206 if (systemModule == nullptr) {
207 TAG_LOGW(AAFwkTag::ABILITY_SIM, "null systemModule");
208 AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER);
209 return CreateJsUndefined(env);
210 }
211 napi_value object = systemModule->GetNapiValue();
212 if (!CheckTypeForNapiValue(env, object, napi_object)) {
213 TAG_LOGE(AAFwkTag::ABILITY_SIM, "get object failed");
214 AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER);
215 return CreateJsUndefined(env);
216 }
217 auto workContext = new (std::nothrow) std::weak_ptr<Context>(moduleContext);
218 napi_coerce_to_native_binding_object(env, object, DetachCallbackFunc, AttachBaseContext, workContext, nullptr);
219 auto res = napi_wrap(env, object, workContext,
220 [](napi_env, void *data, void *) {
221 TAG_LOGD(AAFwkTag::ABILITY_SIM, "Finalizer for weak_ptr module context is called");
222 delete static_cast<std::weak_ptr<Context> *>(data);
223 },
224 nullptr, nullptr);
225 if (res != napi_ok && workContext != nullptr) {
226 TAG_LOGE(AAFwkTag::ABILITY_SIM, "napi_wrap failed:%{public}d", res);
227 delete workContext;
228 return CreateJsUndefined(env);
229 }
230 return object;
231 }
232
CreateModuleResourceManager(napi_env env,napi_callback_info info)233 napi_value JsBaseContext::CreateModuleResourceManager(napi_env env, napi_callback_info info)
234 {
235 return nullptr;
236 }
237
GetArea(napi_env env,napi_callback_info info)238 napi_value JsBaseContext::GetArea(napi_env env, napi_callback_info info)
239 {
240 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetArea, BASE_CONTEXT_NAME);
241 }
242
OnGetArea(napi_env env,NapiCallbackInfo & info)243 napi_value JsBaseContext::OnGetArea(napi_env env, NapiCallbackInfo &info)
244 {
245 auto context = context_.lock();
246 if (!context) {
247 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
248 return CreateJsUndefined(env);
249 }
250 int area = context->GetArea();
251 return CreateJsValue(env, area);
252 }
253
GetCacheDir(napi_env env,napi_callback_info info)254 napi_value JsBaseContext::GetCacheDir(napi_env env, napi_callback_info info)
255 {
256 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetCacheDir, BASE_CONTEXT_NAME);
257 }
258
OnGetCacheDir(napi_env env,NapiCallbackInfo & info)259 napi_value JsBaseContext::OnGetCacheDir(napi_env env, NapiCallbackInfo &info)
260 {
261 auto context = context_.lock();
262 if (!context) {
263 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
264 return CreateJsUndefined(env);
265 }
266 std::string path = context->GetCacheDir();
267 return CreateJsValue(env, path);
268 }
269
GetTempDir(napi_env env,napi_callback_info info)270 napi_value JsBaseContext::GetTempDir(napi_env env, napi_callback_info info)
271 {
272 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetTempDir, BASE_CONTEXT_NAME);
273 }
274
OnGetTempDir(napi_env env,NapiCallbackInfo & info)275 napi_value JsBaseContext::OnGetTempDir(napi_env env, NapiCallbackInfo &info)
276 {
277 auto context = context_.lock();
278 if (!context) {
279 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
280 return CreateJsUndefined(env);
281 }
282 std::string path = context->GetTempDir();
283 return CreateJsValue(env, path);
284 }
285
GetResourceDir(napi_env env,napi_callback_info info)286 napi_value JsBaseContext::GetResourceDir(napi_env env, napi_callback_info info)
287 {
288 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetResourceDir, BASE_CONTEXT_NAME);
289 }
290
OnGetResourceDir(napi_env env,NapiCallbackInfo & info)291 napi_value JsBaseContext::OnGetResourceDir(napi_env env, NapiCallbackInfo &info)
292 {
293 auto context = context_.lock();
294 if (!context) {
295 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
296 return CreateJsUndefined(env);
297 }
298 std::string path = context->GetResourceDir();
299 return CreateJsValue(env, path);
300 }
301
GetFilesDir(napi_env env,napi_callback_info info)302 napi_value JsBaseContext::GetFilesDir(napi_env env, napi_callback_info info)
303 {
304 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetFilesDir, BASE_CONTEXT_NAME);
305 }
306
OnGetFilesDir(napi_env env,NapiCallbackInfo & info)307 napi_value JsBaseContext::OnGetFilesDir(napi_env env, NapiCallbackInfo &info)
308 {
309 auto context = context_.lock();
310 if (!context) {
311 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
312 return CreateJsUndefined(env);
313 }
314 std::string path = context->GetFilesDir();
315 return CreateJsValue(env, path);
316 }
317
GetDistributedFilesDir(napi_env env,napi_callback_info info)318 napi_value JsBaseContext::GetDistributedFilesDir(napi_env env, napi_callback_info info)
319 {
320 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetDistributedFilesDir, BASE_CONTEXT_NAME);
321 }
322
OnGetDistributedFilesDir(napi_env env,NapiCallbackInfo & info)323 napi_value JsBaseContext::OnGetDistributedFilesDir(napi_env env, NapiCallbackInfo &info)
324 {
325 auto context = context_.lock();
326 if (!context) {
327 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
328 return CreateJsUndefined(env);
329 }
330 std::string path = context->GetDistributedFilesDir();
331 return CreateJsValue(env, path);
332 }
333
GetDatabaseDir(napi_env env,napi_callback_info info)334 napi_value JsBaseContext::GetDatabaseDir(napi_env env, napi_callback_info info)
335 {
336 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetDatabaseDir, BASE_CONTEXT_NAME);
337 }
338
OnGetDatabaseDir(napi_env env,NapiCallbackInfo & info)339 napi_value JsBaseContext::OnGetDatabaseDir(napi_env env, NapiCallbackInfo &info)
340 {
341 auto context = context_.lock();
342 if (!context) {
343 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
344 return CreateJsUndefined(env);
345 }
346 std::string path = context->GetDatabaseDir();
347 return CreateJsValue(env, path);
348 }
349
GetPreferencesDir(napi_env env,napi_callback_info info)350 napi_value JsBaseContext::GetPreferencesDir(napi_env env, napi_callback_info info)
351 {
352 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetPreferencesDir, BASE_CONTEXT_NAME);
353 }
354
OnGetPreferencesDir(napi_env env,NapiCallbackInfo & info)355 napi_value JsBaseContext::OnGetPreferencesDir(napi_env env, NapiCallbackInfo &info)
356 {
357 auto context = context_.lock();
358 if (!context) {
359 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
360 return CreateJsUndefined(env);
361 }
362 std::string path = context->GetPreferencesDir();
363 return CreateJsValue(env, path);
364 }
365
GetBundleCodeDir(napi_env env,napi_callback_info info)366 napi_value JsBaseContext::GetBundleCodeDir(napi_env env, napi_callback_info info)
367 {
368 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetBundleCodeDir, BASE_CONTEXT_NAME);
369 }
370
OnGetBundleCodeDir(napi_env env,NapiCallbackInfo & info)371 napi_value JsBaseContext::OnGetBundleCodeDir(napi_env env, NapiCallbackInfo &info)
372 {
373 auto context = context_.lock();
374 if (!context) {
375 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
376 return CreateJsUndefined(env);
377 }
378 std::string path = context->GetBundleCodeDir();
379 return CreateJsValue(env, path);
380 }
381
GetCloudFileDir(napi_env env,napi_callback_info info)382 napi_value JsBaseContext::GetCloudFileDir(napi_env env, napi_callback_info info)
383 {
384 GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsBaseContext, OnGetCloudFileDir, BASE_CONTEXT_NAME);
385 }
386
OnGetCloudFileDir(napi_env env,NapiCallbackInfo & info)387 napi_value JsBaseContext::OnGetCloudFileDir(napi_env env, NapiCallbackInfo &info)
388 {
389 auto context = context_.lock();
390 if (!context) {
391 TAG_LOGW(AAFwkTag::ABILITY_SIM, "context released");
392 return CreateJsUndefined(env);
393 }
394 std::string path = context->GetCloudFileDir();
395 return CreateJsValue(env, path);
396 }
397
OnGetApplicationContext(napi_env env,NapiCallbackInfo & info)398 napi_value JsBaseContext::OnGetApplicationContext(napi_env env, NapiCallbackInfo &info)
399 {
400 TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
401 napi_value value = JsApplicationContextUtils::CreateJsApplicationContext(env, context_.lock());
402 auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.ApplicationContext", &value, 1);
403 if (systemModule == nullptr) {
404 return CreateJsUndefined(env);
405 }
406 auto contextObj = systemModule->GetNapiValue();
407 return contextObj;
408 }
409
CheckCallerIsSystemApp()410 bool JsBaseContext::CheckCallerIsSystemApp()
411 {
412 return true;
413 }
414 } // namespace
415
CreateJsBaseContext(napi_env env,std::shared_ptr<Context> context,bool keepContext)416 napi_value CreateJsBaseContext(napi_env env, std::shared_ptr<Context> context, bool keepContext)
417 {
418 napi_value object = nullptr;
419 napi_create_object(env, &object);
420 if (object == nullptr) {
421 TAG_LOGW(AAFwkTag::ABILITY_SIM, "null object");
422 return object;
423 }
424
425 auto appInfo = context->GetApplicationInfo();
426 if (appInfo != nullptr) {
427 napi_set_named_property(env, object, "applicationInfo", CreateJsApplicationInfo(env, *appInfo));
428 }
429 auto hapModuleInfo = context->GetHapModuleInfo();
430 if (hapModuleInfo != nullptr) {
431 napi_set_named_property(env, object, "currentHapModuleInfo", CreateJsHapModuleInfo(env, *hapModuleInfo));
432 }
433
434 auto resourceManager = context->GetResourceManager();
435 if (resourceManager != nullptr) {
436 auto jsResourceManager = CreateJsResourceManager(env, resourceManager, context);
437 if (jsResourceManager != nullptr) {
438 napi_set_named_property(env, object, "resourceManager", jsResourceManager);
439 } else {
440 TAG_LOGE(AAFwkTag::ABILITY_SIM, "null jsResourceManager");
441 }
442 }
443
444 auto jsContext = std::make_unique<JsBaseContext>(context);
445 SetNamedNativePointer(env, object, BASE_CONTEXT_NAME, jsContext.release(), JsBaseContext::Finalizer);
446
447 BindNativeProperty(env, object, "cacheDir", JsBaseContext::GetCacheDir);
448 BindNativeProperty(env, object, "tempDir", JsBaseContext::GetTempDir);
449 BindNativeProperty(env, object, "resourceDir", JsBaseContext::GetResourceDir);
450 BindNativeProperty(env, object, "filesDir", JsBaseContext::GetFilesDir);
451 BindNativeProperty(env, object, "distributedFilesDir", JsBaseContext::GetDistributedFilesDir);
452 BindNativeProperty(env, object, "databaseDir", JsBaseContext::GetDatabaseDir);
453 BindNativeProperty(env, object, "preferencesDir", JsBaseContext::GetPreferencesDir);
454 BindNativeProperty(env, object, "bundleCodeDir", JsBaseContext::GetBundleCodeDir);
455 BindNativeProperty(env, object, "cloudFileDir", JsBaseContext::GetCloudFileDir);
456 BindNativeProperty(env, object, "area", JsBaseContext::GetArea);
457 const char *moduleName = "JsBaseContext";
458 BindNativeFunction(env, object, "createBundleContext", moduleName, JsBaseContext::CreateBundleContext);
459 BindNativeFunction(env, object, "getApplicationContext", moduleName, JsBaseContext::GetApplicationContext);
460 BindNativeFunction(env, object, "switchArea", moduleName, JsBaseContext::SwitchArea);
461 BindNativeFunction(env, object, "getArea", moduleName, JsBaseContext::GetArea);
462 BindNativeFunction(env, object, "createModuleContext", moduleName, JsBaseContext::CreateModuleContext);
463 BindNativeFunction(env, object, "createModuleResourceManager", moduleName,
464 JsBaseContext::CreateModuleResourceManager);
465
466 return object;
467 }
468
AttachBaseContext(napi_env env,void * value,void * hint)469 napi_value AttachBaseContext(napi_env env, void *value, void *hint)
470 {
471 TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
472 if (value == nullptr || env == nullptr) {
473 TAG_LOGW(AAFwkTag::ABILITY_SIM, "invalid parameter");
474 return nullptr;
475 }
476 auto ptr = reinterpret_cast<std::weak_ptr<Context> *>(value)->lock();
477 if (ptr == nullptr) {
478 TAG_LOGW(AAFwkTag::ABILITY_SIM, "null ptr");
479 return nullptr;
480 }
481 napi_value object = CreateJsBaseContext(env, ptr, true);
482 auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.Context", &object, 1);
483 if (systemModule == nullptr) {
484 TAG_LOGW(AAFwkTag::ABILITY_SIM, "null systemModule");
485 return nullptr;
486 }
487
488 napi_value contextObj = systemModule->GetNapiValue();
489 if (!CheckTypeForNapiValue(env, contextObj, napi_object)) {
490 TAG_LOGE(AAFwkTag::ABILITY_SIM, "get object failed");
491 return nullptr;
492 }
493 auto workContext = new (std::nothrow) std::weak_ptr<Context>(ptr);
494 napi_coerce_to_native_binding_object(
495 env, contextObj, DetachNewBaseContext, AttachBaseContext, workContext, nullptr);
496 napi_add_detached_finalizer(env, contextObj, DetachFinalizeBaseContext, nullptr);
497 auto res = napi_wrap(env, contextObj, workContext,
498 [](napi_env, void *data, void *) {
499 TAG_LOGD(AAFwkTag::ABILITY_SIM, "Finalizer for weak_ptr base context is called");
500 delete static_cast<std::weak_ptr<Context> *>(data);
501 },
502 nullptr, nullptr);
503 if (res != napi_ok && workContext != nullptr) {
504 TAG_LOGE(AAFwkTag::ABILITY_SIM, "napi_wrap failed:%{public}d", res);
505 delete workContext;
506 return nullptr;
507 }
508 return contextObj;
509 }
510 } // namespace AbilityRuntime
511 } // namespace OHOS
512