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