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 "extension_plugin_info.h"
17
18 #include <dirent.h>
19 #include <dlfcn.h>
20 #include <unistd.h>
21
22 #include "extension_module_loader.h"
23 #include "file_path_utils.h"
24 #include "hilog_wrapper.h"
25
26 namespace OHOS {
27 namespace AbilityRuntime {
28 #ifdef APP_USE_ARM64
29 const std::string EXTENSION_LIB = "system/lib64/extensionability";
30 #else
31 const std::string EXTENSION_LIB = "system/lib/extensionability";
32 #endif
33 const std::string PATH_SEPARATOR = "/";
34 const std::string LIB_TYPE = ".so";
35 constexpr char EXTENSION_PARAMS_TYPE[] = "type";
36 constexpr char EXTENSION_PARAMS_NAME[] = "name";
37
ExtensionPluginInfo()38 ExtensionPluginInfo::ExtensionPluginInfo()
39 {
40 }
41
GetInstance()42 ExtensionPluginInfo& ExtensionPluginInfo::GetInstance()
43 {
44 static ExtensionPluginInfo instance;
45 return instance;
46 }
47
Preload()48 void ExtensionPluginInfo::Preload()
49 {
50 // scan all extensions in path
51 std::vector<std::string> extensionFiles;
52 ScanExtensions(extensionFiles);
53 ParseExtensions(extensionFiles);
54 }
55
GetExtensionPlugins()56 std::vector<ExtensionPluginItem> ExtensionPluginInfo::GetExtensionPlugins()
57 {
58 return extensionPlugins_;
59 }
60
ParseExtensions(const std::vector<std::string> & extensionFiles)61 void ExtensionPluginInfo::ParseExtensions(const std::vector<std::string>& extensionFiles)
62 {
63 if (extensionFiles.empty()) {
64 HILOG_ERROR("no extension files.");
65 return;
66 }
67
68 for (auto& file : extensionFiles) {
69 HILOG_DEBUG("Begin load extension file:%{public}s", file.c_str());
70 std::map<std::string, std::string> params =
71 AbilityRuntime::ExtensionModuleLoader::GetLoader(file.c_str()).GetParams();
72 if (params.empty()) {
73 HILOG_ERROR("no extension params.");
74 continue;
75 }
76 // get extension name and type
77 std::map<std::string, std::string>::iterator it = params.find(EXTENSION_PARAMS_TYPE);
78 if (it == params.end()) {
79 HILOG_ERROR("no extension type.");
80 continue;
81 }
82 int32_t type = -1;
83 try {
84 type = static_cast<int32_t>(std::stoi(it->second));
85 } catch (...) {
86 HILOG_WARN("stoi(%{public}s) failed", it->second.c_str());
87 continue;
88 }
89
90 it = params.find(EXTENSION_PARAMS_NAME);
91 if (it == params.end()) {
92 HILOG_ERROR("no extension name.");
93 continue;
94 }
95 std::string extensionName = it->second;
96
97 ExtensionPluginItem item;
98 item.extensionType = type;
99 item.extensionName = extensionName;
100 item.extensionLibFile = file;
101 extensionPlugins_.emplace_back(item);
102 HILOG_DEBUG("Success load extension type: %{public}d, name:%{public}s", type, extensionName.c_str());
103 }
104 }
105
ScanExtensions(std::vector<std::string> & files)106 bool ExtensionPluginInfo::ScanExtensions(std::vector<std::string>& files)
107 {
108 std::string dirPath = EXTENSION_LIB;
109 DIR *dirp = opendir(dirPath.c_str());
110 if (dirp == nullptr) {
111 HILOG_ERROR("ExtensionPluginInfo::ScanDir open dir:%{public}s fail", dirPath.c_str());
112 return false;
113 }
114
115 struct dirent *dirf = nullptr;
116 for (;;) {
117 dirf = readdir(dirp);
118 if (dirf == nullptr) {
119 break;
120 }
121
122 std::string currentName(dirf->d_name);
123 if (currentName.compare(".") == 0 || currentName.compare("..") == 0) {
124 continue;
125 }
126
127 if (CheckFileType(currentName, LIB_TYPE)) {
128 files.emplace_back(dirPath + PATH_SEPARATOR + currentName);
129 }
130 }
131
132 if (closedir(dirp) == -1) {
133 HILOG_WARN("close dir fail");
134 }
135 return true;
136 }
137
CheckFileType(const std::string & fileName,const std::string & extensionName)138 bool ExtensionPluginInfo::CheckFileType(const std::string& fileName, const std::string& extensionName)
139 {
140 HILOG_DEBUG("ExtensionPluginInfo::CheckFileType path is %{public}s, support suffix is %{public}s",
141 fileName.c_str(),
142 extensionName.c_str());
143
144 if (fileName.empty()) {
145 HILOG_ERROR("the file name is empty.");
146 return false;
147 }
148
149 auto position = fileName.rfind('.');
150 if (position == std::string::npos) {
151 HILOG_WARN("filename no extension name.");
152 return false;
153 }
154
155 std::string suffixStr = fileName.substr(position);
156 return LowerStr(suffixStr) == extensionName;
157 }
158 }
159 }
160