• 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 "plugin_mgr.h"
17 #include <fstream>
18 #include <sstream>
19 #include "directory_ex.h"
20 #include "hilog/log.h"
21 #include "json.hpp"
22 #include "json_helper.h"
23 #include "log_tags.h"
24 #include "platform_adp.h"
25 #include "plugin.h"
26 #include "plugin_metadata.h"
27 
28 namespace OHOS {
29 namespace MultimediaPlugin {
30 using nlohmann::json;
31 using std::ifstream;
32 using std::istringstream;
33 using std::size_t;
34 using std::string;
35 using std::vector;
36 using std::weak_ptr;
37 using namespace OHOS::HiviewDFX;
38 
39 static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "PluginMgr" };
40 PlatformAdp &PluginMgr::platformAdp_ = DelayedRefSingleton<PlatformAdp>::GetInstance();
41 
Register(const vector<string> & canonicalPaths)42 uint32_t PluginMgr::Register(const vector<string> &canonicalPaths)
43 {
44     if (canonicalPaths.empty()) {
45         const vector<string> &metadata = OHOS::MultimediaPlugin::META_DATA;
46         for (size_t i = 0; i < metadata.size(); i++) {
47             uint32_t errorCode = RegisterPlugin(metadata[i]);
48             if (errorCode != SUCCESS) {
49                 return errorCode;
50             }
51         }
52         return SUCCESS;
53     }
54 
55     bool pathTraversed = false;
56     uint32_t errorCode = SUCCESS;
57     for (const string &path : canonicalPaths) {
58         uint32_t result = TraverseFiles(path);
59         if (result == SUCCESS) {
60             pathTraversed = true;
61         } else {
62             // no target is not a critical error type, giving priority to more serious errors.
63             if ((errorCode == SUCCESS) || (errorCode == ERR_NO_TARGET)) {
64                 errorCode = result;
65             }
66         }
67     }
68 
69     if (!pathTraversed) {
70         return errorCode;
71     }
72 
73     return SUCCESS;
74 }
75 
76 // ------------------------------- private method -------------------------------
PluginMgr()77 PluginMgr::PluginMgr()
78 {}
79 
~PluginMgr()80 PluginMgr::~PluginMgr()
81 {}
82 
TraverseFiles(const string & canonicalPath)83 uint32_t PluginMgr::TraverseFiles(const string &canonicalPath)
84 {
85     bool noTarget = true;
86     vector<string> strFiles;
87     GetDirFiles(canonicalPath, strFiles);
88     if (strFiles.empty()) {
89         HiLog::Error(LABEL, "failed to get dir files.");
90         return ERR_GENERAL;
91     }
92 
93     string libraryPath;
94     for (const auto &file : strFiles) {
95         if (!CheckPluginMetaFile(file, libraryPath)) {
96             continue;
97         }
98         noTarget = false;
99         RegisterPlugin(file, std::move(libraryPath));
100     }
101 
102     if (noTarget) {
103         HiLog::Warn(LABEL, "there is no plugin meta file in path.");
104         return ERR_NO_TARGET;
105     }
106 
107     return SUCCESS;
108 }
109 
CheckPluginMetaFile(const string & candidateFile,string & libraryPath)110 bool PluginMgr::CheckPluginMetaFile(const string &candidateFile, string &libraryPath)
111 {
112     const string meatedataFileSuffix = "pluginmeta";
113 
114 #ifdef _WIN32
115     const string libraryFileSuffix = "dll";
116 #elif defined _APPLE
117     const string libraryFileSuffix = "dylib";
118 #else
119     const string libraryFileSuffix = "so";
120 #endif
121 
122     string fileExt = ExtractFileExt(candidateFile);
123     if (fileExt != meatedataFileSuffix) {
124         // not a plugin metadata file, quietly skip this item.
125         return false;
126     }
127 
128     ifstream metadata(candidateFile);
129     if (!metadata) {
130         HiLog::Error(LABEL, "failed to open metadata file.");
131         return false;
132     }
133 
134     json root;
135     metadata >> root;
136     if (JsonHelper::GetStringValue(root, "libraryPath", libraryPath) != SUCCESS) {
137         HiLog::Error(LABEL, "read libraryPath failed.");
138         return false;
139     }
140 
141 #if defined(_WIN32) || defined(_APPLE)
142     libraryPath = TransformFileName(libraryPath);
143 #endif
144 
145     fileExt = ExtractFileExt(libraryPath);
146     if (fileExt != libraryFileSuffix) {
147         HiLog::Error(LABEL, "invalid library suffix.");
148         return false;
149     }
150 
151 #if !defined(_WIN32) && !defined(_APPLE)
152     const string dirSeparator = "/";
153     if (libraryPath.substr(0, 1) != dirSeparator) {
154         // relative path to absolute path.
155         // just keep original library name
156         return true;
157     }
158 #endif
159 
160     string realPath;
161     if (!PathToRealPath(libraryPath, realPath)) {
162         HiLog::Error(LABEL, "library path to real path error.");
163         return false;
164     }
165 
166     libraryPath = std::move(realPath);
167     return true;
168 }
169 
RegisterPlugin(const string & metadataPath,string && libraryPath)170 uint32_t PluginMgr::RegisterPlugin(const string &metadataPath, string &&libraryPath)
171 {
172     auto iter = plugins_.find(&libraryPath);
173     if (iter != plugins_.end()) {
174         // already registered before, just skip it.
175         HiLog::Debug(LABEL, "the libraryPath has already been registered before.");
176         return ERR_GENERAL;
177     }
178 
179     ifstream metadata(metadataPath);
180     if (!metadata) {
181         HiLog::Error(LABEL, "failed to open metadata file.");
182         return ERR_GENERAL;
183     }
184 
185     auto plugin = std::make_shared<Plugin>();
186     if (plugin == nullptr) {
187         HiLog::Error(LABEL, "failed to create Plugin.");
188         return ERR_INTERNAL;
189     }
190 
191     weak_ptr<Plugin> weakPtr = plugin;
192     auto regRet = plugin->Register(metadata, std::move(libraryPath), weakPtr);
193     if (regRet != SUCCESS) {
194         HiLog::Error(LABEL, "failed to register plugin,ERRNO: %{public}u.", regRet);
195         return regRet;
196     }
197 
198     const std::string &key = plugin->GetLibraryPath();
199     if (key.empty()) {
200         HiLog::Error(LABEL, "get empty libraryPath.");
201         return ERR_INTERNAL;
202     }
203 
204     auto insertRet = plugins_.insert(PluginMap::value_type(&key, std::move(plugin)));
205     if (!insertRet.second) {
206         HiLog::Error(LABEL, "failed to insert Plugin");
207         return ERR_INTERNAL;
208     }
209 
210     return SUCCESS;
211 }
212 
RegisterPlugin(const string & metadataJson)213 uint32_t PluginMgr::RegisterPlugin(const string &metadataJson)
214 {
215     string libraryPath;
216     json root = nlohmann::json::parse(metadataJson);
217     if (JsonHelper::GetStringValue(root, "libraryPath", libraryPath) != SUCCESS) {
218         HiLog::Error(LABEL, "read libraryPath failed.");
219         return false;
220     }
221 
222     auto iter = plugins_.find(&libraryPath);
223     if (iter != plugins_.end()) {
224         // already registered before, just skip it.
225         HiLog::Debug(LABEL, "the libraryPath has already been registered before.");
226         return ERR_GENERAL;
227     }
228 
229     istringstream metadata(metadataJson);
230     if (!metadata) {
231         HiLog::Error(LABEL, "failed to read metadata.");
232         return ERR_GENERAL;
233     }
234 
235     auto crossPlugin = std::make_shared<Plugin>();
236     weak_ptr<Plugin> weakPtr = crossPlugin;
237     auto regRet = crossPlugin->Register(metadata, std::move(libraryPath), weakPtr);
238     if (regRet != SUCCESS) {
239         HiLog::Error(LABEL, "failed to register plugin,ERRNO: %{public}u.", regRet);
240         return regRet;
241     }
242 
243     const std::string &key = crossPlugin->GetLibraryPath();
244     if (key.empty()) {
245         HiLog::Error(LABEL, "get empty libraryPath.");
246         return ERR_INTERNAL;
247     }
248 
249     auto insertRet = plugins_.insert(PluginMap::value_type(&key, std::move(crossPlugin)));
250     if (!insertRet.second) {
251         HiLog::Error(LABEL, "failed to insert Plugin");
252         return ERR_INTERNAL;
253     }
254 
255     return SUCCESS;
256 }
257 } // namespace MultimediaPlugin
258 } // namespace OHOS
259