1 /*
2 * Copyright (c) 2021 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 "update_client.h"
17
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <fstream>
22 #include <iostream>
23 #include <memory>
24 #include <mutex>
25 #include <string>
26 #include <sys/reboot.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <tuple>
30 #include <unistd.h>
31 #include <uv.h>
32 #include <vector>
33
34 #include "iupdate_service.h"
35 #include "misc_info/misc_info.h"
36 #include "node_api.h"
37 #include "node_api_types.h"
38 #include "package/package.h"
39 #include "securec.h"
40 #include "update_helper.h"
41 #include "update_service_kits.h"
42 #include "update_session.h"
43
44 using namespace std;
45 using namespace OHOS::update_engine;
46
47 namespace updateClient {
48 const int32_t MAX_ARGC = 3;
49 const int32_t DEVICE_ID_INDEX = 1;
50 const int32_t MID_ARGC = 2;
51 const int32_t CLIENT_STRING_MAX_LENGTH = 200;
52 constexpr int PROGRESS_DOWNLOAD_FINISH = 100;
53 const std::string MISC_FILE = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc";
54 const std::string CMD_WIPE_DATA = "--user_wipe_data";
55 const std::string UPDATER_PKG_NAME = "/data/updater/updater.zip";
56
57 struct NotifyInput {
58 NotifyInput() = default;
NotifyInputupdateClient::NotifyInput59 NotifyInput(UpdateClient* iclient, const string &itype, int32_t iretcode, UpdateResult *iresult)
60 :client(iclient), type(itype), retcode(iretcode), result(iresult) {}
61 UpdateClient* client;
62 string type;
63 int32_t retcode;
64 UpdateResult *result;
65 };
66
UpdateClient(napi_env env,napi_value thisVar)67 UpdateClient::UpdateClient(napi_env env, napi_value thisVar)
68 {
69 thisReference_ = nullptr;
70 env_ = env;
71 napi_create_reference(env, thisVar, 1, &thisReference_);
72 context_.type = "OTA";
73 context_.upgradeDevId = "local";
74 context_.controlDevId = "local";
75 context_.upgradeApp = "updateclient";
76 context_.upgradeFile = UPDATER_PKG_NAME;
77 }
78
~UpdateClient()79 UpdateClient::~UpdateClient()
80 {
81 sessions_.clear();
82 if (thisReference_ != nullptr) {
83 napi_delete_reference(env_, thisReference_);
84 }
85 }
86
RemoveSession(uint32_t sessionId)87 UpdateSession *UpdateClient::RemoveSession(uint32_t sessionId)
88 {
89 CLIENT_LOGI("RemoveSession sess");
90 #ifndef UPDATER_API_TEST
91 std::lock_guard<std::mutex> guard(sessionMutex_);
92 #endif
93 UpdateSession *sess = nullptr;
94 auto iter = sessions_.find(sessionId);
95 if (iter != sessions_.end()) {
96 sess = iter->second.get();
97 sessions_.erase(iter);
98 }
99 return sess;
100 }
101
AddSession(std::shared_ptr<UpdateSession> session)102 void UpdateClient::AddSession(std::shared_ptr<UpdateSession> session)
103 {
104 CLIENT_CHECK(session != nullptr, return, "Invalid param");
105 #ifndef UPDATER_API_TEST
106 std::lock_guard<std::mutex> guard(sessionMutex_);
107 #endif
108 sessions_.insert(make_pair(session->GetSessionId(), session));
109 }
110
GetUpdaterForOther(napi_env env,napi_callback_info info)111 napi_value UpdateClient::GetUpdaterForOther(napi_env env, napi_callback_info info)
112 {
113 size_t argc = MAX_ARGC;
114 napi_value args[MAX_ARGC] = {0};
115 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
116 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
117 CLIENT_CHECK_NAPI_CALL(env, argc >= MID_ARGC, return nullptr, "Invalid param");
118
119 // Get the devid.
120 int ret = GetStringValue(env, args[1], context_.upgradeDevId);
121 CLIENT_CHECK_NAPI_CALL(env, ret == napi_ok, return nullptr, "Error get type");
122 return GetUpdater(env, info, DEVICE_ID_INDEX + 1);
123 }
124
GetUpdaterFromOther(napi_env env,napi_callback_info info)125 napi_value UpdateClient::GetUpdaterFromOther(napi_env env, napi_callback_info info)
126 {
127 size_t argc = MAX_ARGC;
128 napi_value args[MAX_ARGC] = {0};
129 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
130 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
131 CLIENT_CHECK_NAPI_CALL(env, argc >= MID_ARGC, return nullptr, "Invalid param");
132
133 // Get the devid.
134 int ret = GetStringValue(env, args[1], context_.controlDevId);
135 CLIENT_CHECK_NAPI_CALL(env, ret == napi_ok, return nullptr, "Error get type");
136 return GetUpdater(env, info, DEVICE_ID_INDEX + 1);
137 }
138
CheckUpgradeType(const std::string & type)139 bool UpdateClient::CheckUpgradeType(const std::string &type)
140 {
141 std::vector<std::string> upgradeTypes = {
142 "ota", "patch"
143 };
144 std::string upgradeType = type;
145 upgradeType.erase(0, upgradeType.find_first_not_of(" "));
146 upgradeType.erase(upgradeType.find_last_not_of(" ") + 1);
147 std::transform(upgradeType.begin(), upgradeType.end(), upgradeType.begin(), ::tolower);
148 for (auto inter = upgradeTypes.cbegin(); inter != upgradeTypes.cend(); inter++) {
149 if ((*inter).compare(upgradeType) == 0) {
150 return true;
151 }
152 }
153 return false;
154 }
155
CheckUpgradeFile(const std::string & upgradeFile)156 bool UpdateClient::CheckUpgradeFile(const std::string &upgradeFile)
157 {
158 if (upgradeFile.empty()) {
159 return false;
160 }
161 std::string file = upgradeFile;
162 file.erase(0, file.find_first_not_of(" "));
163 file.erase(file.find_last_not_of(" ") + 1);
164 int32_t pos = file.find_first_of('/');
165 if (pos != 0) {
166 return false;
167 }
168 pos = file.find_last_of('.');
169 if (pos < 0) {
170 return false;
171 }
172 std::string postfix = file.substr(pos + 1, -1);
173 std::transform(postfix.begin(), postfix.end(), postfix.begin(), ::tolower);
174 if (postfix.compare("bin") == 0) {
175 return true;
176 } else if (postfix.compare("zip") == 0) {
177 return true;
178 } else if (postfix.compare("lz4") == 0) {
179 return true;
180 } else if (postfix.compare("gz") == 0) {
181 return true;
182 }
183 return false;
184 }
185
GetUpdater(napi_env env,napi_callback_info info,int32_t typeIndex)186 napi_value UpdateClient::GetUpdater(napi_env env, napi_callback_info info, int32_t typeIndex)
187 {
188 napi_value result;
189 napi_create_int32(env, 0, &result);
190 size_t argc = MAX_ARGC;
191 napi_value args[MAX_ARGC] = {0};
192 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
193 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
194 CLIENT_CHECK_NAPI_CALL(env, argc >= 1, return nullptr, "Invalid param");
195 CLIENT_CHECK_NAPI_CALL(env, !isInit, return result, "Has beed init");
196
197 int ret = GetStringValue(env, args[0], context_.upgradeFile);
198 CLIENT_CHECK_NAPI_CALL(env, ret == napi_ok && CheckUpgradeFile(context_.upgradeFile),
199 return nullptr, "Invalid upgradeFile");
200 ret = GetStringValue(env, args[typeIndex], context_.type);
201 if (ret == napi_ok) {
202 CLIENT_CHECK_NAPI_CALL(env, CheckUpgradeType(context_.type), return nullptr, "Error get upgradeType");
203 } else {
204 context_.type = "OTA";
205 }
206 CLIENT_LOGE("GetUpdater argc %s", context_.type.c_str());
207 UpdateCallbackInfo callback {
208 [&](const VersionInfo &info) {
209 this->NotifyCheckVersionDone(info);
210 },
211 [&](const Progress &info) {
212 this->NotifyDownloadProgress(info);
213 },
214 [&](const Progress &info) {
215 this->NotifyUpgradeProgresss(info);
216 },
217 };
218 UpdateServiceKits::GetInstance().RegisterUpdateCallback(context_, callback);
219 isInit = true;
220 return result;
221 }
222
StartSession(napi_env env,napi_callback_info info,int32_t type,size_t callbackStartIndex,DoWorkFunction function)223 napi_value UpdateClient::StartSession(napi_env env,
224 napi_callback_info info, int32_t type, size_t callbackStartIndex, DoWorkFunction function)
225 {
226 size_t argc = MAX_ARGC;
227 napi_value args[MAX_ARGC] = {0};
228 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
229 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
230
231 CLIENT_LOGE("StartSession type %d argc %zu callbackStartIndex %d", type, argc,
232 static_cast<int>(callbackStartIndex));
233 std::shared_ptr<UpdateSession> sess = nullptr;
234 if (argc > callbackStartIndex) {
235 sess = std::make_shared<UpdateAsyncession>(this, type, argc, 1);
236 } else {
237 sess = std::make_shared<UpdatePromiseSession>(this, type, argc, 0);
238 }
239 CLIENT_CHECK_NAPI_CALL(env, sess != nullptr, return nullptr, "Failed to create update session");
240 AddSession(sess);
241 napi_value retValue = sess->StartWork(env, callbackStartIndex, args, function, nullptr);
242 CLIENT_CHECK(retValue != nullptr, RemoveSession(sess->GetSessionId()); return nullptr, "Failed to start worker.");
243
244 return retValue;
245 }
246
CheckNewVersion(napi_env env,napi_callback_info info)247 napi_value UpdateClient::CheckNewVersion(napi_env env, napi_callback_info info)
248 {
249 versionInfo_.status = SYSTEM_ERROR;
250 napi_value ret = StartSession(env, info, SESSION_CHECK_VERSION, 0,
251 [&](int32_t type, void *context) -> int {
252 return UpdateServiceKits::GetInstance().CheckNewVersion();
253 });
254 CLIENT_CHECK(ret != nullptr, return nullptr, "Failed to start worker.");
255 return ret;
256 }
257
CancelUpgrade(napi_env env,napi_callback_info info)258 napi_value UpdateClient::CancelUpgrade(napi_env env, napi_callback_info info)
259 {
260 size_t argc = MAX_ARGC;
261 napi_value args[MAX_ARGC] = {0};
262 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
263 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok && argc == 0, return nullptr, "Error get cb info");
264 CLIENT_LOGE("CancelUpgrade");
265 std::shared_ptr<UpdateSession> sess = nullptr;
266 sess = std::make_shared<UpdateAsyncessionNoCallback>(this, SESSION_CANCEL_UPGRADE, argc, 0);
267 CLIENT_CHECK_NAPI_CALL(env, sess != nullptr, return nullptr, "Failed to create update session");
268 AddSession(sess);
269 napi_value retValue = sess->StartWork(env, 0, args,
270 [&](int32_t type, void *context) -> int {
271 return UpdateServiceKits::GetInstance().Cancel(IUpdateService::DOWNLOAD);
272 }, nullptr);
273 CLIENT_CHECK(retValue != nullptr, RemoveSession(sess->GetSessionId()); return nullptr, "Failed to start worker.");
274 return retValue;
275 }
276
DownloadVersion(napi_env env,napi_callback_info info)277 napi_value UpdateClient::DownloadVersion(napi_env env, napi_callback_info info)
278 {
279 size_t argc = MAX_ARGC;
280 napi_value args[MAX_ARGC] = {0};
281 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
282 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
283 CLIENT_LOGE("DownloadVersion");
284 std::shared_ptr<UpdateSession> sess = nullptr;
285 sess = std::make_shared<UpdateAsyncessionNoCallback>(this, SESSION_DOWNLOAD, argc, 0);
286 CLIENT_CHECK_NAPI_CALL(env, sess != nullptr, return nullptr, "Failed to create update session");
287 AddSession(sess);
288 napi_value retValue = sess->StartWork(env, 0, args,
289 [&](int32_t type, void *context) -> int {
290 return UpdateServiceKits::GetInstance().DownloadVersion();
291 }, nullptr);
292 CLIENT_CHECK(retValue != nullptr, RemoveSession(sess->GetSessionId()); return nullptr, "Failed to start worker.");
293 return retValue;
294 }
295
UpgradeVersion(napi_env env,napi_callback_info info)296 napi_value UpdateClient::UpgradeVersion(napi_env env, napi_callback_info info)
297 {
298 size_t argc = MAX_ARGC;
299 napi_value args[MAX_ARGC] = {0};
300 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
301 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
302 std::shared_ptr<UpdateSession> sess = nullptr;
303 sess = std::make_shared<UpdateAsyncessionNoCallback>(this, SESSION_UPGRADE, argc, 0);
304 CLIENT_CHECK_NAPI_CALL(env, sess != nullptr, return nullptr, "Failed to create update session");
305 AddSession(sess);
306 napi_value retValue = sess->StartWork(env, 0, args,
307 [&](int32_t type, void *context) -> int {
308 #ifndef UPDATER_API_TEST
309 return UpdateServiceKits::GetInstance().DoUpdate();
310 #else
311 return 0;
312 #endif
313 }, nullptr);
314 CLIENT_CHECK(retValue != nullptr, RemoveSession(sess->GetSessionId()); return nullptr, "Failed to start worker.");
315 return retValue;
316 }
317
SetUpdatePolicy(napi_env env,napi_callback_info info)318 napi_value UpdateClient::SetUpdatePolicy(napi_env env, napi_callback_info info)
319 {
320 size_t argc = MAX_ARGC;
321 napi_value args[MAX_ARGC] = {0};
322 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
323 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
324
325 int ret = GetUpdatePolicyFromArg(env, args[0], updatePolicy_);
326 CLIENT_CHECK_NAPI_CALL(env, ret == napi_ok, return nullptr, "Failed to get policy para");
327
328 std::shared_ptr<UpdateSession> sess = nullptr;
329 if (argc >= MID_ARGC) {
330 sess = std::make_shared<UpdateAsyncession>(this, SESSION_SET_POLICY, argc, 1);
331 } else {
332 sess = std::make_shared<UpdatePromiseSession>(this, SESSION_SET_POLICY, argc, 0);
333 }
334 CLIENT_CHECK_NAPI_CALL(env, sess != nullptr, return nullptr, "Failed to create update session");
335 AddSession(sess);
336 napi_value retValue = sess->StartWork(env, 1, args,
337 [&](int32_t type, void *context) -> int {
338 result_ = UpdateServiceKits::GetInstance().SetUpdatePolicy(updatePolicy_);
339 return result_;
340 }, nullptr);
341 CLIENT_CHECK(retValue != nullptr, RemoveSession(sess->GetSessionId());
342 return nullptr, "Failed to SetUpdatePolicy.");
343 return retValue;
344 }
345
GetUpdatePolicy(napi_env env,napi_callback_info info)346 napi_value UpdateClient::GetUpdatePolicy(napi_env env, napi_callback_info info)
347 {
348 napi_value retValue = StartSession(env, info, SESSION_GET_POLICY, 0,
349 [&](int32_t type, void *context) -> int {
350 return UpdateServiceKits::GetInstance().GetUpdatePolicy(updatePolicy_);
351 });
352 CLIENT_CHECK(retValue != nullptr, return nullptr, "Failed to UpgradeVersion.");
353 return retValue;
354 }
355
GetNewVersionInfo(napi_env env,napi_callback_info info)356 napi_value UpdateClient::GetNewVersionInfo(napi_env env, napi_callback_info info)
357 {
358 napi_value retValue = StartSession(env, info, SESSION_GET_NEW_VERSION, 0,
359 [&](int32_t type, void *context) -> int {
360 return UpdateServiceKits::GetInstance().GetNewVersion(versionInfo_);
361 });
362 CLIENT_CHECK(retValue != nullptr, return nullptr, "Failed to GetNewVersionInfo.");
363 return retValue;
364 }
365
GetUpgradeStatus(napi_env env,napi_callback_info info)366 napi_value UpdateClient::GetUpgradeStatus(napi_env env, napi_callback_info info)
367 {
368 napi_value retValue = StartSession(env, info, SESSION_GET_STATUS, 0,
369 [&](int32_t type, void *context) -> int {
370 return UpdateServiceKits::GetInstance().GetUpgradeStatus(upgradeInfo_);
371 });
372 CLIENT_CHECK(retValue != nullptr, return nullptr, "Failed to GetUpgradeStatus.");
373 return retValue;
374 }
375
ApplyNewVersion(napi_env env,napi_callback_info info)376 napi_value UpdateClient::ApplyNewVersion(napi_env env, napi_callback_info info)
377 {
378 napi_value retValue = StartSession(env, info, SESSION_APPLY_NEW_VERSION, 0,
379 [&](int32_t type, void *context) -> int {
380 #ifndef UPDATER_API_TEST
381 result_ = UpdateServiceKits::GetInstance().RebootAndInstall(MISC_FILE, UPDATER_PKG_NAME);
382 #endif
383 return result_;
384 });
385 CLIENT_CHECK(retValue != nullptr, return nullptr, "Failed to GetNewVersionInfo.");
386 return retValue;
387 }
388
RebootAndClean(napi_env env,napi_callback_info info)389 napi_value UpdateClient::RebootAndClean(napi_env env, napi_callback_info info)
390 {
391 napi_value retValue = StartSession(env, info, SESSION_REBOOT_AND_CLEAN, 0,
392 [&](int32_t type, void *context) -> int {
393 #ifndef UPDATER_API_TEST
394 result_ = UpdateServiceKits::GetInstance().RebootAndClean(MISC_FILE, CMD_WIPE_DATA);
395 #endif
396 return result_;
397 });
398 CLIENT_CHECK(retValue != nullptr, return nullptr, "Failed to GetNewVersionInfo.");
399 return retValue;
400 }
401
VerifyUpdatePackage(napi_env env,napi_callback_info info)402 napi_value UpdateClient::VerifyUpdatePackage(napi_env env, napi_callback_info info)
403 {
404 size_t argc = MAX_ARGC;
405 napi_value args[MAX_ARGC] = {0};
406 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
407 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
408 CLIENT_CHECK_NAPI_CALL(env, argc >= MID_ARGC, return nullptr, "Error get cb info");
409
410 int ret = GetStringValue(env, args[0], upgradeFile_);
411 CLIENT_CHECK_NAPI_CALL(env, ret == napi_ok, return nullptr, "Error get upgradeType");
412 ret = GetStringValue(env, args[1], certsFile_);
413 CLIENT_CHECK_NAPI_CALL(env, ret == napi_ok, return nullptr, "Error get certsFile");
414
415 CLIENT_LOGE("VerifyUpdatePackage");
416 std::shared_ptr<UpdateSession> sess = nullptr;
417 sess = std::make_shared<UpdateAsyncessionNoCallback>(this, SESSION_VERIFY_PACKAGE, argc, 0);
418 CLIENT_CHECK_NAPI_CALL(env, sess != nullptr, return nullptr, "Fail to create update session");
419 AddSession(sess);
420 size_t startIndex = 2;
421 napi_value retValue = sess->StartWork(env, startIndex, args,
422 [&](int32_t type, void *context) -> int {
423 CLIENT_LOGE("StartWork VerifyUpdatePackage");
424 result_ = VerifyPackageWithCallback(upgradeFile_, certsFile_,
425 [&](int32_t result, uint32_t percent) { NotifyVerifyProgresss(result, percent); });
426 return result_;
427 },
428 nullptr);
429 CLIENT_CHECK(retValue != nullptr, RemoveSession(sess->GetSessionId()); return nullptr, "Failed to start worker.");
430 return retValue;
431 }
432
SubscribeEvent(napi_env env,napi_callback_info info)433 napi_value UpdateClient::SubscribeEvent(napi_env env, napi_callback_info info)
434 {
435 size_t argc = MAX_ARGC;
436 napi_value args[MAX_ARGC] = {0};
437 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
438 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
439 // Two arguments are required: type + callback.
440 CLIENT_CHECK_NAPI_CALL(env, argc >= MID_ARGC, return nullptr, "Invalid param");
441
442 std::string eventType;
443 int ret = UpdateClient::GetStringValue(env, args[0], eventType);
444 CLIENT_CHECK_NAPI_CALL(env, ret == napi_ok, return nullptr, "Failed to get event type");
445 CLIENT_CHECK(FindSessionByHandle(env, eventType, args[1]) == nullptr, return nullptr, "Handle has been sub");
446
447 std::shared_ptr<UpdateSession> sess = std::make_shared<UpdateListener>(this, SESSION_SUBSCRIBE, argc, 1, false);
448 CLIENT_CHECK_NAPI_CALL(env, sess != nullptr, return nullptr, "Failed to create listener");
449 AddSession(sess);
450 napi_value retValue = sess->StartWork(env, 1, args,
451 [&](int32_t type, void *context) -> int {
452 return 0;
453 }, nullptr);
454 CLIENT_CHECK(retValue != nullptr, RemoveSession(sess->GetSessionId()); return nullptr, "Failed to SubscribeEvent.");
455 return retValue;
456 }
457
UnsubscribeEvent(napi_env env,napi_callback_info info)458 napi_value UpdateClient::UnsubscribeEvent(napi_env env, napi_callback_info info)
459 {
460 size_t argc = MAX_ARGC;
461 napi_value args[MAX_ARGC] = {0};
462 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
463 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Error get cb info");
464
465 std::string eventType;
466 int ret = UpdateClient::GetStringValue(env, args[0], eventType);
467 CLIENT_CHECK_NAPI_CALL(env, ret == napi_ok, return nullptr, "Failed to get event type");
468
469 CLIENT_LOGI("UnsubscribeEvent %s argc %d", eventType.c_str(), static_cast<int>(argc));
470 if (argc >= MID_ARGC) {
471 napi_valuetype valuetype;
472 napi_status status = napi_typeof(env, args[1], &valuetype);
473 CLIENT_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Failed to napi_typeof");
474 CLIENT_CHECK_NAPI_CALL(env, valuetype == napi_function, return nullptr, "Invalid callback type");
475 }
476 ret = ProcessUnsubscribe(eventType, argc, args[1]);
477 napi_value result;
478 napi_create_int32(env, ret, &result);
479 return result;
480 }
481
ProcessUnsubscribe(const std::string & eventType,size_t argc,napi_value arg)482 int32_t UpdateClient::ProcessUnsubscribe(const std::string &eventType, size_t argc, napi_value arg)
483 {
484 napi_handle_scope scope;
485 napi_status status = napi_open_handle_scope(env_, &scope);
486 CLIENT_CHECK(status == napi_ok, return -1, "Error open handle");
487
488 uint32_t nextSessId = 0;
489 bool hasNext = GetFirstSessionId(nextSessId);
490 while (hasNext) {
491 uint32_t currSessId = nextSessId;
492 auto iter = sessions_.find(currSessId);
493 if (iter == sessions_.end()) {
494 break;
495 }
496 hasNext = GetNextSessionId(nextSessId);
497
498 UpdateListener *listener = static_cast<UpdateListener *>(iter->second.get());
499 if (listener->GetType() != SESSION_SUBSCRIBE
500 || eventType.compare(listener->GetEventType()) != 0) {
501 continue;
502 }
503 CLIENT_LOGI("ProcessUnsubscribe remove session");
504 if (argc == 1) {
505 listener->RemoveHandlerRef(env_);
506 RemoveSession(currSessId);
507 } else if (listener->CheckEqual(env_, arg, eventType)) {
508 listener->RemoveHandlerRef(env_);
509 RemoveSession(currSessId);
510 break;
511 }
512 }
513 napi_close_handle_scope(env_, scope);
514 return 0;
515 }
516
FindSessionByHandle(napi_env env,const std::string & eventType,napi_value arg)517 UpdateSession *UpdateClient::FindSessionByHandle(napi_env env, const std::string &eventType, napi_value arg)
518 {
519 uint32_t nextSessId = 0;
520 bool hasNext = GetFirstSessionId(nextSessId);
521 while (hasNext) {
522 uint32_t currSessId = nextSessId;
523 auto iter = sessions_.find(currSessId);
524 if (iter == sessions_.end()) {
525 break;
526 }
527 hasNext = GetNextSessionId(nextSessId);
528
529 UpdateListener *listener = static_cast<UpdateListener *>(iter->second.get());
530 if (listener->GetType() != SESSION_SUBSCRIBE) {
531 continue;
532 }
533 if ((eventType.compare(listener->GetEventType()) == 0) && listener->CheckEqual(env_, arg, eventType)) {
534 return listener;
535 }
536 }
537 return nullptr;
538 }
539
GetNextSessionId(uint32_t & sessionId)540 bool UpdateClient::GetNextSessionId(uint32_t &sessionId)
541 {
542 #ifndef UPDATER_API_TEST
543 std::lock_guard<std::mutex> guard(sessionMutex_);
544 #endif
545 {
546 auto iter = sessions_.find(sessionId);
547 if (iter == sessions_.end()) {
548 return false;
549 }
550 iter++;
551 if (iter == sessions_.end()) {
552 return false;
553 }
554 sessionId = iter->second->GetSessionId();
555 }
556 return true;
557 }
558
GetFirstSessionId(uint32_t & sessionId)559 bool UpdateClient::GetFirstSessionId(uint32_t &sessionId)
560 {
561 #ifndef UPDATER_API_TEST
562 std::lock_guard<std::mutex> guard(sessionMutex_);
563 #endif
564 {
565 if (sessions_.empty()) {
566 return false;
567 }
568 sessionId = sessions_.begin()->second->GetSessionId();
569 return true;
570 }
571 }
572
PublishToJS(const std::string & type,int32_t retcode,const UpdateResult & result)573 void UpdateClient::PublishToJS(const std::string &type, int32_t retcode, const UpdateResult &result)
574 {
575 napi_handle_scope scope;
576 napi_status status = napi_open_handle_scope(env_, &scope);
577 CLIENT_CHECK_NAPI_CALL(env_, status == napi_ok, return, "Error open_handle_scope");
578 napi_value thisVar = nullptr;
579 status = napi_get_reference_value(env_, thisReference_, &thisVar);
580 CLIENT_CHECK_NAPI_CALL(env_, status == napi_ok, return, "Error get_reference");
581
582 uint32_t nextSessId = 0;
583 bool hasNext = GetFirstSessionId(nextSessId);
584 while (hasNext) {
585 uint32_t currSessId = nextSessId;
586 auto iter = sessions_.find(currSessId);
587 if (iter == sessions_.end()) {
588 break;
589 }
590 hasNext = GetNextSessionId(nextSessId);
591 UpdateListener *listener = static_cast<UpdateListener *>((iter->second).get());
592 if ((listener->GetType() != SESSION_SUBSCRIBE) || (type.compare(listener->GetEventType()) != 0)) {
593 continue;
594 }
595 listener->NotifyJS(env_, thisVar, retcode, result);
596 iter = sessions_.find(currSessId);
597 if (iter == sessions_.end()) {
598 continue;
599 }
600 listener = static_cast<UpdateListener *>((iter->second).get());
601 if (listener->IsOnce()) {
602 listener->RemoveHandlerRef(env_);
603 RemoveSession(currSessId);
604 }
605 }
606 napi_close_handle_scope(env_, scope);
607 }
608
Emit(const std::string & type,int32_t retcode,const UpdateResult & result)609 void UpdateClient::Emit(const std::string &type, int32_t retcode, const UpdateResult &result)
610 {
611 auto freeUpdateResult = [](const UpdateResult *lres) {
612 if (lres != nullptr) {
613 delete lres->result.progress;
614 }
615 delete lres;
616 };
617 UpdateResult *res = new(std::nothrow) UpdateResult();
618 CLIENT_CHECK(res != nullptr, return, "copy update result failed.");
619 res->type = result.type;
620 res->buildJSObject = result.buildJSObject;
621 res->result.progress = new(std::nothrow) Progress();
622 CLIENT_CHECK(res->result.progress != nullptr,
623 freeUpdateResult(res);
624 return, "copy update result failed.");
625 res->result.progress->status = result.result.progress->status;
626 res->result.progress->endReason = result.result.progress->endReason;
627 res->result.progress->percent = result.result.progress->percent;
628
629 uv_loop_s *loop = nullptr;
630 napi_get_uv_event_loop(env_, &loop);
631 CLIENT_CHECK(loop != nullptr,
632 freeUpdateResult(res);
633 return, "get event loop failed.");
634 uv_work_t *work = new(std::nothrow) uv_work_t;
635 CLIENT_CHECK(work != nullptr,
636 freeUpdateResult(res);
637 return, "alloc work failed.");
638 work->data = (void*)new(std::nothrow) NotifyInput(this, type, retcode, res);
639 CLIENT_CHECK(work != nullptr,
640 freeUpdateResult(res);
641 delete work;
642 return, "alloc work data failed.");
643
644 uv_queue_work(
645 loop,
646 work,
647 [](uv_work_t *work) {}, // run in C++ thread
648 [](uv_work_t *work, int status) {
649 NotifyInput *input = (NotifyInput *)work->data;
650 input->client->PublishToJS(input->type, input->retcode, *input->result);
651 delete input->result->result.progress;
652 delete input->result;
653 delete input;
654 });
655 }
656
NotifyDownloadProgress(const Progress & progress)657 void UpdateClient::NotifyDownloadProgress(const Progress &progress)
658 {
659 CLIENT_LOGI("NotifyDownloadProgress status %d %d", progress.status, progress.percent);
660 if (progress.percent == PROGRESS_DOWNLOAD_FINISH && progress.status == UPDATE_STATE_DOWNLOAD_ON) {
661 return;
662 }
663 progress_.percent = progress.percent;
664 progress_.status = progress.status;
665 progress_.endReason = progress.endReason;
666 UpdateResult result;
667 result.type = SESSION_DOWNLOAD;
668 result.result.progress = &progress_;
669 result.buildJSObject = BuildProgress;
670 int32_t fail = (progress_.status == UPDATE_STATE_DOWNLOAD_FAIL || progress_.status == UPDATE_STATE_VERIFY_FAIL) ?
671 progress_.status : 0;
672 Emit("downloadProgress", fail, result);
673 }
674
NotifyUpgradeProgresss(const Progress & progress)675 void UpdateClient::NotifyUpgradeProgresss(const Progress &progress)
676 {
677 CLIENT_LOGI("NotifyUpgradeProgresss status %d %d", progress.status, progress.percent);
678 progress_.percent = progress.percent;
679 progress_.status = progress.status;
680
681 UpdateResult result;
682 result.type = SESSION_UPGRADE;
683 result.result.progress = &progress_;
684 result.buildJSObject = BuildProgress;
685 int32_t fail = (progress_.status == UPDATE_STATE_DOWNLOAD_FAIL) ? progress_.status : 0;
686 Emit("upgradeProgress", fail, result);
687 }
688
NotifyVerifyProgresss(int32_t retCode,uint32_t percent)689 void UpdateClient::NotifyVerifyProgresss(int32_t retCode, uint32_t percent)
690 {
691 verifyProgress_.status = (retCode == 0) ? UPDATE_STATE_VERIFY_SUCCESS : UPDATE_STATE_VERIFY_FAIL;
692 verifyProgress_.percent = percent;
693
694 UpdateResult result;
695 result.type = SESSION_VERIFY_PACKAGE;
696 result.result.progress = &verifyProgress_;
697 result.buildJSObject = BuildProgress;
698 Emit("verifyProgress", retCode, result);
699 }
700
NotifyCheckVersionDone(const VersionInfo & info)701 void UpdateClient::NotifyCheckVersionDone(const VersionInfo &info)
702 {
703 CLIENT_LOGE("NotifyCheckVersionDone status %d", info.status);
704 CLIENT_LOGE("NotifyCheckVersionDone errMsg %s", info.errMsg.c_str());
705 CLIENT_LOGE("NotifyCheckVersionDone versionName : %s", info.result[0].versionName.c_str());
706 CLIENT_LOGE("NotifyCheckVersionDone versionCode : %s", info.result[0].versionCode.c_str());
707 CLIENT_LOGE("NotifyCheckVersionDone verifyInfo : %s", info.result[0].verifyInfo.c_str());
708 CLIENT_LOGE("NotifyCheckVersionDone size : %zu", info.result[0].size);
709 CLIENT_LOGE("NotifyCheckVersionDone content : %s", info.descriptInfo[0].content.c_str());
710
711 UpdateHelper::CopyVersionInfo(info, versionInfo_);
712 }
713
GetInt32(napi_env env,napi_value arg,const std::string & attrName,int32_t & intValue)714 int32_t UpdateClient::GetInt32(napi_env env, napi_value arg, const std::string &attrName, int32_t &intValue)
715 {
716 bool result = false;
717 napi_status status = napi_has_named_property(env, arg, attrName.c_str(), &result);
718 if (result && (status == napi_ok)) {
719 napi_value value = nullptr;
720 napi_get_named_property(env, arg, attrName.c_str(), &value);
721 napi_get_value_int32(env, value, &intValue);
722 }
723 return CLIENT_SUCCESS;
724 }
725
GetBool(napi_env env,napi_value arg,const std::string & attrName,bool & value)726 int32_t UpdateClient::GetBool(napi_env env, napi_value arg, const std::string &attrName, bool &value)
727 {
728 bool result = false;
729 napi_status status = napi_has_named_property(env, arg, attrName.c_str(), &result);
730 if (result && (status == napi_ok)) {
731 napi_value obj = nullptr;
732 napi_get_named_property(env, arg, attrName.c_str(), &obj);
733 napi_get_value_bool(env, obj, &value);
734 }
735 return CLIENT_SUCCESS;
736 }
737
GetStringValue(napi_env env,napi_value arg,std::string & strValue)738 int32_t UpdateClient::GetStringValue(napi_env env, napi_value arg, std::string &strValue)
739 {
740 napi_valuetype valuetype;
741 napi_status status = napi_typeof(env, arg, &valuetype);
742 CLIENT_CHECK(status == napi_ok, return status, "Failed to napi_typeof");
743 CLIENT_CHECK(valuetype == napi_string, return CLIENT_INVALID_TYPE, "Invalid type");
744 std::vector<char> buff(CLIENT_STRING_MAX_LENGTH);
745 size_t copied;
746 status = napi_get_value_string_utf8(env, arg, (char*)buff.data(), CLIENT_STRING_MAX_LENGTH, &copied);
747 CLIENT_CHECK(status == napi_ok, return CLIENT_INVALID_TYPE, "Error get string");
748 strValue.assign(buff.data(), copied);
749 return napi_ok;
750 }
751
SetString(napi_env env,napi_value arg,const std::string & attrName,const std::string & string)752 int32_t UpdateClient::SetString(napi_env env, napi_value arg, const std::string &attrName, const std::string &string)
753 {
754 napi_value value = nullptr;
755 napi_create_string_utf8(env, string.c_str(), string.length(), &value);
756 napi_set_named_property(env, arg, attrName.c_str(), value);
757 return CLIENT_SUCCESS;
758 }
759
SetInt32(napi_env env,napi_value arg,const std::string & attrName,int32_t intValue)760 int32_t UpdateClient::SetInt32(napi_env env, napi_value arg, const std::string &attrName, int32_t intValue)
761 {
762 napi_value infoStatus = nullptr;
763 napi_create_int32(env, intValue, &infoStatus);
764 napi_set_named_property(env, arg, attrName.c_str(), infoStatus);
765 return CLIENT_SUCCESS;
766 }
767
SetBool(napi_env env,napi_value arg,const std::string & attrName,bool value)768 int32_t UpdateClient::SetBool(napi_env env, napi_value arg, const std::string &attrName, bool value)
769 {
770 napi_value infoStatus = nullptr;
771 napi_create_int32(env, value, &infoStatus);
772 napi_set_named_property(env, arg, attrName.c_str(), infoStatus);
773 return CLIENT_SUCCESS;
774 }
775
SetInt64(napi_env env,napi_value arg,const std::string & attrName,int64_t intValue)776 int32_t UpdateClient::SetInt64(napi_env env, napi_value arg, const std::string &attrName, int64_t intValue)
777 {
778 napi_value infoStatus = nullptr;
779 napi_create_int64(env, intValue, &infoStatus);
780 napi_set_named_property(env, arg, attrName.c_str(), infoStatus);
781 return CLIENT_SUCCESS;
782 }
783
GetUpdatePolicyFromArg(napi_env env,const napi_value arg,UpdatePolicy & updatePolicy) const784 int32_t UpdateClient::GetUpdatePolicyFromArg(napi_env env,
785 const napi_value arg, UpdatePolicy &updatePolicy) const
786 {
787 napi_valuetype type = napi_undefined;
788 napi_status status = napi_typeof(env, arg, &type);
789 CLIENT_CHECK(status == napi_ok, return CLIENT_INVALID_TYPE, "Invlid argc %d", static_cast<int32_t>(status));
790 CLIENT_CHECK(type == napi_object, return CLIENT_INVALID_TYPE, "Invlid argc %d", static_cast<int32_t>(type));
791
792 // updatePolicy
793 int32_t tmpValue = 0;
794 int32_t ret = GetBool(env, arg, "autoDownload", updatePolicy.autoDownload);
795 ret |= GetBool(env, arg, "autoDownloadNet", updatePolicy.autoDownloadNet);
796 ret |= GetInt32(env, arg, "mode", tmpValue);
797 updatePolicy.mode = static_cast<InstallMode>(tmpValue);
798 CLIENT_CHECK(ret == 0, return CLIENT_INVALID_TYPE, "Failed to get attr ");
799
800 // Get the array.
801 bool result = false;
802 status = napi_has_named_property(env, arg, "autoUpgradeInterval", &result);
803 if (result && (status == napi_ok)) {
804 napi_value value;
805 status = napi_get_named_property(env, arg, "autoUpgradeInterval", &value);
806 CLIENT_CHECK(status == napi_ok, return CLIENT_FAIL, "Failed to get attr autoUpgradeInterval");
807 status = napi_is_array(env, value, &result);
808 CLIENT_CHECK(status == napi_ok, return CLIENT_FAIL, "napi_is_array failed");
809 uint32_t count = 0;
810 status = napi_get_array_length(env, value, &count);
811 CLIENT_CHECK(status == napi_ok, return CLIENT_FAIL, "napi_get_array_length failed");
812 uint32_t i = 0;
813 do {
814 napi_value element;
815 ret = napi_get_element(env, value, i, &element);
816 ret = napi_get_value_uint32(env, element, &updatePolicy.autoUpgradeInterval[i]);
817 CLIENT_LOGI("updatePolicy autoUpgradeInterval:%u ", updatePolicy.autoUpgradeInterval[i]);
818 if (i >= sizeof(updatePolicy.autoUpgradeInterval) / sizeof(updatePolicy.autoUpgradeInterval[0])) {
819 break;
820 }
821 i++;
822 } while (i < count);
823 }
824 ret |= GetInt32(env, arg, "autoUpgradeCondition", tmpValue);
825 CLIENT_CHECK(ret == 0, return CLIENT_INVALID_TYPE, "Failed to get attr autoUpgradeCondition");
826 updatePolicy.autoUpgradeCondition = static_cast<AutoUpgradeCondition>(tmpValue);
827 CLIENT_LOGI("updatePolicy autoDownload:%d autoDownloadNet:%d mode:%d autoUpgradeCondition:%d",
828 static_cast<int32_t>(updatePolicy.autoDownload),
829 static_cast<int32_t>(updatePolicy.autoDownloadNet),
830 static_cast<int32_t>(updatePolicy.mode),
831 static_cast<int32_t>(updatePolicy.autoUpgradeCondition));
832 return CLIENT_SUCCESS;
833 }
834
BuildCheckVersionResult(napi_env env,napi_value & obj,const UpdateResult & result)835 int32_t UpdateClient::BuildCheckVersionResult(napi_env env, napi_value &obj, const UpdateResult &result)
836 {
837 CLIENT_CHECK(result.type == SESSION_CHECK_VERSION || result.type == SESSION_GET_NEW_VERSION,
838 return CLIENT_INVALID_TYPE, "invalid type %d", result.type);
839 napi_status status = napi_create_object(env, &obj);
840 CLIENT_CHECK(status == napi_ok, return CLIENT_INVALID_TYPE,
841 "Failed to create napi_create_object %d", static_cast<int32_t>(status));
842 VersionInfo *info = result.result.versionInfo;
843
844 // Add the result.
845 int32_t ret = SetInt32(env, obj, "status", info->status);
846 if (info->status == SERVER_BUSY || info->status == SYSTEM_ERROR) {
847 ret = SetString(env, obj, "errMsg", info->errMsg);
848 return ret;
849 }
850 napi_value checkResults;
851 napi_create_array_with_length(env, sizeof(info->result) / sizeof(info->result[0]), &checkResults);
852 for (size_t i = 0; i < sizeof(info->result) / sizeof(info->result[0]); i++) {
853 napi_value result;
854 status = napi_create_object(env, &result);
855
856 ret |= SetString(env, result, "versionName", info->result[i].versionName);
857 ret |= SetString(env, result, "versionCode", info->result[i].versionCode);
858 ret |= SetString(env, result, "verifyInfo", info->result[i].verifyInfo);
859 ret |= SetString(env, result, "descriptionId", info->result[i].descriptPackageId);
860 ret |= SetInt64(env, result, "size", info->result[i].size);
861 ret |= SetInt32(env, result, "packageType", info->result[i].packageType);
862 napi_set_element(env, checkResults, i, result);
863 }
864 napi_set_named_property(env, obj, "checkResults", checkResults);
865
866 napi_value descriptInfos;
867 napi_create_array_with_length(env, sizeof(info->descriptInfo) / sizeof(info->descriptInfo[0]), &descriptInfos);
868 for (size_t i = 0; i < sizeof(info->descriptInfo) / sizeof(info->descriptInfo[0]); i++) {
869 napi_value descriptInfo;
870 status = napi_create_object(env, &descriptInfo);
871 ret |= SetString(env, descriptInfo, "descriptionId", info->descriptInfo[i].descriptPackageId);
872 ret |= SetString(env, descriptInfo, "content", info->descriptInfo[i].content);
873 napi_set_element(env, descriptInfos, i, descriptInfo);
874 }
875 napi_set_named_property(env, obj, "descriptionInfo", descriptInfos);
876 return CLIENT_SUCCESS;
877 }
878
BuildProgress(napi_env env,napi_value & obj,const UpdateResult & result)879 int32_t UpdateClient::BuildProgress(napi_env env, napi_value &obj, const UpdateResult &result)
880 {
881 napi_status status = napi_create_object(env, &obj);
882 CLIENT_CHECK(status == napi_ok, return CLIENT_INVALID_TYPE,
883 "Failed to create napi_create_object %d", static_cast<int32_t>(status));
884 int32_t ret = SetInt32(env, obj, "status", result.result.progress->status);
885 ret |= SetInt32(env, obj, "percent", result.result.progress->percent);
886 ret |= SetString(env, obj, "endReason", result.result.progress->endReason);
887 return CLIENT_SUCCESS;
888 }
889
BuildErrorResult(napi_env env,napi_value & obj,int32_t result)890 int32_t UpdateClient::BuildErrorResult(napi_env env, napi_value &obj, int32_t result)
891 {
892 napi_status status = napi_create_object(env, &obj);
893 CLIENT_CHECK(status == napi_ok, return CLIENT_INVALID_TYPE,
894 "Failed to create napi_create_object %d", static_cast<int32_t>(status));
895 return SetInt32(env, obj, "code", result);
896 }
897
BuildInt32Status(napi_env env,napi_value & obj,const UpdateResult & result)898 int32_t UpdateClient::BuildInt32Status(napi_env env, napi_value &obj, const UpdateResult &result)
899 {
900 return napi_create_int32(env, result.result.status, &obj);
901 }
902
BuildUpdatePolicy(napi_env env,napi_value & obj,const UpdateResult & result)903 int32_t UpdateClient::BuildUpdatePolicy(napi_env env, napi_value &obj, const UpdateResult &result)
904 {
905 CLIENT_CHECK(result.type == SESSION_GET_POLICY || result.type == SESSION_SET_POLICY,
906 return CLIENT_INVALID_TYPE, "invalid type %d", result.type);
907 napi_status status = napi_create_object(env, &obj);
908 CLIENT_CHECK(status == napi_ok, return status, "Failed to create napi_create_object %d", status);
909 UpdatePolicy &updatePolicy = *result.result.updatePolicy;
910
911 // Add the result.
912 int32_t ret = SetBool(env, obj, "autoDownload", updatePolicy.autoDownload);
913 ret |= SetBool(env, obj, "autoDownloadNet", updatePolicy.autoDownloadNet);
914 ret |= SetInt32(env, obj, "mode", static_cast<int32_t>(updatePolicy.mode));
915 CLIENT_CHECK(ret == napi_ok, return ret, "Failed to add value %d", ret);
916
917 napi_value autoUpgradeInterval;
918 size_t count = sizeof(updatePolicy.autoUpgradeInterval) / sizeof(updatePolicy.autoUpgradeInterval[0]);
919 status = napi_create_array_with_length(env, count, &autoUpgradeInterval);
920 CLIENT_CHECK(status == napi_ok, return status, "Failed to create array for interval %d", status);
921 for (size_t i = 0; i < count; i++) {
922 napi_value interval;
923 status = napi_create_uint32(env, updatePolicy.autoUpgradeInterval[i], &interval);
924 status = napi_set_element(env, autoUpgradeInterval, i, interval);
925 CLIENT_CHECK(status == napi_ok, return status, "Failed to add interval to array %d", status);
926 }
927 status = napi_set_named_property(env, obj, "autoUpgradeInterval", autoUpgradeInterval);
928 CLIENT_CHECK(status == napi_ok, return status, "Failed to add autoUpgradeInterval %d", status);
929 ret |= SetInt32(env, obj, "autoUpgradeCondition", static_cast<int32_t>(updatePolicy.autoUpgradeCondition));
930 CLIENT_CHECK(ret == napi_ok, return ret, "Failed to add autoUpgradeCondition %d", ret);
931 return napi_ok;
932 }
933
GetUpdateResult(int type,UpdateResult & result,int32_t & fail)934 int32_t UpdateClient::GetUpdateResult(int type, UpdateResult &result, int32_t &fail)
935 {
936 fail = 0;
937 result.type = type;
938 switch (type) {
939 case SESSION_CHECK_VERSION:
940 case SESSION_GET_NEW_VERSION: {
941 fail = (versionInfo_.status == SYSTEM_ERROR) ? versionInfo_.status : 0;
942 result.result.versionInfo = &versionInfo_;
943 result.buildJSObject = BuildCheckVersionResult;
944 break;
945 }
946 case SESSION_DOWNLOAD: {
947 fail = (progress_.status == UPDATE_STATE_DOWNLOAD_FAIL || progress_.status == UPDATE_STATE_VERIFY_FAIL) ?
948 progress_.status : 0;
949 result.result.progress = &progress_;
950 result.buildJSObject = BuildProgress;
951 break;
952 }
953 case SESSION_UPGRADE: {
954 fail = (progress_.status == UPDATE_STATE_DOWNLOAD_FAIL) ? progress_.status : 0;
955 result.result.progress = &progress_;
956 result.buildJSObject = BuildProgress;
957 break;
958 }
959 case SESSION_VERIFY_PACKAGE: {
960 fail = (verifyProgress_.status == UPDATE_STATE_VERIFY_FAIL) ? verifyProgress_.status : 0;
961 result.result.progress = &verifyProgress_;
962 result.buildJSObject = BuildProgress;
963 break;
964 }
965 case SESSION_GET_POLICY: {
966 result.result.updatePolicy = &updatePolicy_;
967 result.buildJSObject = BuildUpdatePolicy;
968 break;
969 }
970 case SESSION_GET_STATUS: {
971 result.result.status = upgradeInfo_.status;
972 result.buildJSObject = BuildInt32Status;
973 break;
974 }
975 default:{
976 fail = result_;
977 result.result.status = result_;
978 result.buildJSObject = BuildInt32Status;
979 break;
980 }
981 }
982 return napi_ok;
983 }
984 } // namespace updateClient
985