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)33 Status UriPermissionManager::GrantUriPermission(
34     const std::vector<Uri> &allUri, uint32_t tokenId, const std::string &queryKey)
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         auto time = std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL);
61         std::for_each(uriLst.begin(), uriLst.end(), [&](const Uri &uri) {
62             auto times = std::make_pair(uri.ToString(), tokenId);
63             uriTimeout_.Insert(times, time);
64         });
65     }
66     ZLOGI("GrantUriPermission end, url size:%{public}zu, queryKey:%{public}s.", allUri.size(), queryKey.c_str());
67 
68     std::unique_lock<std::mutex> lock(taskMutex_);
69     if (taskId_ == ExecutorPool::INVALID_TASK_ID && executorPool_ != nullptr) {
70         taskId_ = executorPool_->Schedule(
71             std::chrono::minutes(INTERVAL), std::bind(&UriPermissionManager::RevokeUriPermission, this));
72     }
73     return E_OK;
74 }
75 
RevokeUriPermission()76 void UriPermissionManager::RevokeUriPermission()
77 {
78     auto current = std::chrono::steady_clock::now();
79     uriTimeout_.EraseIf([&](const auto &key, const Time &time) {
80         if (time > current) {
81             return false;
82         }
83         Uri uri(key.first);
84         uint32_t tokenId = key.second;
85         std::string bundleName;
86         if (!PreProcessUtils::GetHapBundleNameByToken(tokenId, bundleName)) {
87             ZLOGE("Get BundleName fail, tokenId:%{public}u.", tokenId);
88             return true;
89         }
90         int32_t instIndex = -1;
91         if (!PreProcessUtils::GetInstIndex(tokenId, instIndex)) {
92             ZLOGE("Get InstIndex fail, tokenId:%{public}u.", tokenId);
93             return true;
94         }
95         int status = AAFwk::UriPermissionManagerClient::GetInstance().RevokeUriPermissionManually(
96             uri, bundleName, instIndex);
97         if (status != E_OK) {
98             ZLOGE("RevokeUriPermission error, permissionCode:%{public}d, bundleName:%{public}s, instIndex:%{public}d",
99                 status, bundleName.c_str(), instIndex);
100         }
101         return true;
102     });
103 
104     std::unique_lock<std::mutex> lock(taskMutex_);
105     if (!uriTimeout_.Empty() && executorPool_ != nullptr) {
106         ZLOGD("RevokeUriPermission, uriTimeout size:%{public}zu", uriTimeout_.Size());
107         taskId_ = executorPool_->Schedule(
108             std::chrono::minutes(INTERVAL), std::bind(&UriPermissionManager::RevokeUriPermission, this));
109     } else {
110         taskId_ = ExecutorPool::INVALID_TASK_ID;
111     }
112 }
113 
SetThreadPool(std::shared_ptr<ExecutorPool> executors)114 void UriPermissionManager::SetThreadPool(std::shared_ptr<ExecutorPool> executors)
115 {
116     executorPool_ = executors;
117 }
118 } // namespace UDMF
119 } // namespace OHOS
120