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(¬ifyData.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 ¬ifyData)
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 ¬ifyData)
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 ¬ifyData, Notify ¬ify)
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 ¬ifyData, Notify ¬ify)
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