• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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