• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_config_mgr.h"
17 
18 #include <cctype>
19 #include <fstream>
20 #include <nlohmann/json.hpp>
21 
22 #include "app_module_checker.h"
23 #include "hilog_tag_wrapper.h"
24 #include "hitrace_meter.h"
25 
26 namespace OHOS::AbilityRuntime {
27 namespace {
28     constexpr char EXTENSION_BLOCKLIST_FILE_PATH[] = "/system/etc/extension_blocklist_config.json";
29 }
30 
Init()31 void ExtensionConfigMgr::Init()
32 {
33     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
34     TAG_LOGD(AAFwkTag::EXT, "Init begin");
35     // clear cached data
36     blocklistConfig_.clear();
37     extensionBlocklist_.clear();
38     extensionEtsBlocklist_.clear();
39 
40     // read blocklist from extension_blocklist_config.json
41     std::ifstream inFile;
42     inFile.open(EXTENSION_BLOCKLIST_FILE_PATH, std::ios::in);
43     if (!inFile.is_open()) {
44         TAG_LOGE(AAFwkTag::EXT, "read extension config error");
45         return;
46     }
47     nlohmann::json extensionConfig;
48     inFile >> extensionConfig;
49     if (extensionConfig.is_discarded()) {
50         TAG_LOGE(AAFwkTag::EXT, "extension config json discarded error");
51         inFile.close();
52         return;
53     }
54     if (!extensionConfig.contains(ExtensionConfigItem::ITEM_NAME_BLOCKLIST)) {
55         TAG_LOGE(AAFwkTag::EXT, "extension config file have no blocklist node");
56         inFile.close();
57         return;
58     }
59     auto blackList = extensionConfig.at(ExtensionConfigItem::ITEM_NAME_BLOCKLIST);
60     std::unordered_set<std::string> currentBlockList;
61     for (const auto& item : blackList.items()) {
62         if (!blackList[item.key()].is_array()) {
63             continue;
64         }
65         for (const auto& value : blackList[item.key()]) {
66             currentBlockList.emplace(value.get<std::string>());
67         }
68         blocklistConfig_.emplace(item.key(), std::move(currentBlockList));
69         currentBlockList.clear();
70     }
71     inFile.close();
72     TAG_LOGD(AAFwkTag::EXT, "Init end");
73 }
74 
AddBlockListItem(const std::string & name,int32_t type)75 void ExtensionConfigMgr::AddBlockListItem(const std::string& name, int32_t type)
76 {
77     TAG_LOGD(AAFwkTag::EXT, "name: %{public}s, type: %{public}d", name.c_str(), type);
78     auto iter = blocklistConfig_.find(name);
79     if (iter == blocklistConfig_.end()) {
80         TAG_LOGD(AAFwkTag::EXT, "Extension name: %{public}s not exist", name.c_str());
81         return;
82     }
83     extensionBlocklist_.emplace(type, iter->second);
84 }
85 
UpdateRuntimeModuleChecker(const std::unique_ptr<AbilityRuntime::Runtime> & runtime)86 void ExtensionConfigMgr::UpdateRuntimeModuleChecker(const std::unique_ptr<AbilityRuntime::Runtime> &runtime)
87 {
88     if (!runtime) {
89         TAG_LOGE(AAFwkTag::EXT, "null runtime");
90         return;
91     }
92     TAG_LOGD(AAFwkTag::EXT, "extensionType_: %{public}d", extensionType_);
93     if (runtime->GetLanguage() == AbilityRuntime::Runtime::Language::ETS) {
94         TAG_LOGD(AAFwkTag::EXT, "ets runtime");
95         GenerateExtensionEtsBlocklists();
96         SetExtensionEtsCheckCallback(runtime);
97     }
98 
99     auto moduleChecker = std::make_shared<AppModuleChecker>(extensionType_, extensionBlocklist_);
100     runtime->SetModuleLoadChecker(moduleChecker);
101     extensionBlocklist_.clear();
102 }
103 
GenerateExtensionEtsBlocklists()104 void ExtensionConfigMgr::GenerateExtensionEtsBlocklists()
105 {
106     if (!extensionEtsBlocklist_.empty()) {
107         TAG_LOGD(AAFwkTag::EXT, "extension ets block list not empty.");
108         return;
109     }
110     auto iter = extensionBlocklist_.find(extensionType_);
111     if (iter == extensionBlocklist_.end()) {
112         TAG_LOGD(AAFwkTag::EXT, "null extension block, extensionType: %{public}d.", extensionType_);
113         return;
114     }
115     for (const auto& module: iter->second) {
116         extensionEtsBlocklist_.emplace(module);
117     }
118 }
119 
GetStringAfterRemovePreFix(const std::string & name)120 std::string ExtensionConfigMgr::GetStringAfterRemovePreFix(const std::string &name)
121 {
122     if (!name.empty() && name[0] == '@') {
123         size_t dotPos = name.find('.');
124         if (dotPos != std::string::npos) {
125             return name.substr(dotPos + 1);
126         }
127     }
128     return name;
129 }
130 
CheckEtsModuleLoadable(const std::string & className,const std::string & fileName)131 bool ExtensionConfigMgr::CheckEtsModuleLoadable(const std::string &className, const std::string &fileName)
132 {
133     TAG_LOGD(AAFwkTag::EXT, "extensionType: %{public}d, className is %{public}s, fileName is %{public}s",
134         extensionType_, className.c_str(), fileName.c_str());
135     if (fileName.size() >= className.size() ||
136         className.compare(0, fileName.size(), fileName) != 0 ||
137         ((className.compare(0, fileName.size(), fileName) == 0) && className[fileName.size()] != '.')) {
138         TAG_LOGE(AAFwkTag::EXT, "The fileName:%{public}s and className:%{public}s do not match.",
139             fileName.c_str(), className.c_str());
140         return false;
141     }
142 
143     std::string fileNameRemovePrefix = GetStringAfterRemovePreFix(fileName);
144     for (const auto &blockModuleName: extensionEtsBlocklist_) {
145         if (blockModuleName == fileNameRemovePrefix) {
146             TAG_LOGE(AAFwkTag::EXT, "%{public}s is in blocklist.", fileName.c_str());
147             return false;
148         }
149     }
150     TAG_LOGD(AAFwkTag::EXT, "not in blocklist.");
151     return true;
152 }
153 
SetExtensionEtsCheckCallback(const std::unique_ptr<AbilityRuntime::Runtime> & runtime)154 void ExtensionConfigMgr::SetExtensionEtsCheckCallback(const std::unique_ptr<AbilityRuntime::Runtime> &runtime)
155 {
156     auto callback = [extensionConfigMgrWeak = weak_from_this()](const std::string &className,
157         const std::string &fileName) -> bool {
158         auto extensionConfigMgr = extensionConfigMgrWeak.lock();
159         if (extensionConfigMgr == nullptr) {
160             TAG_LOGE(AAFwkTag::EXT, "null extensionConfigMgr");
161             return false;
162         }
163         return extensionConfigMgr->CheckEtsModuleLoadable(className, fileName);
164     };
165     runtime->SetExtensionApiCheckCallback(callback);
166 }
167 }