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 "UriPermissionManager"
16 
17 #include "uri_permission_manager.h"
18 
19 #include "log_print.h"
20 #include "preprocess_utils.h"
21 #include "uri_permission_manager_client.h"
22 #include "want.h"
23 
24 namespace OHOS {
25 namespace UDMF {
26 constexpr const std::uint32_t GRANT_URI_PERMISSION_MAX_SIZE = 500;
GetInstance()27 UriPermissionManager &UriPermissionManager::GetInstance()
28 {
29     static UriPermissionManager instance;
30     return instance;
31 }
32 
GrantUriPermission( const std::vector<Uri> &allUri, uint32_t tokenId, const std::string &queryKey, uint32_t &completeCount)33 Status UriPermissionManager::GrantUriPermission(
34     const std::vector<Uri> &allUri, uint32_t tokenId, const std::string &queryKey, uint32_t &completeCount)
35 {
36     std::string bundleName;
37     if (!PreProcessUtils::GetHapBundleNameByToken(tokenId, bundleName)) {
38         ZLOGE("Get BundleName fail, key:%{public}s, tokenId:%{public}u.", queryKey.c_str(), tokenId);
39         return E_ERROR;
40     }
41     int32_t instIndex = -1;
42     if (!PreProcessUtils::GetInstIndex(tokenId, instIndex)) {
43         ZLOGE("Get InstIndex fail, key:%{public}s, tokenId:%{public}u.", queryKey.c_str(), tokenId);
44         return E_ERROR;
45     }
46 
47     //  GrantUriPermission is time-consuming, need recording the begin,end time in log.
48     ZLOGI("GrantUriPermission begin, url size:%{public}zu, queryKey:%{public}s, instIndex:%{public}d.",
49         allUri.size(), queryKey.c_str(), instIndex);
50     for (size_t index = 0; index < allUri.size(); index += GRANT_URI_PERMISSION_MAX_SIZE) {
51         std::vector<Uri> uriLst(
52             allUri.begin() + index, allUri.begin() + std::min(index + GRANT_URI_PERMISSION_MAX_SIZE, allUri.size()));
53         auto status = AAFwk::UriPermissionManagerClient::GetInstance().GrantUriPermissionPrivileged(
54             uriLst, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, bundleName, instIndex);
55         if (status != ERR_OK) {
56             ZLOGE("GrantUriPermission failed, status:%{public}d, queryKey:%{public}s, instIndex:%{public}d.",
57                 status, queryKey.c_str(), instIndex);
58             return E_NO_PERMISSION;
59         }
60         completeCount = std::min(allUri.size(), index + GRANT_URI_PERMISSION_MAX_SIZE);
61         auto time = std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL);
62         std::for_each(uriLst.begin(), uriLst.end(), [&](const Uri &uri) {
63             auto times = std::make_pair(uri.ToString(), tokenId);
64             uriTimeout_.Insert(times, time);
65         });
66     }
67     ZLOGI("GrantUriPermission end, url size:%{public}zu, queryKey:%{public}s.", allUri.size(), queryKey.c_str());
68 
69     std::unique_lock<std::mutex> lock(taskMutex_);
70     if (taskId_ == ExecutorPool::INVALID_TASK_ID && executorPool_ != nullptr) {
71         taskId_ = executorPool_->Schedule(
72             std::chrono::minutes(INTERVAL), std::bind(&UriPermissionManager::RevokeUriPermission, this));
73     }
74     return E_OK;
75 }
76 
RevokeUriPermission()77 void UriPermissionManager::RevokeUriPermission()
78 {
79     auto current = std::chrono::steady_clock::now();
80     uriTimeout_.EraseIf([&](const auto &key, const Time &time) {
81         if (time > current) {
82             return false;
83         }
84         Uri uri(key.first);
85         uint32_t tokenId = key.second;
86         std::string bundleName;
87         if (!PreProcessUtils::GetHapBundleNameByToken(tokenId, bundleName)) {
88             ZLOGE("Get BundleName fail, tokenId:%{public}u.", tokenId);
89             return true;
90         }
91         int32_t instIndex = -1;
92         if (!PreProcessUtils::GetInstIndex(tokenId, instIndex)) {
93             ZLOGE("Get InstIndex fail, tokenId:%{public}u.", tokenId);
94             return true;
95         }
96         int status = AAFwk::UriPermissionManagerClient::GetInstance().RevokeUriPermissionManually(
97             uri, bundleName, instIndex);
98         if (status != E_OK) {
99             ZLOGE("RevokeUriPermission error, permissionCode:%{public}d, bundleName:%{public}s, instIndex:%{public}d",
100                 status, bundleName.c_str(), instIndex);
101         }
102         return true;
103     });
104 
105     std::unique_lock<std::mutex> lock(taskMutex_);
106     if (!uriTimeout_.Empty() && executorPool_ != nullptr) {
107         ZLOGD("RevokeUriPermission, uriTimeout size:%{public}zu", uriTimeout_.Size());
108         taskId_ = executorPool_->Schedule(
109             std::chrono::minutes(INTERVAL), std::bind(&UriPermissionManager::RevokeUriPermission, this));
110     } else {
111         taskId_ = ExecutorPool::INVALID_TASK_ID;
112     }
113 }
114 
SetThreadPool(std::shared_ptr<ExecutorPool> executors)115 void UriPermissionManager::SetThreadPool(std::shared_ptr<ExecutorPool> executors)
116 {
117     executorPool_ = executors;
118 }
119 } // namespace UDMF
120 } // namespace OHOS
121