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