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 #define LOG_TAG "LoadConfigFromDataShareBundleInfoStrategy"
16 
17 #include "load_config_from_data_share_bundle_info_strategy.h"
18 
19 #include "bundle_mgr_proxy.h"
20 #include "data_share_profile_config.h"
21 #include "datashare_errno.h"
22 #include "log_print.h"
23 #include "uri_utils.h"
24 #include "utils/anonymous.h"
25 
26 namespace OHOS::DataShare {
27 struct ConfigData {
28     constexpr static int8_t TABLE_MATCH_PRIORITY = 3;
29     constexpr static int8_t STORE_MATCH_PRIORITY = 2;
30     constexpr static int8_t COMMON_MATCH_PRIORITY = 1;
31     constexpr static int8_t UNDEFINED_PRIORITY = -1;
ConfigDataOHOS::DataShare::ConfigData32     ConfigData() : crossMode_(AccessSystemMode::UNDEFINED, UNDEFINED_PRIORITY) {}
SetCrossUserModeOHOS::DataShare::ConfigData33     void SetCrossUserMode(uint8_t priority, uint8_t crossMode)
34     {
35         if (crossMode_.second < priority && crossMode > AccessSystemMode::UNDEFINED &&
36             crossMode < AccessSystemMode::MAX) {
37             crossMode_.first = static_cast<AccessSystemMode>(crossMode);
38             crossMode_.second = priority;
39         }
40     }
FillIntoContextOHOS::DataShare::ConfigData41     void FillIntoContext(std::shared_ptr<Context> context)
42     {
43         if (crossMode_.second != ConfigData::UNDEFINED_PRIORITY) {
44             context->accessSystemMode = crossMode_.first;
45         }
46     }
47 
48 private:
49     std::pair<AccessSystemMode, int8_t> crossMode_;
50 };
51 
LoadConfigFromProfile(const ProfileInfo & profileInfo,std::shared_ptr<Context> context)52 bool LoadConfigFromDataShareBundleInfoStrategy::LoadConfigFromProfile(
53     const ProfileInfo &profileInfo, std::shared_ptr<Context> context)
54 {
55     std::string storeUri = URIUtils::DATA_SHARE_SCHEMA + context->calledBundleName + "/" + context->calledModuleName +
56         "/" + context->calledStoreName;
57     std::string tableUri = storeUri + "/" + context->calledTableName;
58     ConfigData result;
59     for (auto const &item : profileInfo.tableConfig) {
60         if (item.uri == tableUri) {
61             result.SetCrossUserMode(ConfigData::TABLE_MATCH_PRIORITY, item.crossUserMode);
62             continue;
63         }
64         if (item.uri == storeUri) {
65             result.SetCrossUserMode(ConfigData::STORE_MATCH_PRIORITY, item.crossUserMode);
66             continue;
67         }
68         if (item.uri == "*") {
69             result.SetCrossUserMode(ConfigData::COMMON_MATCH_PRIORITY, item.crossUserMode);
70             continue;
71         }
72     }
73     result.FillIntoContext(context);
74     return true;
75 }
76 
operator ()(std::shared_ptr<Context> context)77 bool LoadConfigFromDataShareBundleInfoStrategy::operator()(std::shared_ptr<Context> context)
78 {
79     if (!LoadConfigFromUri(context)) {
80         ZLOGE("LoadConfigFromUri failed! bundleName: %{public}s", context->calledBundleName.c_str());
81         return false;
82     }
83     if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(
84         context->calledBundleName, context->currentUserId, context->bundleInfo) != E_OK) {
85         ZLOGE("GetBundleInfoFromBMS failed! bundleName: %{public}s", context->calledBundleName.c_str());
86         return false;
87     }
88     for (auto const &item : context->bundleInfo.extensionInfos) {
89         if (item.type == AppExecFwk::ExtensionAbilityType::DATASHARE) {
90             context->permission = context->isRead ? item.readPermission : item.writePermission;
91 
92             auto profileInfo = item.profileInfo;
93             if (profileInfo.resultCode == NOT_FOUND) {
94                 return true; // optional meta data config
95             }
96             if (profileInfo.resultCode == ERROR) {
97                 ZLOGE("parse failed! %{public}s", context->calledBundleName.c_str());
98                 return false;
99             }
100             LoadConfigFromProfile(profileInfo.profile, context);
101             return true;
102         }
103     }
104     return false;
105 }
LoadConfigFromUri(std::shared_ptr<Context> context)106 bool LoadConfigFromDataShareBundleInfoStrategy::LoadConfigFromUri(std::shared_ptr<Context> context)
107 {
108     UriInfo uriInfo;
109     if (!URIUtils::GetInfoFromURI(context->uri, uriInfo)) {
110         return false;
111     }
112     context->calledBundleName = std::move(uriInfo.bundleName);
113     context->calledModuleName = std::move(uriInfo.moduleName);
114     context->calledStoreName = std::move(uriInfo.storeName);
115     context->calledTableName = std::move(uriInfo.tableName);
116     return true;
117 }
118 } // namespace OHOS::DataShare