diff --git a/interfaces/kits/ani/webview/ets/@ohos.web.webview.ets b/interfaces/kits/ani/webview/ets/@ohos.web.webview.ets index e16beab36e3e92e9bad96581f8f28145ab85b9ea..02a507674e4fb46e007aaf9e46904122e64b03c9 100644 --- a/interfaces/kits/ani/webview/ets/@ohos.web.webview.ets +++ b/interfaces/kits/ani/webview/ets/@ohos.web.webview.ets @@ -703,6 +703,14 @@ export default namespace webview { } return this.precompileJavaScriptInternal(url,resScript,cacheOptions); } + native storeWebArchiveCallback(baseName: string, autoName: boolean, callback: AsyncCallback): void; + storeWebArchive(baseName: string, autoName: boolean, callback: AsyncCallback): void { + this.storeWebArchiveCallback(baseName, autoName, callback); + } + native storeWebArchivePromise(baseName: string, autoName: boolean): Promise; + storeWebArchive(baseName: string, autoName: boolean): Promise { + return this.storeWebArchivePromise(baseName, autoName); + } } export class WebSchemeHandlerResponse { diff --git a/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.cpp b/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.cpp index 62120c98bed6989b4db650dea1191bcef2a2df0a..17071231e52e88525a6b693fe24be06de2aeaecb 100644 --- a/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.cpp +++ b/interfaces/kits/ani/webview/src/webviewcontroller/ani_webview_controller.cpp @@ -51,6 +51,7 @@ #include "nweb_precompile_callback.h" #include "nweb_cache_options_impl.h" +#include "nweb_store_web_archive_callback.h" #include "bundle_mgr_proxy.h" #include "if_system_ability_manager.h" @@ -4546,6 +4547,157 @@ ani_status StsPrintDocumentAdapterInit(ani_env* env) } +static void StoreWebArchiveCallbackInternal( + ani_env* env, std::string baseNameStr, bool autoNameStr, ani_ref jsCallback, int32_t nwebId) +{ + if (!env) { + return; + } + if (jsCallback == nullptr) { + return; + } + auto nweb_ptr = NWebHelper::Instance().GetNWeb(nwebId); + if (!nweb_ptr) { + std::vector resultRef; + ani_ref tmp = NWebError::AniBusinessError::CreateError(env, INVALID_RESOURCE); + resultRef.push_back(tmp); + env->GetNull(&tmp); + resultRef.push_back(tmp); + ani_ref fnReturnVal; + env->FunctionalObject_Call( + static_cast(jsCallback), resultRef.size(), resultRef.data(), &fnReturnVal); + env->GlobalReference_Delete(jsCallback); + return; + } + + auto callbackImpl = std::make_shared(); + callbackImpl->SetCallBack([env, jCallback = std::move(jsCallback)](std::string result) { + if (!env) { + return; + } + std::vector resultRef; + if (!result.empty()) { + ani_ref tmp; + env->GetNull(&tmp); + ani_string str {}; + env->String_NewUTF8(result.c_str(), result.size(), &str); + resultRef.push_back(tmp); + resultRef.push_back(str); + } else { + ani_ref tmp = NWebError::AniBusinessError::CreateError(env, INVALID_RESOURCE); + resultRef.push_back(tmp); + env->GetNull(&tmp); + resultRef.push_back(tmp); + } + ani_ref fnReturnVal; + env->FunctionalObject_Call( + static_cast(jCallback), resultRef.size(), resultRef.data(), &fnReturnVal); + env->GlobalReference_Delete(jCallback); + }); + nweb_ptr->StoreWebArchive(baseNameStr, autoNameStr, callbackImpl); +} + +static void StoreWebArchiveCallback( + ani_env* env, ani_object object, ani_string baseName, ani_boolean autoName, ani_fn_object callbackObj) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return; + } + ani_boolean isUndefined = ANI_TRUE; + if (env->Reference_IsUndefined(baseName, &isUndefined) != ANI_OK || isUndefined == ANI_TRUE) { + WVLOG_E("baseName is undefined"); + return; + } + std::string baseNameStr; + if (!AniParseUtils::ParseString(env, baseName, baseNameStr)) { + WVLOG_E("Parse baseName failed"); + AniBusinessError::ThrowError(env, NWebError::PARAM_CHECK_ERROR, + NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "baseName", "string")); + return; + } + bool autoNameStr = static_cast(autoName); + + auto* controller = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!controller) { + WVLOG_E("controller is null"); + return; + } + int32_t webId = controller->GetWebId(); + + ani_ref jsCallback = nullptr; + env->GlobalReference_Create(callbackObj, &jsCallback); + return StoreWebArchiveCallbackInternal(env, baseNameStr, autoNameStr, jsCallback, webId); +} + +static void StoreWebArchivePromiseInternal( + ani_env* env, std::string baseNameStr, bool autoNameStr, ani_resolver deferred, int32_t nwebId) +{ + if (!env) { + return; + } + if (deferred == nullptr) { + return; + } + auto nweb_ptr = NWebHelper::Instance().GetNWeb(nwebId); + if (!nweb_ptr) { + WVLOG_E("nweb_ptr is nullptr"); + ani_ref jsResult = nullptr; + jsResult = NWebError::AniBusinessError::CreateError(env, INIT_ERROR); + env->PromiseResolver_Reject(deferred, reinterpret_cast(jsResult)); + return; + } + + auto callbackImpl = std::make_shared(); + callbackImpl->SetCallBack([env, deferred](std::string result) { + if (!env) { + return; + } + std::vector resultRef(RESULT_COUNT); + resultRef[0] = NWebError::AniBusinessError::CreateError(env, INVALID_RESOURCE); + ani_string str {}; + env->String_NewUTF8(result.c_str(), result.size(), &str); + resultRef[1] = static_cast(str); + if (!result.empty()) { + env->PromiseResolver_Resolve(deferred, resultRef[1]); + } else { + env->PromiseResolver_Reject(deferred, reinterpret_cast(resultRef[0])); + } + }); + nweb_ptr->StoreWebArchive(baseNameStr, autoNameStr, callbackImpl); +} + +static ani_object StoreWebArchivePromise(ani_env* env, ani_object object, ani_string baseName, ani_boolean autoName) +{ + if (env == nullptr) { + WVLOG_E("env is nullptr"); + return nullptr; + } + ani_boolean isUndefined = ANI_TRUE; + if (env->Reference_IsUndefined(baseName, &isUndefined) != ANI_OK || isUndefined == ANI_TRUE) { + WVLOG_E("baseName is undefined"); + return nullptr; + } + std::string baseNameStr; + if (!AniParseUtils::ParseString(env, baseName, baseNameStr)) { + WVLOG_E("Parse baseName failed"); + AniBusinessError::ThrowError(env, NWebError::PARAM_CHECK_ERROR, + NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "baseName", "string")); + return nullptr; + } + bool autoNameStr = static_cast(autoName); + auto* controller = reinterpret_cast(AniParseUtils::Unwrap(env, object)); + if (!controller) { + WVLOG_E("controller is null"); + return nullptr; + } + int32_t webId = controller->GetWebId(); + ani_object promise; + ani_resolver deferred; + env->Promise_New(&deferred, &promise); + StoreWebArchivePromiseInternal(env, baseNameStr, autoNameStr, deferred, webId); + return promise; +} ani_status StsWebviewControllerInit(ani_env *env) { WVLOG_D("[DOWNLOAD] StsWebviewControllerInit"); @@ -4679,6 +4831,8 @@ ani_status StsWebviewControllerInit(ani_env *env) ani_native_function { "getMediaPlaybackState", nullptr, reinterpret_cast(GetMediaPlaybackState) }, ani_native_function { "webPageSnapshot", nullptr, reinterpret_cast(WebPageSnapshot) }, ani_native_function { "innerCompleteWindowNew", nullptr, reinterpret_cast(InnerCompleteWindowNew) }, + ani_native_function { "storeWebArchiveCallback", nullptr, reinterpret_cast(StoreWebArchiveCallback) }, + ani_native_function { "storeWebArchivePromise", nullptr, reinterpret_cast(StoreWebArchivePromise) }, }; status = env->Class_BindNativeMethods(webviewControllerCls, controllerMethods.data(), controllerMethods.size());