1 /*
2 * Copyright (c) 2023 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_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(NativeEngine *engine, void *data, void *hint);
35 static NativeValue *CreateBundleContext(NativeEngine *engine, NativeCallbackInfo *info);
36 static NativeValue *GetApplicationContext(NativeEngine *engine, NativeCallbackInfo *info);
37 static NativeValue *SwitchArea(NativeEngine *engine, NativeCallbackInfo *info);
38 static NativeValue *GetArea(NativeEngine *engine, NativeCallbackInfo *info);
39 static NativeValue *CreateModuleContext(NativeEngine *engine, NativeCallbackInfo *info);
40
41 static NativeValue *GetCacheDir(NativeEngine *engine, NativeCallbackInfo *info);
42 static NativeValue *GetTempDir(NativeEngine *engine, NativeCallbackInfo *info);
43 static NativeValue *GetFilesDir(NativeEngine *engine, NativeCallbackInfo *info);
44 static NativeValue *GetDistributedFilesDir(NativeEngine *engine, NativeCallbackInfo *info);
45 static NativeValue *GetDatabaseDir(NativeEngine *engine, NativeCallbackInfo *info);
46 static NativeValue *GetPreferencesDir(NativeEngine *engine, NativeCallbackInfo *info);
47 static NativeValue *GetBundleCodeDir(NativeEngine *engine, NativeCallbackInfo *info);
48
49 NativeValue *OnGetCacheDir(NativeEngine &engine, NativeCallbackInfo &info);
50 NativeValue *OnGetTempDir(NativeEngine &engine, NativeCallbackInfo &info);
51 NativeValue *OnGetFilesDir(NativeEngine &engine, NativeCallbackInfo &info);
52 NativeValue *OnGetDistributedFilesDir(NativeEngine &engine, NativeCallbackInfo &info);
53 NativeValue *OnGetDatabaseDir(NativeEngine &engine, NativeCallbackInfo &info);
54 NativeValue *OnGetPreferencesDir(NativeEngine &engine, NativeCallbackInfo &info);
55 NativeValue *OnGetBundleCodeDir(NativeEngine &engine, NativeCallbackInfo &info);
56 NativeValue *OnSwitchArea(NativeEngine &engine, NativeCallbackInfo &info);
57 NativeValue *OnGetArea(NativeEngine &engine, NativeCallbackInfo &info);
58 NativeValue *OnGetApplicationContext(NativeEngine &engine, NativeCallbackInfo &info);
59
60 protected:
61 std::weak_ptr<Context> context_;
62 };
63
Finalizer(NativeEngine * engine,void * data,void * hint)64 void JsBaseContext::Finalizer(NativeEngine *engine, void *data, void *hint)
65 {
66 HILOG_DEBUG("called");
67 std::unique_ptr<JsBaseContext>(static_cast<JsBaseContext*>(data));
68 }
69
CreateBundleContext(NativeEngine * engine,NativeCallbackInfo * info)70 NativeValue *JsBaseContext::CreateBundleContext(NativeEngine *engine, NativeCallbackInfo *info)
71 {
72 return nullptr;
73 }
74
GetApplicationContext(NativeEngine * engine,NativeCallbackInfo * info)75 NativeValue *JsBaseContext::GetApplicationContext(NativeEngine *engine, NativeCallbackInfo *info)
76 {
77 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
78 return me != nullptr ? me->OnGetApplicationContext(*engine, *info) : nullptr;
79 }
80
SwitchArea(NativeEngine * engine,NativeCallbackInfo * info)81 NativeValue *JsBaseContext::SwitchArea(NativeEngine *engine, NativeCallbackInfo *info)
82 {
83 HILOG_DEBUG("called");
84 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
85 return me != nullptr ? me->OnSwitchArea(*engine, *info) : nullptr;
86 }
87
OnSwitchArea(NativeEngine & engine,NativeCallbackInfo & info)88 NativeValue *JsBaseContext::OnSwitchArea(NativeEngine &engine, NativeCallbackInfo &info)
89 {
90 if (info.argc == 0) {
91 HILOG_ERROR("Not enough params");
92 return engine.CreateUndefined();
93 }
94
95 auto context = context_.lock();
96 if (!context) {
97 HILOG_WARN("context is already released");
98 return engine.CreateUndefined();
99 }
100
101 int mode = 0;
102 if (!ConvertFromJsValue(engine, info.argv[0], mode)) {
103 HILOG_ERROR("Parse mode failed");
104 return engine.CreateUndefined();
105 }
106
107 context->SwitchArea(mode);
108
109 NativeValue *thisVar = info.thisVar;
110 NativeObject *object = ConvertNativeValueTo<NativeObject>(thisVar);
111 if (object == nullptr) {
112 HILOG_ERROR("object is nullptr");
113 return engine.CreateUndefined();
114 }
115 BindNativeProperty(*object, "cacheDir", GetCacheDir);
116 BindNativeProperty(*object, "tempDir", GetTempDir);
117 BindNativeProperty(*object, "filesDir", GetFilesDir);
118 BindNativeProperty(*object, "distributedFilesDir", GetDistributedFilesDir);
119 BindNativeProperty(*object, "databaseDir", GetDatabaseDir);
120 BindNativeProperty(*object, "preferencesDir", GetPreferencesDir);
121 BindNativeProperty(*object, "bundleCodeDir", GetBundleCodeDir);
122 return engine.CreateUndefined();
123 }
124
CreateModuleContext(NativeEngine * engine,NativeCallbackInfo * info)125 NativeValue *JsBaseContext::CreateModuleContext(NativeEngine *engine, NativeCallbackInfo *info)
126 {
127 return nullptr;
128 }
129
GetArea(NativeEngine * engine,NativeCallbackInfo * info)130 NativeValue *JsBaseContext::GetArea(NativeEngine *engine, NativeCallbackInfo *info)
131 {
132 HILOG_DEBUG("called");
133 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
134 return me != nullptr ? me->OnGetArea(*engine, *info) : nullptr;
135 }
136
OnGetArea(NativeEngine & engine,NativeCallbackInfo & info)137 NativeValue *JsBaseContext::OnGetArea(NativeEngine &engine, NativeCallbackInfo &info)
138 {
139 auto context = context_.lock();
140 if (!context) {
141 HILOG_WARN("context is already released");
142 return engine.CreateUndefined();
143 }
144 int area = context->GetArea();
145 return engine.CreateNumber(area);
146 }
147
GetCacheDir(NativeEngine * engine,NativeCallbackInfo * info)148 NativeValue *JsBaseContext::GetCacheDir(NativeEngine *engine, NativeCallbackInfo *info)
149 {
150 HILOG_DEBUG("called");
151 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
152 return me != nullptr ? me->OnGetCacheDir(*engine, *info) : nullptr;
153 }
154
OnGetCacheDir(NativeEngine & engine,NativeCallbackInfo & info)155 NativeValue *JsBaseContext::OnGetCacheDir(NativeEngine &engine, NativeCallbackInfo &info)
156 {
157 auto context = context_.lock();
158 if (!context) {
159 HILOG_WARN("context is already released");
160 return engine.CreateUndefined();
161 }
162 std::string path = context->GetCacheDir();
163 return engine.CreateString(path.c_str(), path.length());
164 }
165
GetTempDir(NativeEngine * engine,NativeCallbackInfo * info)166 NativeValue *JsBaseContext::GetTempDir(NativeEngine *engine, NativeCallbackInfo *info)
167 {
168 HILOG_DEBUG("called");
169 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
170 return me != nullptr ? me->OnGetTempDir(*engine, *info) : nullptr;
171 }
172
OnGetTempDir(NativeEngine & engine,NativeCallbackInfo & info)173 NativeValue *JsBaseContext::OnGetTempDir(NativeEngine &engine, NativeCallbackInfo &info)
174 {
175 auto context = context_.lock();
176 if (!context) {
177 HILOG_WARN("context is already released");
178 return engine.CreateUndefined();
179 }
180 std::string path = context->GetTempDir();
181 return engine.CreateString(path.c_str(), path.length());
182 }
183
GetFilesDir(NativeEngine * engine,NativeCallbackInfo * info)184 NativeValue *JsBaseContext::GetFilesDir(NativeEngine *engine, NativeCallbackInfo *info)
185 {
186 HILOG_DEBUG("called");
187 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
188 return me != nullptr ? me->OnGetFilesDir(*engine, *info) : nullptr;
189 }
190
OnGetFilesDir(NativeEngine & engine,NativeCallbackInfo & info)191 NativeValue *JsBaseContext::OnGetFilesDir(NativeEngine &engine, NativeCallbackInfo &info)
192 {
193 auto context = context_.lock();
194 if (!context) {
195 HILOG_WARN("context is already released");
196 return engine.CreateUndefined();
197 }
198 std::string path = context->GetFilesDir();
199 return engine.CreateString(path.c_str(), path.length());
200 }
201
GetDistributedFilesDir(NativeEngine * engine,NativeCallbackInfo * info)202 NativeValue *JsBaseContext::GetDistributedFilesDir(NativeEngine *engine, NativeCallbackInfo *info)
203 {
204 HILOG_DEBUG("called");
205 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
206 return me != nullptr ? me->OnGetDistributedFilesDir(*engine, *info) : nullptr;
207 }
208
OnGetDistributedFilesDir(NativeEngine & engine,NativeCallbackInfo & info)209 NativeValue *JsBaseContext::OnGetDistributedFilesDir(NativeEngine &engine, NativeCallbackInfo &info)
210 {
211 auto context = context_.lock();
212 if (!context) {
213 HILOG_WARN("context is already released");
214 return engine.CreateUndefined();
215 }
216 std::string path = context->GetDistributedFilesDir();
217 return engine.CreateString(path.c_str(), path.length());
218 }
219
GetDatabaseDir(NativeEngine * engine,NativeCallbackInfo * info)220 NativeValue *JsBaseContext::GetDatabaseDir(NativeEngine *engine, NativeCallbackInfo *info)
221 {
222 HILOG_DEBUG("called");
223 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
224 return me != nullptr ? me->OnGetDatabaseDir(*engine, *info) : nullptr;
225 }
226
OnGetDatabaseDir(NativeEngine & engine,NativeCallbackInfo & info)227 NativeValue *JsBaseContext::OnGetDatabaseDir(NativeEngine &engine, NativeCallbackInfo &info)
228 {
229 auto context = context_.lock();
230 if (!context) {
231 HILOG_WARN("context is already released");
232 return engine.CreateUndefined();
233 }
234 std::string path = context->GetDatabaseDir();
235 return engine.CreateString(path.c_str(), path.length());
236 }
237
GetPreferencesDir(NativeEngine * engine,NativeCallbackInfo * info)238 NativeValue *JsBaseContext::GetPreferencesDir(NativeEngine *engine, NativeCallbackInfo *info)
239 {
240 HILOG_DEBUG("called");
241 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
242 return me != nullptr ? me->OnGetPreferencesDir(*engine, *info) : nullptr;
243 }
244
OnGetPreferencesDir(NativeEngine & engine,NativeCallbackInfo & info)245 NativeValue *JsBaseContext::OnGetPreferencesDir(NativeEngine &engine, NativeCallbackInfo &info)
246 {
247 auto context = context_.lock();
248 if (!context) {
249 HILOG_WARN("context is already released");
250 return engine.CreateUndefined();
251 }
252 std::string path = context->GetPreferencesDir();
253 return engine.CreateString(path.c_str(), path.length());
254 }
255
GetBundleCodeDir(NativeEngine * engine,NativeCallbackInfo * info)256 NativeValue *JsBaseContext::GetBundleCodeDir(NativeEngine *engine, NativeCallbackInfo *info)
257 {
258 HILOG_DEBUG("called");
259 JsBaseContext *me = CheckParamsAndGetThis<JsBaseContext>(engine, info, BASE_CONTEXT_NAME);
260 return me != nullptr ? me->OnGetBundleCodeDir(*engine, *info) : nullptr;
261 }
262
OnGetBundleCodeDir(NativeEngine & engine,NativeCallbackInfo & info)263 NativeValue *JsBaseContext::OnGetBundleCodeDir(NativeEngine &engine, NativeCallbackInfo &info)
264 {
265 auto context = context_.lock();
266 if (!context) {
267 HILOG_WARN("context is already released");
268 return engine.CreateUndefined();
269 }
270 std::string path = context->GetBundleCodeDir();
271 return engine.CreateString(path.c_str(), path.length());
272 }
273
OnGetApplicationContext(NativeEngine & engine,NativeCallbackInfo & info)274 NativeValue *JsBaseContext::OnGetApplicationContext(NativeEngine &engine, NativeCallbackInfo &info)
275 {
276 HILOG_DEBUG("called");
277 NativeValue *value = JsApplicationContextUtils::CreateJsApplicationContext(engine, context_.lock());
278 auto systemModule = JsRuntime::LoadSystemModuleByEngine(&engine, "application.ApplicationContext", &value, 1);
279 if (systemModule == nullptr) {
280 return engine.CreateUndefined();
281 }
282 auto contextObj = systemModule->Get();
283 return contextObj;
284 }
285 } // namespace
286
CreateJsBaseContext(NativeEngine & engine,std::shared_ptr<Context> context,bool keepContext)287 NativeValue *CreateJsBaseContext(NativeEngine &engine, std::shared_ptr<Context> context, bool keepContext)
288 {
289 NativeValue *objValue = engine.CreateObject();
290 NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
291 if (object == nullptr) {
292 HILOG_WARN("invalid object.");
293 return objValue;
294 }
295
296 auto appInfo = context->GetApplicationInfo();
297 if (appInfo != nullptr) {
298 object->SetProperty("applicationInfo", CreateJsApplicationInfo(engine, *appInfo));
299 }
300 auto hapModuleInfo = context->GetHapModuleInfo();
301 if (hapModuleInfo != nullptr) {
302 object->SetProperty("currentHapModuleInfo", CreateJsHapModuleInfo(engine, *hapModuleInfo));
303 }
304
305 auto jsContext = std::make_unique<JsBaseContext>(context);
306 SetNamedNativePointer(engine, *object, BASE_CONTEXT_NAME, jsContext.release(), JsBaseContext::Finalizer);
307
308 BindNativeProperty(*object, "cacheDir", JsBaseContext::GetCacheDir);
309 BindNativeProperty(*object, "tempDir", JsBaseContext::GetTempDir);
310 BindNativeProperty(*object, "filesDir", JsBaseContext::GetFilesDir);
311 BindNativeProperty(*object, "distributedFilesDir", JsBaseContext::GetDistributedFilesDir);
312 BindNativeProperty(*object, "databaseDir", JsBaseContext::GetDatabaseDir);
313 BindNativeProperty(*object, "preferencesDir", JsBaseContext::GetPreferencesDir);
314 BindNativeProperty(*object, "bundleCodeDir", JsBaseContext::GetBundleCodeDir);
315 BindNativeProperty(*object, "area", JsBaseContext::GetArea);
316 const char *moduleName = "JsBaseContext";
317 BindNativeFunction(engine, *object, "createBundleContext", moduleName, JsBaseContext::CreateBundleContext);
318 BindNativeFunction(engine, *object, "getApplicationContext", moduleName, JsBaseContext::GetApplicationContext);
319 BindNativeFunction(engine, *object, "switchArea", moduleName, JsBaseContext::SwitchArea);
320 BindNativeFunction(engine, *object, "getArea", moduleName, JsBaseContext::GetArea);
321 BindNativeFunction(engine, *object, "createModuleContext", moduleName, JsBaseContext::CreateModuleContext);
322
323 return objValue;
324 }
325 } // namespace AbilityRuntime
326 } // namespace OHOS
327