• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "appspawn_adapter.h"
17 
18 #include <set>
19 #include "appspawn_service.h"
20 #include "config_policy_utils.h"
21 #include "hitrace_meter.h"
22 #include "js_runtime.h"
23 #include "parameters.h"
24 #include "runtime.h"
25 #include "json_utils.h"
26 #include "resource_manager.h"
27 #include "foundation/ability/ability_runtime/interfaces/kits/native/appkit/app/main_thread.h"
28 #include "syspara/parameter.h"
29 
30 using namespace OHOS::AppSpawn;
31 using namespace OHOS::Global;
32 
33 #ifdef ASAN_DETECTOR
34 static const bool DEFAULT_PRELOAD_VALUE = false;
35 #else
36 static const bool DEFAULT_PRELOAD_VALUE = true;
37 #endif
38 static const std::string PRELOAD_JSON_CONFIG("/appspawn_preload.json");
39 
GetPreloadModules(const std::string & configName,std::set<std::string> & modules)40 static void GetPreloadModules(const std::string &configName, std::set<std::string> &modules)
41 {
42     // Preload napi module
43     nlohmann::json preloadJson;
44     bool rc = JsonUtils::GetJsonObjFromJson(preloadJson, configName);
45     APPSPAWN_CHECK_ONLY_EXPER(rc, return);
46     // no config
47     if (preloadJson.find("napi") == preloadJson.end()) {
48         return;
49     }
50 
51     nlohmann::json modulesJson = preloadJson["napi"];
52     uint32_t moduleCount = modulesJson.size();
53     for (uint32_t i = 0; i < moduleCount; ++i) {
54         nlohmann::json moduleName = modulesJson[i];
55         APPSPAWN_LOGV("moduleName %{public}s", moduleName.get<std::string>().c_str());
56         if (!modules.count(moduleName.get<std::string>())) {
57             modules.insert(moduleName.get<std::string>());
58         }
59     }
60 }
61 
PreloadModule(void)62 static void PreloadModule(void)
63 {
64 #ifndef APPSPAWN_TEST
65     OHOS::AbilityRuntime::Runtime::Options options;
66     options.lang = OHOS::AbilityRuntime::Runtime::Language::JS;
67     options.loadAce = true;
68     options.preload = true;
69 
70     auto runtime = OHOS::AbilityRuntime::Runtime::Create(options);
71     if (!runtime) {
72         APPSPAWN_LOGE("LoadExtendLib: Failed to create runtime");
73         return;
74     }
75 #endif
76     std::set<std::string> modules = {};
77     CfgFiles *files = GetCfgFiles("etc/appspawn");
78     if (files == nullptr) {
79         APPSPAWN_LOGE("LoadExtendLib: Get cfg file fail");
80         return;
81     }
82     for (int i = 0; i < MAX_CFG_POLICY_DIRS_CNT; ++i) {
83         if (files->paths[i] == nullptr) {
84             continue;
85         }
86         std::string path = files->paths[i];
87         path += PRELOAD_JSON_CONFIG;
88         APPSPAWN_LOGI("PreloadModules path %{public}s", path.c_str());
89         GetPreloadModules(path, modules);
90     }
91     FreeCfgFiles(files);
92     for (std::string moduleName : modules) {
93         APPSPAWN_LOGI("moduleName %{public}s", moduleName.c_str());
94 #ifndef APPSPAWN_TEST
95         runtime->PreloadSystemModule(moduleName);
96 #endif
97     }
98 #ifndef APPSPAWN_TEST
99     // Save preloaded runtime
100     OHOS::AbilityRuntime::Runtime::SavePreloaded(std::move(runtime));
101 #endif
102 }
103 
LoadExtendLib(AppSpawnContent * content)104 void LoadExtendLib(AppSpawnContent *content)
105 {
106     const char *acelibdir("libace.z.so");
107     APPSPAWN_LOGI("LoadExtendLib: Start calling dlopen acelibdir.");
108     void *aceAbilityLib = dlopen(acelibdir, RTLD_NOW | RTLD_GLOBAL);
109     APPSPAWN_CHECK(aceAbilityLib != nullptr, return, "Fail to dlopen %{public}s, [%{public}s]", acelibdir, dlerror());
110     APPSPAWN_LOGI("LoadExtendLib: Success to dlopen %{public}s", acelibdir);
111 
112 #ifndef APPSPAWN_TEST
113     OHOS::AppExecFwk::MainThread::PreloadExtensionPlugin();
114 #endif
115 
116     bool preload = OHOS::system::GetBoolParameter("const.appspawn.preload", DEFAULT_PRELOAD_VALUE);
117     if (!preload) {
118         APPSPAWN_LOGI("LoadExtendLib: Do not preload JS VM");
119         return;
120     }
121 
122     APPSPAWN_LOGI("LoadExtendLib: Start preload JS VM");
123     SetTraceDisabled(true);
124 #ifndef APPSPAWN_TEST
125     PreloadModule();
126 #endif
127     SetTraceDisabled(false);
128 
129     Resource::ResourceManager *systemResMgr = Resource::GetSystemResourceManagerNoSandBox();
130     APPSPAWN_CHECK(systemResMgr != nullptr, return, "Fail to get system resource manager");
131     APPSPAWN_LOGI("LoadExtendLib: End preload JS VM");
132 }
133 
RunChildProcessor(AppSpawnContent * content,AppSpawnClient * client)134 void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client)
135 {
136     APPSPAWN_CHECK(client != NULL && content != NULL, return, "Invalid client");
137     AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
138     if (appProperty->property.code == SPAWN_NATIVE_PROCESS) {
139         APPSPAWN_LOGI("renderCmd %{public}s", appProperty->property.renderCmd);
140         (void)system(appProperty->property.renderCmd);
141         return;
142     }
143     APPSPAWN_LOGI("LoadExtendLib: RunChildProcessor");
144 #ifndef APPSPAWN_TEST
145     std::string checkExit;
146     if (GetIntParameter("persist.init.debug.checkexit", true)) {
147         checkExit = std::to_string(getpid());
148     }
149     setenv(APPSPAWN_CHECK_EXIT, checkExit.c_str(), true);
150     OHOS::AppExecFwk::MainThread::Start();
151     unsetenv(APPSPAWN_CHECK_EXIT);
152 #endif
153 }
154