• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "napi_send_recv_mms.h"
16 
17 #include <chrono>
18 
19 #include "ability.h"
20 #include "napi_base_context.h"
21 #include "napi_mms_pdu.h"
22 #include "napi_mms_pdu_helper.h"
23 #include "sms_constants_utils.h"
24 #include "telephony_permission.h"
25 
26 
27 namespace OHOS {
28 namespace Telephony {
29 namespace {
30 const std::string SMS_PROFILE_URI = "datashare:///com.ohos.smsmmsability";
31 static const int32_t DEFAULT_REF_COUNT = 1;
32 const bool STORE_MMS_PDU_TO_FILE = false;
33 const int32_t ARGS_ONE = 1;
34 std::shared_ptr<DataShare::DataShareHelper> g_datashareHelper = nullptr;
35 constexpr static uint32_t WAIT_PDN_TOGGLE_TIME = 3000;
36 } // namespace
37 std::mutex NapiSendRecvMms::downloadCtx_;
38 std::mutex NapiSendRecvMms::countCtx_;
39 int32_t NapiSendRecvMms::reqCount_ = 0;
40 bool NapiSendRecvMms::waitFlag = false;
41 
GetDataShareHelper(napi_env env,napi_callback_info info)42 std::shared_ptr<OHOS::DataShare::DataShareHelper> GetDataShareHelper(napi_env env, napi_callback_info info)
43 {
44     size_t argc = ARGS_ONE;
45     napi_value argv[ARGS_ONE] = { 0 };
46     napi_value thisVar = nullptr;
47     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
48 
49     std::shared_ptr<DataShare::DataShareHelper> dataShareHelper = nullptr;
50     bool isStageMode = false;
51     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, argv[0], isStageMode);
52     if (status != napi_ok || !isStageMode) {
53         auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
54         if (ability == nullptr) {
55             TELEPHONY_LOGE("Failed to get native ability instance");
56             return nullptr;
57         }
58         auto context = ability->GetContext();
59         if (context == nullptr) {
60             TELEPHONY_LOGE("Failed to get native context instance");
61             return nullptr;
62         }
63         dataShareHelper = DataShare::DataShareHelper::Creator(context->GetToken(), SMS_PROFILE_URI);
64     } else {
65         auto context = OHOS::AbilityRuntime::GetStageModeContext(env, argv[0]);
66         if (context == nullptr) {
67             TELEPHONY_LOGE("Failed to get native stage context instance");
68             return nullptr;
69         }
70         dataShareHelper = DataShare::DataShareHelper::Creator(context->GetToken(), SMS_PROFILE_URI);
71     }
72     return dataShareHelper;
73 }
74 
GetMmsPduFromFile(const std::string & fileName,std::string & mmsPdu)75 bool GetMmsPduFromFile(const std::string &fileName, std::string &mmsPdu)
76 {
77     char realPath[PATH_MAX] = { 0 };
78     if (fileName.empty() || realpath(fileName.c_str(), realPath) == nullptr) {
79         TELEPHONY_LOGE("path or realPath is nullptr");
80         return false;
81     }
82 
83     FILE *pFile = fopen(realPath, "rb");
84     if (pFile == nullptr) {
85         TELEPHONY_LOGE("openFile Error");
86         return false;
87     }
88 
89     (void)fseek(pFile, 0, SEEK_END);
90     long fileLen = ftell(pFile);
91     if (fileLen <= 0 || fileLen > static_cast<long>(MMS_PDU_MAX_SIZE)) {
92         (void)fclose(pFile);
93         TELEPHONY_LOGE("fileLen Over Max Error");
94         return false;
95     }
96 
97     std::unique_ptr<char[]> pduBuffer = std::make_unique<char[]>(fileLen);
98     if (!pduBuffer) {
99         (void)fclose(pFile);
100         TELEPHONY_LOGE("make unique pduBuffer nullptr Error");
101         return false;
102     }
103     (void)fseek(pFile, 0, SEEK_SET);
104     int32_t totolLength = static_cast<int32_t>(fread(pduBuffer.get(), 1, MMS_PDU_MAX_SIZE, pFile));
105     TELEPHONY_LOGI("fread totolLength%{private}d", totolLength);
106 
107     long i = 0;
108     while (i < fileLen) {
109         mmsPdu += pduBuffer[i];
110         i++;
111     }
112     (void)fclose(pFile);
113     return true;
114 }
115 
StoreSendMmsPduToDataBase(NapiMmsPduHelper & helper)116 void StoreSendMmsPduToDataBase(NapiMmsPduHelper &helper) __attribute__((no_sanitize("cfi")))
117 {
118     std::shared_ptr<NAPIMmsPdu> mmsPduObj = std::make_shared<NAPIMmsPdu>();
119     if (mmsPduObj == nullptr) {
120         TELEPHONY_LOGE("mmsPduObj nullptr");
121         helper.NotifyAll();
122         return;
123     }
124     std::string mmsPdu;
125     if (!GetMmsPduFromFile(helper.GetPduFileName(), mmsPdu)) {
126         TELEPHONY_LOGE("get mmsPdu fail");
127         helper.NotifyAll();
128         return;
129     }
130     mmsPduObj->InsertMmsPdu(helper, mmsPdu);
131 }
132 
UpdateTimeStamp(int64_t & timeStamp,MmsContext & context)133 void UpdateTimeStamp(int64_t &timeStamp, MmsContext &context)
134 {
135     context.timeStamp = timeStamp;
136 }
137 
NativeSendMms(napi_env env,void * data)138 void NativeSendMms(napi_env env, void *data)
139 {
140     auto asyncContext = static_cast<MmsContext *>(data);
141     if (asyncContext == nullptr) {
142         TELEPHONY_LOGE("asyncContext nullptr");
143         return;
144     }
145     if (!TelephonyPermission::CheckCallerIsSystemApp()) {
146         TELEPHONY_LOGE("Non-system applications use system APIs!");
147         asyncContext->errorCode = TELEPHONY_ERR_ILLEGAL_USE_OF_SYSTEM_API;
148         return;
149     }
150     if (!STORE_MMS_PDU_TO_FILE) {
151         std::string pduFileName = NapiUtil::ToUtf8(asyncContext->data);
152         if (pduFileName.empty()) {
153             asyncContext->errorCode = TELEPHONY_ERR_ARGUMENT_INVALID;
154             asyncContext->resolved = false;
155             TELEPHONY_LOGE("pduFileName empty");
156             return;
157         }
158         if (g_datashareHelper == nullptr) {
159             asyncContext->errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
160             asyncContext->resolved = false;
161             TELEPHONY_LOGE("g_datashareHelper is nullptr");
162             return;
163         }
164         NapiMmsPduHelper helper;
165         helper.SetDataShareHelper(g_datashareHelper);
166         helper.SetPduFileName(pduFileName);
167         if (!helper.Run(StoreSendMmsPduToDataBase, helper)) {
168             TELEPHONY_LOGE("StoreMmsPdu fail");
169             asyncContext->errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
170             asyncContext->resolved = false;
171             return;
172         }
173         asyncContext->data = NapiUtil::ToUtf16(helper.GetDbUrl());
174     }
175     asyncContext->errorCode =
176         Singleton<SmsServiceManagerClient>::GetInstance().SendMms(asyncContext->slotId, asyncContext->mmsc,
177             asyncContext->data, asyncContext->mmsConfig.userAgent,
178             asyncContext->mmsConfig.userAgentProfile, asyncContext->timeStamp);
179     if (asyncContext->errorCode == TELEPHONY_ERR_SUCCESS) {
180         asyncContext->resolved = true;
181     } else {
182         asyncContext->resolved = false;
183     }
184     TELEPHONY_LOGI("NativeSendMms end resolved = %{public}d", asyncContext->resolved);
185 }
186 
SendMmsCallback(napi_env env,napi_status status,void * data)187 void SendMmsCallback(napi_env env, napi_status status, void *data)
188 {
189     auto context = static_cast<MmsContext *>(data);
190     if (context == nullptr) {
191         TELEPHONY_LOGE("SendMmsCallback context nullptr");
192         return;
193     }
194     napi_value callbackValue = nullptr;
195     if (context->resolved) {
196         napi_get_undefined(env, &callbackValue);
197     } else {
198         JsError error = NapiUtil::ConverErrorMessageWithPermissionForJs(
199             context->errorCode, "sendMms", "ohos.permission.SEND_MESSAGES");
200         callbackValue = NapiUtil::CreateErrorMessage(env, error.errorMessage, error.errorCode);
201     }
202     NapiUtil::Handle1ValueCallback(env, context, callbackValue);
203 }
204 
MatchMmsParameters(napi_env env,napi_value parameters[],size_t parameterCount)205 bool MatchMmsParameters(napi_env env, napi_value parameters[], size_t parameterCount)
206 {
207     bool typeMatch = false;
208     switch (parameterCount) {
209         case TWO_PARAMETERS: {
210             typeMatch = NapiUtil::MatchParameters(env, parameters, { napi_object, napi_object });
211             break;
212         }
213         case THREE_PARAMETERS: {
214             typeMatch = NapiUtil::MatchParameters(env, parameters, { napi_object, napi_object, napi_function });
215             break;
216         }
217         default: {
218             break;
219         }
220     }
221     if (typeMatch) {
222         return NapiUtil::MatchObjectProperty(env, parameters[1],
223             {
224                 { "slotId", napi_number },
225                 { "mmsc", napi_string },
226                 { "data", napi_string },
227                 { "mmsConfig", napi_object },
228             });
229     }
230     return false;
231 }
232 
GetMmsValueLength(napi_env env,napi_value param)233 static bool GetMmsValueLength(napi_env env, napi_value param)
234 {
235     size_t len = 0;
236     napi_status status = napi_get_value_string_utf8(env, param, nullptr, 0, &len);
237     if (status != napi_ok) {
238         TELEPHONY_LOGE("Get length failed");
239         return false;
240     }
241     return (len > 0) && (len < BUFF_LENGTH);
242 }
243 
GetMmsNameProperty(napi_env env,napi_value param,MmsContext & context)244 static void GetMmsNameProperty(napi_env env, napi_value param, MmsContext &context)
245 {
246     napi_value slotIdValue = NapiUtil::GetNamedProperty(env, param, "slotId");
247     if (slotIdValue != nullptr) {
248         napi_get_value_int32(env, slotIdValue, &(context.slotId));
249     }
250     napi_value mmscValue = NapiUtil::GetNamedProperty(env, param, "mmsc");
251     if (mmscValue != nullptr && GetMmsValueLength(env, mmscValue)) {
252         char strChars[NORMAL_STRING_SIZE] = { 0 };
253         size_t strLength = 0;
254         napi_get_value_string_utf8(env, mmscValue, strChars, BUFF_LENGTH, &strLength);
255         std::string str8(strChars, strLength);
256         context.mmsc = NapiUtil::ToUtf16(str8);
257     }
258     napi_value dataValue = NapiUtil::GetNamedProperty(env, param, "data");
259     if (dataValue != nullptr && GetMmsValueLength(env, dataValue)) {
260         char strChars[NORMAL_STRING_SIZE] = { 0 };
261         size_t strLength = 0;
262         napi_get_value_string_utf8(env, dataValue, strChars, BUFF_LENGTH, &strLength);
263         std::string str8(strChars, strLength);
264         context.data = NapiUtil::ToUtf16(str8);
265     }
266     napi_value configValue = NapiUtil::GetNamedProperty(env, param, "mmsConfig");
267     if (configValue != nullptr) {
268         napi_value uaValue = NapiUtil::GetNamedProperty(env, configValue, "userAgent");
269         if (uaValue != nullptr && GetMmsValueLength(env, uaValue)) {
270             char strChars[NORMAL_STRING_SIZE] = { 0 };
271             size_t strLength = 0;
272             napi_get_value_string_utf8(env, uaValue, strChars, BUFF_LENGTH, &strLength);
273             std::string str8(strChars, strLength);
274             context.mmsConfig.userAgent = NapiUtil::ToUtf16(str8);
275         }
276         napi_value uaprofValue = NapiUtil::GetNamedProperty(env, configValue, "userAgentProfile");
277         if (uaprofValue != nullptr && GetMmsValueLength(env, uaprofValue)) {
278             char strChars[NORMAL_STRING_SIZE] = { 0 };
279             size_t strLength = 0;
280             napi_get_value_string_utf8(env, uaprofValue, strChars, BUFF_LENGTH, &strLength);
281             std::string str8(strChars, strLength);
282             context.mmsConfig.userAgentProfile = NapiUtil::ToUtf16(str8);
283         }
284     }
285 }
286 
SendMms(napi_env env,napi_callback_info info)287 napi_value NapiSendRecvMms::SendMms(napi_env env, napi_callback_info info)
288 {
289     size_t parameterCount = THREE_PARAMETERS;
290     napi_value parameters[THREE_PARAMETERS] = { 0 };
291     napi_value thisVar = nullptr;
292     void *data = nullptr;
293     int64_t timeStamp =
294         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
295             .count();
296     napi_get_cb_info(env, info, &parameterCount, parameters, &thisVar, &data);
297     if (!MatchMmsParameters(env, parameters, parameterCount)) {
298         TELEPHONY_LOGE("parameter matching failed.");
299         NapiUtil::ThrowParameterError(env);
300         return nullptr;
301     }
302     auto context = std::make_unique<MmsContext>().release();
303     if (context == nullptr) {
304         TELEPHONY_LOGE("MmsContext is nullptr.");
305         NapiUtil::ThrowParameterError(env);
306         return nullptr;
307     }
308     if (!STORE_MMS_PDU_TO_FILE) {
309         g_datashareHelper = GetDataShareHelper(env, info);
310     }
311     GetMmsNameProperty(env, parameters[1], *context);
312     if (parameterCount == THREE_PARAMETERS) {
313         napi_create_reference(env, parameters[PARAMETERS_INDEX_TWO], DEFAULT_REF_COUNT, &context->callbackRef);
314     }
315     UpdateTimeStamp(timeStamp, *context);
316     napi_value result = NapiUtil::HandleAsyncWork(env, context, "SendMms", NativeSendMms, SendMmsCallback);
317     return result;
318 }
319 
WriteBufferToFile(const std::unique_ptr<char[]> & buff,uint32_t len,const std::string & strPathName)320 bool WriteBufferToFile(const std::unique_ptr<char[]> &buff, uint32_t len, const std::string &strPathName)
321 {
322     if (buff == nullptr) {
323         TELEPHONY_LOGE("buff nullptr");
324         return false;
325     }
326 
327     char realPath[PATH_MAX] = { 0 };
328     if (strPathName.empty() || realpath(strPathName.c_str(), realPath) == nullptr) {
329         TELEPHONY_LOGE("path or realPath is nullptr");
330         return false;
331     }
332 
333     FILE *pFile = fopen(realPath, "wb");
334     if (pFile == nullptr) {
335         TELEPHONY_LOGE("openFile Error");
336         return false;
337     }
338     uint32_t fileLen = fwrite(buff.get(), len, 1, pFile);
339     (void)fclose(pFile);
340     if (fileLen > 0) {
341         TELEPHONY_LOGI("write mms buffer to file success");
342         return true;
343     } else {
344         TELEPHONY_LOGI("write mms buffer to file error");
345         return false;
346     }
347 }
348 
StoreMmsPduToFile(const std::string & fileName,const std::string & mmsPdu)349 bool StoreMmsPduToFile(const std::string &fileName, const std::string &mmsPdu)
350 {
351     uint32_t len = static_cast<uint32_t>(mmsPdu.size());
352     if (len > MMS_PDU_MAX_SIZE || len == 0) {
353         TELEPHONY_LOGE("MMS pdu length invalid");
354         return false;
355     }
356 
357     std::unique_ptr<char[]> resultResponse = std::make_unique<char[]>(len);
358     if (memset_s(resultResponse.get(), len, 0x00, len) != EOK) {
359         TELEPHONY_LOGE("memset_s err");
360         return false;
361     }
362     if (memcpy_s(resultResponse.get(), len, &mmsPdu[0], len) != EOK) {
363         TELEPHONY_LOGE("memcpy_s error");
364         return false;
365     }
366 
367     TELEPHONY_LOGI("len:%{public}d", len);
368     if (!WriteBufferToFile(std::move(resultResponse), len, fileName)) {
369         TELEPHONY_LOGE("write to file error");
370         return false;
371     }
372     return true;
373 }
374 
GetMmsPduFromDataBase(NapiMmsPduHelper & helper)375 void GetMmsPduFromDataBase(NapiMmsPduHelper &helper) __attribute__((no_sanitize("cfi")))
376 {
377     NAPIMmsPdu mmsPduObj;
378     std::string mmsPdu = mmsPduObj.GetMmsPdu(helper);
379     if (mmsPdu.empty()) {
380         TELEPHONY_LOGE("from dataBase empty");
381         return;
382     }
383 
384     mmsPduObj.DeleteMmsPdu(helper);
385     if (!StoreMmsPduToFile(helper.GetStoreFileName(), mmsPdu)) {
386         TELEPHONY_LOGE("store mmsPdu fail");
387     }
388     helper.NotifyAll();
389 }
390 
DownloadExceptionCase(MmsContext & context,std::shared_ptr<OHOS::DataShare::DataShareHelper> g_datashareHelper)391 static bool DownloadExceptionCase(
392     MmsContext &context, std::shared_ptr<OHOS::DataShare::DataShareHelper> g_datashareHelper)
393 {
394     if (!TelephonyPermission::CheckCallerIsSystemApp()) {
395         TELEPHONY_LOGE("Non-system applications use system APIs!");
396         context.errorCode = TELEPHONY_ERR_ILLEGAL_USE_OF_SYSTEM_API;
397         context.resolved = false;
398         return false;
399     }
400     if (g_datashareHelper == nullptr) {
401         TELEPHONY_LOGE("g_datashareHelper is nullptr");
402         context.errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
403         context.resolved = false;
404         return false;
405     }
406     std::string fileName = NapiUtil::ToUtf8(context.data);
407     char realPath[PATH_MAX] = { 0 };
408     if (fileName.empty() || realpath(fileName.c_str(), realPath) == nullptr) {
409         TELEPHONY_LOGE("path or realPath is nullptr");
410         context.errorCode = TELEPHONY_ERR_ARGUMENT_INVALID;
411         context.resolved = false;
412         return false;
413     }
414     FILE *pFile = fopen(realPath, "wb");
415     if (pFile == nullptr) {
416         TELEPHONY_LOGE("openFile Error");
417         context.errorCode = TELEPHONY_ERR_ARGUMENT_INVALID;
418         context.resolved = false;
419         return false;
420     }
421     (void)fclose(pFile);
422     return true;
423 }
424 
UpdateReqCount()425 void UpdateReqCount()
426 {
427     std::unique_lock<std::mutex> lck(NapiSendRecvMms::countCtx_);
428     NapiSendRecvMms::reqCount_++;
429     TELEPHONY_LOGI("reqCount_:%{public}d", NapiSendRecvMms::reqCount_);
430 }
431 
DecreaseReqCount()432 void DecreaseReqCount()
433 {
434     NapiSendRecvMms::reqCount_--;
435     if (NapiSendRecvMms::reqCount_ > 0) {
436         NapiSendRecvMms::waitFlag = true;
437     } else {
438         NapiSendRecvMms::waitFlag = false;
439     }
440 }
441 
NativeDownloadMms(napi_env env,void * data)442 void NativeDownloadMms(napi_env env, void *data)
443 {
444     auto asyncContext = static_cast<MmsContext *>(data);
445     if (asyncContext == nullptr) {
446         TELEPHONY_LOGE("asyncContext nullptr");
447         return;
448     }
449     if (!DownloadExceptionCase(*asyncContext, g_datashareHelper)) {
450         TELEPHONY_LOGE("Exception case");
451         return;
452     }
453 
454     TELEPHONY_LOGI("native download mms");
455     UpdateReqCount();
456     std::unique_lock<std::mutex> lck(NapiSendRecvMms::downloadCtx_);
457     if (NapiSendRecvMms::waitFlag) {
458         TELEPHONY_LOGI("down multiple mms at once wait");
459         std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_PDN_TOGGLE_TIME));
460     }
461     std::u16string dbUrls;
462     asyncContext->errorCode =
463         Singleton<SmsServiceManagerClient>::GetInstance().DownloadMms(asyncContext->slotId, asyncContext->mmsc,
464             dbUrls, asyncContext->mmsConfig.userAgent, asyncContext->mmsConfig.userAgentProfile);
465     TELEPHONY_LOGI("NativeDownloadMms dbUrls:%{public}s", NapiUtil::ToUtf8(dbUrls).c_str());
466     if (asyncContext->errorCode == TELEPHONY_ERR_SUCCESS) {
467         asyncContext->resolved = true;
468         if (!STORE_MMS_PDU_TO_FILE) {
469             NapiMmsPduHelper helper;
470             helper.SetDataShareHelper(g_datashareHelper);
471             helper.SetDbUrl(NapiUtil::ToUtf8(dbUrls));
472             helper.SetStoreFileName(NapiUtil::ToUtf8(asyncContext->data));
473             if (!helper.Run(GetMmsPduFromDataBase, helper)) {
474                 TELEPHONY_LOGE("StoreMmsPdu fail");
475                 asyncContext->errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
476                 asyncContext->resolved = false;
477                 return;
478             }
479         }
480     } else {
481         asyncContext->resolved = false;
482     }
483     DecreaseReqCount();
484     TELEPHONY_LOGI("NativeDownloadMms end resolved = %{public}d", asyncContext->resolved);
485 }
486 
DownloadMmsCallback(napi_env env,napi_status status,void * data)487 void DownloadMmsCallback(napi_env env, napi_status status, void *data)
488 {
489     auto context = static_cast<MmsContext *>(data);
490     if (context == nullptr) {
491         TELEPHONY_LOGE("SendMmsCallback context nullptr");
492         return;
493     }
494     napi_value callbackValue = nullptr;
495     if (context->resolved) {
496         napi_get_undefined(env, &callbackValue);
497     } else {
498         JsError error = NapiUtil::ConverErrorMessageWithPermissionForJs(
499             context->errorCode, "downloadMms", "ohos.permission.RECEIVE_MMS");
500         callbackValue = NapiUtil::CreateErrorMessage(env, error.errorMessage, error.errorCode);
501     }
502     NapiUtil::Handle1ValueCallback(env, context, callbackValue);
503 }
504 
DownloadMms(napi_env env,napi_callback_info info)505 napi_value NapiSendRecvMms::DownloadMms(napi_env env, napi_callback_info info)
506 {
507     size_t parameterCount = THREE_PARAMETERS;
508     napi_value parameters[THREE_PARAMETERS] = { 0 };
509     napi_value thisVar = nullptr;
510     void *data = nullptr;
511 
512     napi_get_cb_info(env, info, &parameterCount, parameters, &thisVar, &data);
513     if (!MatchMmsParameters(env, parameters, parameterCount)) {
514         TELEPHONY_LOGE("DownloadMms parameter matching failed.");
515         NapiUtil::ThrowParameterError(env);
516         return nullptr;
517     }
518     auto context = std::make_unique<MmsContext>().release();
519     if (context == nullptr) {
520         TELEPHONY_LOGE("DownloadMms MmsContext is nullptr.");
521         NapiUtil::ThrowParameterError(env);
522         return nullptr;
523     }
524     if (!STORE_MMS_PDU_TO_FILE) {
525         g_datashareHelper = GetDataShareHelper(env, info);
526     }
527     GetMmsNameProperty(env, parameters[1], *context);
528     if (parameterCount == THREE_PARAMETERS) {
529         napi_create_reference(env, parameters[PARAMETERS_INDEX_TWO], DEFAULT_REF_COUNT, &context->callbackRef);
530     }
531     napi_value result = NapiUtil::HandleAsyncWork(env, context, "DownloadMms", NativeDownloadMms, DownloadMmsCallback);
532     return result;
533 }
534 } // namespace Telephony
535 } // namespace OHOS
536