• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "notify_stub.h"
17 
18 #include <thread>
19 
20 #include "download_server_ipc_interface_code.h"
21 #include "log.h"
22 #include "parcel_helper.h"
23 #include "request_event.h"
24 
25 namespace OHOS::Request {
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)26 int32_t NotifyStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
27 {
28     auto descriptorToken = data.ReadInterfaceToken();
29     if (descriptorToken != GetDescriptor()) {
30         REQUEST_HILOGE("Remote descriptor not the same as local descriptor.");
31         return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
32     }
33     switch (code) {
34         case static_cast<uint32_t>(RequestNotifyInterfaceCode::REQUEST_NOTIFY):
35             OnCallBack(data);
36             break;
37         case static_cast<uint32_t>(RequestNotifyInterfaceCode::REQUEST_DONE_NOTIFY):
38             break;
39         default:
40             REQUEST_HILOGE("Default value received, check needed.");
41             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
42     }
43     return ERR_NONE;
44 }
45 
OnCallBack(MessageParcel & data)46 void NotifyStub::OnCallBack(MessageParcel &data)
47 {
48     REQUEST_HILOGD("Receive callback");
49     std::string type = data.ReadString();
50     std::string tid = data.ReadString();
51     NotifyData notifyData;
52     notifyData.progress.state = static_cast<State>(data.ReadUint32());
53     notifyData.progress.index = data.ReadUint32();
54     notifyData.progress.processed = data.ReadUint64();
55     notifyData.progress.totalProcessed = data.ReadUint64();
56     data.ReadInt64Vector(&notifyData.progress.sizes);
57     uint32_t size = data.ReadUint32();
58     if (size > data.GetReadableBytes()) {
59         REQUEST_HILOGE("Size exceeds the upper limit, size = %{public}d", size);
60         return;
61     }
62     for (uint32_t i = 0; i < size; i++) {
63         std::string key = data.ReadString();
64         notifyData.progress.extras[key] = data.ReadString();
65     }
66 
67     notifyData.action = static_cast<Action>(data.ReadUint32());
68     notifyData.version = static_cast<Version>(data.ReadUint32());
69     size = data.ReadUint32();
70     if (size > data.GetReadableBytes()) {
71         REQUEST_HILOGE("Size exceeds the upper limit, size = %{public}d", size);
72         return;
73     }
74     for (uint32_t i = 0; i < size; i++) {
75         TaskState taskState;
76         taskState.path = data.ReadString();
77         taskState.responseCode = data.ReadUint32();
78         taskState.message = data.ReadString();
79         notifyData.taskStates.push_back(taskState);
80     }
81     RequestCallBack(type, tid, notifyData);
82 
83     if (type == "complete" || type == "fail" || type == "remove") {
84         JsTask::ClearTaskContext(tid);
85         JsTask::ClearTaskMap(tid);
86     }
87 }
88 
RequestCallBack(const std::string & type,const std::string & tid,const NotifyData & notifyData)89 void NotifyStub::RequestCallBack(const std::string &type, const std::string &tid, const NotifyData &notifyData)
90 {
91     REQUEST_HILOGI("RequestCallBack type is %{public}s, tid is %{public}s", type.c_str(), tid.c_str());
92     Notify notify;
93     if (notifyData.version != Version::API10) {
94         auto func = notifyData.action == Action::DOWNLOAD ? GetDownloadNotify : GetUploadNotify;
95         func(type, notifyData, notify);
96     } else {
97         REQUEST_HILOGD("Receive API10 callback");
98         notify.type = EventType::PROGRESS_CALLBACK;
99         notify.progress = notifyData.progress;
100     }
101 
102     JsTask *task = nullptr;
103     {
104         std::lock_guard<std::mutex> lockGuard(JsTask::taskMutex_);
105         auto item = JsTask::taskMap_.find(tid);
106         if (item == JsTask::taskMap_.end()) {
107             REQUEST_HILOGE("Task ID not found");
108             return;
109         }
110         task = item->second;
111     }
112 
113     uint32_t index = notifyData.progress.index;
114     size_t len = task->config_.bodyFileNames.size();
115     if (index < len && IsHeaderReceive(type, notifyData)) {
116         std::string &filePath = task->config_.bodyFileNames[index];
117         NapiUtils::ReadBytesFromFile(filePath, notify.progress.bodyBytes);
118         // Waiting for "complete" to read and delete.
119         if (!(notifyData.version == Version::API10 && index == len - 1 && type == "progress")) {
120             NapiUtils::RemoveFile(filePath);
121         }
122     }
123 
124     std::string key = type + tid;
125     std::lock_guard<std::mutex> autoLock(task->listenerMutex_);
126     auto it = task->listenerMap_.find(key);
127     if (it == task->listenerMap_.end()) {
128         REQUEST_HILOGE("Unregistered %{public}s callback", type.c_str());
129         return;
130     }
131     for (const auto &callback : it->second) {
132         callback->CallBack(notify);
133     }
134 }
135 
IsHeaderReceive(const std::string & type,const NotifyData & notifyData)136 bool NotifyStub::IsHeaderReceive(const std::string &type, const NotifyData &notifyData)
137 {
138     if (notifyData.version == Version::API9 && notifyData.action == Action::UPLOAD && type == "headerReceive") {
139         return true;
140     } else if (notifyData.version == Version::API10 && notifyData.action == Action::UPLOAD
141                && notifyData.progress.state == State::COMPLETED && (type == "progress" || type == "complete")) {
142         return true;
143     }
144     return false;
145 }
146 
GetDownloadNotify(const std::string & type,const NotifyData & notifyData,Notify & notify)147 void NotifyStub::GetDownloadNotify(const std::string &type, const NotifyData &notifyData, Notify &notify)
148 {
149     REQUEST_HILOGD("Get download notify data");
150     notify.type = EventType::DATA_CALLBACK;
151     if (type == "progress") {
152         notify.data.push_back(notifyData.progress.processed);
153         if (!notifyData.progress.sizes.empty()) {
154             notify.data.push_back(notifyData.progress.sizes[0]);
155         }
156     } else if (type == "fail") {
157         if (notifyData.taskStates.empty()) {
158             return;
159         }
160         int64_t failedReason;
161         auto it = RequestEvent::failMap_.find(static_cast<Reason>(notifyData.taskStates[0].responseCode));
162         if (it != RequestEvent::failMap_.end()) {
163             failedReason = it->second;
164         } else {
165             failedReason = static_cast<int64_t>(ERROR_UNKNOWN);
166         }
167         notify.data.push_back(failedReason);
168     }
169 }
170 
GetUploadNotify(const std::string & type,const NotifyData & notifyData,Notify & notify)171 void NotifyStub::GetUploadNotify(const std::string &type, const NotifyData &notifyData, Notify &notify)
172 {
173     REQUEST_HILOGD("Get upload notify data");
174     if (type == "complete" || type == "fail") {
175         notify.type = EventType::TASK_STATE_CALLBACK;
176         notify.taskStates = notifyData.taskStates;
177     } else if (type == "progress") {
178         notify.type = EventType::DATA_CALLBACK;
179         int64_t size = 0;
180         for (const auto &i : notifyData.progress.sizes) {
181             size += i;
182         }
183         notify.data.push_back(notifyData.progress.totalProcessed);
184         notify.data.push_back(size);
185     } else {
186         notify.type = EventType::HEADER_CALLBACK;
187         notify.progress.extras = notifyData.progress.extras;
188     }
189 }
190 } // namespace OHOS::Request
191