1 // Copyright (C) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 pub(crate) use ffi::TaskFilter;
15
16 use super::events::QueryEvent;
17 use super::TaskManager;
18 use crate::config::{Action, Mode};
19 use crate::manage::database::RequestDb;
20 use crate::task::config::TaskConfig;
21 use crate::task::info::{State, TaskInfo};
22
get_task(task_id: u32, token: String) -> Option<TaskConfig>23 pub(crate) fn get_task(task_id: u32, token: String) -> Option<TaskConfig> {
24 if let Some(config) = RequestDb::get_instance().get_task_config(task_id) {
25 if config.token.eq(token.as_str()) {
26 return Some(config);
27 }
28 return None;
29 }
30 None
31 }
32
search(filter: TaskFilter, method: SearchMethod) -> Vec<u32>33 pub(crate) fn search(filter: TaskFilter, method: SearchMethod) -> Vec<u32> {
34 let database = RequestDb::get_instance();
35
36 match method {
37 SearchMethod::User(uid) => database.search_task(filter, uid),
38 SearchMethod::System(bundle_name) => database.system_search_task(filter, bundle_name),
39 }
40 }
41
42 impl TaskManager {
handle_query_event(&self, event: QueryEvent)43 pub(crate) fn handle_query_event(&self, event: QueryEvent) {
44 let (info, tx) = match event {
45 QueryEvent::Show(task_id, uid, tx) => {
46 let info = self.show(uid, task_id);
47 (info, tx)
48 }
49 QueryEvent::Query(task_id, action, tx) => {
50 let info = self.query(task_id, action);
51 (info, tx)
52 }
53 QueryEvent::Touch(task_id, uid, token, tx) => {
54 let info = self.touch(uid, task_id, token);
55 (info, tx)
56 }
57 };
58 let _ = tx.send(info);
59 }
60
show(&self, uid: u64, task_id: u32) -> Option<TaskInfo>61 pub(crate) fn show(&self, uid: u64, task_id: u32) -> Option<TaskInfo> {
62 if let Some(task) = self.scheduler.get_task(uid, task_id) {
63 task.update_progress_in_database()
64 }
65
66 match RequestDb::get_instance().get_task_info(task_id) {
67 Some(info) if info.uid() == uid => Some(info),
68 _ => {
69 info!("TaskManger Show: no task found");
70 None
71 }
72 }
73 }
74
touch(&self, uid: u64, task_id: u32, token: String) -> Option<TaskInfo>75 pub(crate) fn touch(&self, uid: u64, task_id: u32, token: String) -> Option<TaskInfo> {
76 if let Some(task) = self.scheduler.get_task(uid, task_id) {
77 task.update_progress_in_database()
78 }
79
80 let mut info = match RequestDb::get_instance().get_task_info(task_id) {
81 Some(info) => info,
82 None => {
83 info!("TaskManger Touch: no task found");
84 return None;
85 }
86 };
87
88 if info.uid() == uid && info.token() == token {
89 info.bundle = "".to_string();
90 Some(info)
91 } else {
92 info!("TaskManger Touch: no task found");
93 None
94 }
95 }
96
query(&self, task_id: u32, action: Action) -> Option<TaskInfo>97 pub(crate) fn query(&self, task_id: u32, action: Action) -> Option<TaskInfo> {
98 if let Some(task) = self
99 .scheduler
100 .tasks()
101 .find(|task| task.task_id() == task_id)
102 {
103 task.update_progress_in_database()
104 }
105
106 let mut info = match RequestDb::get_instance().get_task_info(task_id) {
107 Some(info) => info,
108 None => {
109 info!("TaskManger Query: no task found");
110 return None;
111 }
112 };
113
114 if info.action() == action || action == Action::Any {
115 info.data = "".to_string();
116 info.url = "".to_string();
117 Some(info)
118 } else {
119 info!("TaskManger Query: no task found");
120 None
121 }
122 }
123 }
124
125 impl RequestDb {
search_task(&self, filter: TaskFilter, uid: u64) -> Vec<u32>126 pub(crate) fn search_task(&self, filter: TaskFilter, uid: u64) -> Vec<u32> {
127 let mut sql = format!("SELECT task_id from request_task WHERE uid = {} AND ", uid);
128 Self::search_filter(&mut sql, &filter);
129 self.query_integer(&sql)
130 }
131
system_search_task(&self, filter: TaskFilter, bundle_name: String) -> Vec<u32>132 pub(crate) fn system_search_task(&self, filter: TaskFilter, bundle_name: String) -> Vec<u32> {
133 let mut sql = "SELECT task_id from request_task WHERE ".to_string();
134 if bundle_name != "*" {
135 sql.push_str(&format!("bundle = '{}' AND ", bundle_name));
136 }
137 Self::search_filter(&mut sql, &filter);
138 self.query_integer(&sql)
139 }
140
search_filter(sql: &mut String, filter: &TaskFilter)141 fn search_filter(sql: &mut String, filter: &TaskFilter) {
142 sql.push_str(&format!(
143 "ctime BETWEEN {} AND {} ",
144 filter.after, filter.before
145 ));
146 if filter.state != State::Any.repr {
147 sql.push_str(&format!("AND state = {} ", filter.state));
148 }
149 if filter.action != Action::Any.repr {
150 sql.push_str(&format!("AND action = {} ", filter.action));
151 }
152 if filter.mode != Mode::Any.repr {
153 sql.push_str(&format!("AND mode = {} ", filter.mode));
154 }
155 }
156 }
157
query_mime_type(uid: u64, task_id: u32) -> String158 pub(crate) fn query_mime_type(uid: u64, task_id: u32) -> String {
159 match RequestDb::get_instance().get_task_info(task_id) {
160 Some(info) if info.uid() == uid => info.mime_type(),
161 _ => {
162 info!("TaskManger QueryMimeType: no task found");
163 "".into()
164 }
165 }
166 }
167
168 #[derive(Debug)]
169 pub(crate) enum SearchMethod {
170 User(u64),
171 System(String),
172 }
173
174 #[allow(unreachable_pub)]
175 #[cxx::bridge(namespace = "OHOS::Request")]
176 mod ffi {
177 #[derive(Debug)]
178 struct TaskFilter {
179 before: i64,
180 after: i64,
181 state: u8,
182 action: u8,
183 mode: u8,
184 }
185 }
186
187 #[cfg(test)]
188 mod test {
189 use super::*;
190 use crate::tests::{lock_database, test_init};
191 use crate::utils::get_current_timestamp;
192 use crate::utils::task_id_generator::TaskIdGenerator;
193
194 #[test]
ut_search_user()195 fn ut_search_user() {
196 test_init();
197 let _lock = lock_database();
198 let db = RequestDb::get_instance();
199 let task_id = TaskIdGenerator::generate();
200 let uid = get_current_timestamp();
201 db.execute(&format!(
202 "INSERT INTO request_task (task_id, uid, state, ctime, action, mode) VALUES ({}, {}, {} ,{} ,{} ,{})",
203 task_id,
204 uid,
205 State::Removed.repr,
206 get_current_timestamp(),
207 Action::Upload.repr,
208 Mode::BackGround.repr
209 )).unwrap();
210
211 let filter = TaskFilter {
212 before: get_current_timestamp() as i64,
213 after: get_current_timestamp() as i64 - 200,
214 state: State::Completed.repr,
215 action: Action::Any.repr,
216 mode: Mode::Any.repr,
217 };
218 let res = db.search_task(filter, uid);
219 assert_eq!(res, vec![]);
220
221 let filter = TaskFilter {
222 before: get_current_timestamp() as i64,
223 after: get_current_timestamp() as i64 - 200,
224 state: State::Any.repr,
225 action: Action::Download.repr,
226 mode: Mode::Any.repr,
227 };
228 let res = db.search_task(filter, uid);
229 assert_eq!(res, vec![]);
230
231 let filter = TaskFilter {
232 before: get_current_timestamp() as i64,
233 after: get_current_timestamp() as i64 - 200,
234 state: State::Any.repr,
235 action: Action::Any.repr,
236 mode: Mode::FrontEnd.repr,
237 };
238 let res = db.search_task(filter, uid);
239 assert_eq!(res, vec![]);
240
241 let filter = TaskFilter {
242 before: get_current_timestamp() as i64,
243 after: get_current_timestamp() as i64 - 200,
244 state: State::Removed.repr,
245 action: Action::Upload.repr,
246 mode: Mode::BackGround.repr,
247 };
248 let res = db.search_task(filter, uid);
249 assert_eq!(res, vec![task_id as u32]);
250
251 let filter = TaskFilter {
252 before: get_current_timestamp() as i64,
253 after: get_current_timestamp() as i64 - 200,
254 state: State::Any.repr,
255 action: Action::Any.repr,
256 mode: Mode::Any.repr,
257 };
258 let res = db.search_task(filter, uid);
259 assert_eq!(res, vec![task_id as u32]);
260
261 let filter = TaskFilter {
262 before: get_current_timestamp() as i64,
263 after: get_current_timestamp() as i64 - 200,
264 state: State::Any.repr,
265 action: Action::Upload.repr,
266 mode: Mode::BackGround.repr,
267 };
268 let res = db.search_task(filter, uid);
269 assert_eq!(res, vec![task_id as u32]);
270 }
271
272 #[test]
ut_search_system()273 fn ut_search_system() {
274 test_init();
275 let db = RequestDb::get_instance();
276 let _lock = lock_database();
277 let task_id = TaskIdGenerator::generate();
278 let bundle_name = "com.ohos.app";
279 db.execute(&format!(
280 "INSERT INTO request_task (task_id, bundle, state, ctime, action, mode) VALUES ({}, '{}' ,{} ,{} ,{}, {})",
281 task_id,
282 bundle_name,
283 State::Removed.repr,
284 get_current_timestamp(),
285 Action::Download.repr,
286 Mode::BackGround.repr
287 )).unwrap();
288
289 let filter = TaskFilter {
290 before: get_current_timestamp() as i64,
291 after: get_current_timestamp() as i64 - 200,
292 state: State::Completed.repr,
293 action: Action::Any.repr,
294 mode: Mode::Any.repr,
295 };
296 let res = db.system_search_task(filter, bundle_name.to_string());
297 assert_eq!(res, vec![]);
298
299 let filter = TaskFilter {
300 before: get_current_timestamp() as i64,
301 after: get_current_timestamp() as i64 - 200,
302 state: State::Any.repr,
303 action: Action::Any.repr,
304 mode: Mode::Any.repr,
305 };
306 let res = db.system_search_task(filter, bundle_name.to_string());
307 assert_eq!(res, vec![task_id as u32]);
308
309 let filter = TaskFilter {
310 before: get_current_timestamp() as i64,
311 after: get_current_timestamp() as i64 - 200,
312 state: State::Any.repr,
313 action: Action::Download.repr,
314 mode: Mode::BackGround.repr,
315 };
316 let res = db.system_search_task(filter, "*".to_string());
317 assert_eq!(res, vec![task_id as u32]);
318 }
319 }
320