1 /*
2  * Copyright (c) 2024 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 "cj_web_ffi.h"
17 
18 #include "application_context.h"
19 #include "cj_lambda.h"
20 #include "webview_controller_impl.h"
21 
22 #include "base/log/ace_scoring_log.h"
23 #include "base/memory/ace_type.h"
24 #include "base/memory/referenced.h"
25 #include "base/utils/utils.h"
26 #include "base/web/webview/ohos_nweb/include/nweb.h"
27 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
28 #include "core/common/container.h"
29 #include "core/common/container_scope.h"
30 #include "core/components/web/web_event.h"
31 #include "core/components_ng/pattern/web/web_model_ng.h"
32 #include "core/pipeline/pipeline_base.h"
33 
34 using namespace OHOS::Ace;
35 using namespace OHOS::FFI;
36 using namespace OHOS::Ace::Framework;
37 using namespace OHOS::Webview;
38 
39 struct FfiWebEvent {
40     const char* url;
41     const char* message;
42     const char* value;
43     RefPtr<Result>* result;
44 };
45 
46 namespace OHOS::Ace::Framework {
47 bool g_cjWebDebuggingAccess = false;
48 constexpr int32_t PARENT_FIRST_VALUE = 2;
49 RequestResultCallback g_requestResultcb = nullptr;
50 
51 class CJWebWindowNewHandler : public Referenced {
52 public:
53     struct ChildWindowInfo {
54         int32_t parentWebId_ = -1;
55         WebviewControllerImpl* controller_;
56     };
57 
SetEvent(const WebWindowNewEvent & eventInfo)58     void SetEvent(const WebWindowNewEvent& eventInfo)
59     {
60         handler_ = eventInfo.GetWebWindowNewHandler();
61     }
62 
PopupController(int32_t id,int32_t * parentId=nullptr)63     static WebviewControllerImpl* PopupController(int32_t id, int32_t* parentId = nullptr)
64     {
65         auto iter = controller_map_.find(id);
66         if (iter == controller_map_.end()) {
67             return nullptr;
68         }
69         auto controller = iter->second.controller_;
70         if (parentId) {
71             *parentId = iter->second.parentWebId_;
72         }
73         controller_map_.erase(iter);
74         return controller;
75     }
76 
ExistController(WebviewControllerImpl * controller,int32_t & parentWebId)77     static bool ExistController(WebviewControllerImpl* controller, int32_t& parentWebId)
78     {
79         if (controller == nullptr) {
80             parentWebId = -1;
81             return false;
82         }
83 
84         auto webId1 = controller->GetWebId();
85         for (auto iter = controller_map_.begin(); iter != controller_map_.end(); iter++) {
86             auto webId2 = iter->second.controller_->GetWebId();
87             if (webId1 == webId2) {
88                 parentWebId = iter->second.parentWebId_;
89                 return true;
90             }
91         }
92 
93         parentWebId = -1;
94         return false;
95     }
96 
SetWebController(WebviewControllerImpl * controller)97     void SetWebController(WebviewControllerImpl* controller)
98     {
99         if (handler_) {
100             int32_t parentNWebId = handler_->GetParentNWebId();
101             if (parentNWebId == -1) {
102                 return;
103             }
104             if (controller == nullptr) {
105                 WebModel::GetInstance()->NotifyPopupWindowResult(parentNWebId, false);
106                 return;
107             }
108 
109             auto childWebId = controller->GetWebId();
110             if (childWebId == parentNWebId || childWebId != -1) {
111                 WebModel::GetInstance()->NotifyPopupWindowResult(parentNWebId, false);
112                 return;
113             }
114             controller_map_.insert(
115                 std::pair<int32_t, ChildWindowInfo>(handler_->GetId(), { parentNWebId, controller }));
116         }
117     }
118 
119 private:
120     RefPtr<WebWindowNewHandler> handler_;
121     static std::unordered_map<int32_t, ChildWindowInfo> controller_map_;
122 };
123 
124 class __attribute__((visibility("default"))) CJWebPermissionRequest : public Referenced {
125 public:
SetEvent(const Ace::WebPermissionRequestEvent & eventInfo)126     void SetEvent(const Ace::WebPermissionRequestEvent& eventInfo)
127     {
128         webPermissionRequest_ = eventInfo.GetWebPermissionRequest();
129     }
130 
Deny()131     void Deny()
132     {
133         if (webPermissionRequest_) {
134             webPermissionRequest_->Deny();
135         }
136     }
137 
GetOrigin()138     std::string GetOrigin()
139     {
140         std::string origin;
141         if (webPermissionRequest_) {
142             origin = webPermissionRequest_->GetOrigin();
143         }
144         return origin;
145     }
146 
GetAccessibleResources()147     std::vector<std::string> GetAccessibleResources()
148     {
149         std::vector<std::string> resources;
150         if (webPermissionRequest_) {
151             resources = webPermissionRequest_->GetResources();
152         }
153         return resources;
154     }
155 
Grant(std::vector<std::string> & args)156     void Grant(std::vector<std::string>& args)
157     {
158         if (args.size() < 1) {
159             if (webPermissionRequest_) {
160                 webPermissionRequest_->Deny();
161             }
162         }
163         std::vector<std::string> resources;
164         for (size_t i = 0; i < args.size(); i++) {
165             resources.push_back(args[i]);
166         }
167         if (webPermissionRequest_) {
168             webPermissionRequest_->Grant(resources);
169         }
170     }
171 
172 private:
Construct()173     static CJWebPermissionRequest* Construct()
174     {
175         auto cjWebPermissionrequest = Ace::Referenced::MakeRefPtr<CJWebPermissionRequest>();
176         cjWebPermissionrequest->IncRefCount();
177         return Ace::Referenced::RawPtr(cjWebPermissionrequest);
178     }
179 
Destructor(CJWebPermissionRequest * cjWebPermissionRequest)180     static void Destructor(CJWebPermissionRequest* cjWebPermissionRequest)
181     {
182         if (cjWebPermissionRequest != nullptr) {
183             cjWebPermissionRequest->DecRefCount();
184         }
185     }
186     Ace::RefPtr<Ace::WebPermissionRequest> webPermissionRequest_;
187 };
188 
MallocCString(const std::string & origin)189 char* MallocCString(const std::string& origin)
190 {
191     auto len = origin.length() + 1;
192     char* res = static_cast<char*>(malloc(sizeof(char) * len));
193     if (res == nullptr) {
194         return nullptr;
195     }
196     return std::char_traits<char>::copy(res, origin.c_str(), len);
197 }
198 
RequestPermissionsFromUserWeb(CJWebPermissionRequest & request)199 void RequestPermissionsFromUserWeb(CJWebPermissionRequest& request)
200 {
201     auto abilityContext = AbilityRuntime::Context::GetApplicationContext();
202     std::string permission = "ohos.permission.READ_PASTEBOARD";
203     char* cPermission = MallocCString(permission);
204 
205     if (cPermission == nullptr) {
206         return;
207     }
208     auto callBack = [&request](RetDataCPermissionRequestResult infoRef) -> void {
209         if (infoRef.code == 0) {
210             request.GetAccessibleResources();
211         } else {
212             request.Deny();
213         }
214     };
215 
216     std::function<void(RetDataCPermissionRequestResult)> func = callBack;
217     g_requestResultcb(abilityContext.get(), CArrString { .head = &cPermission, .size = 1 }, &func);
218 
219     free(cPermission);
220 }
221 } // namespace OHOS::Ace::Framework
222 std::unordered_map<int32_t, CJWebWindowNewHandler::ChildWindowInfo> CJWebWindowNewHandler::controller_map_;
223 extern "C" {
FfiOHOSAceFrameworkWebSetCallback(RequestResultCallback cb)224 void FfiOHOSAceFrameworkWebSetCallback(RequestResultCallback cb)
225 {
226     if (g_requestResultcb == nullptr) {
227         g_requestResultcb = cb;
228     }
229 }
230 
FfiOHOSAceFrameworkWebCreate(const char * src,int64_t controllerId,int32_t type,bool mode)231 void FfiOHOSAceFrameworkWebCreate(const char* src, int64_t controllerId, int32_t type, bool mode)
232 {
233     RenderMode renderMode = RenderMode::ASYNC_RENDER;
234     renderMode = static_cast<RenderMode>(type);
235 
236     auto controller = FFIData::GetData<WebviewControllerImpl>(controllerId);
237     if (controller) {
238         auto setIdCallback = [controller](int32_t webId) { controller->SetWebId(webId); };
239         std::function<void(const std::string&)> setHapPathCallback = nullptr;
240         setHapPathCallback = [controller](const std::string& hapPath) { controller->InnerSetHapPath(hapPath); };
241 
242         std::function<void(const std::shared_ptr<BaseEventInfo>&)> requestPermissionsFromUserCallback = nullptr;
243         requestPermissionsFromUserCallback = [controller](const std::shared_ptr<BaseEventInfo>& info) {
244             auto* eventInfo = TypeInfoHelper::DynamicCast<WebPermissionRequestEvent>(info.get());
245             auto permissionObj = OHOS::Ace::Framework::CJWebPermissionRequest();
246             permissionObj.SetEvent(*eventInfo);
247             OHOS::Ace::Framework::RequestPermissionsFromUserWeb(permissionObj);
248         };
249 
250         int32_t parentNWebId = -1;
251         bool isPopup = CJWebWindowNewHandler::ExistController(controller, parentNWebId);
252         WebModel::GetInstance()->Create(src, std::move(setIdCallback), std::move(setHapPathCallback),
253             parentNWebId, isPopup, renderMode, mode);
254         WebModel::GetInstance()->SetPermissionClipboard(std::move(requestPermissionsFromUserCallback));
255         if (!controller->customeSchemeCmdLine_.empty()) {
256             WebModel::GetInstance()->SetCustomScheme(controller->customeSchemeCmdLine_);
257         }
258         if (controller->webDebuggingAccess_ == g_cjWebDebuggingAccess) {
259             return;
260         }
261         WebModel::GetInstance()->SetWebDebuggingAccessEnabled(controller->webDebuggingAccess_);
262         g_cjWebDebuggingAccess = controller->webDebuggingAccess_;
263         return;
264     } else {
265         LOGI("Web controller init failed");
266     }
267     WebModel::GetInstance()->SetFocusable(true);
268     WebModel::GetInstance()->SetFocusNode(true);
269 }
270 
FfiOHOSAceFrameworkWebHandleCancel(void * result)271 void FfiOHOSAceFrameworkWebHandleCancel(void* result)
272 {
273     auto res = *reinterpret_cast<RefPtr<Result>*>(result);
274     res->Cancel();
275     FfiOHOSAceFrameworkWebReleaseResult(result);
276 }
277 
FfiOHOSAceFrameworkWebHandleConfirm(void * result)278 void FfiOHOSAceFrameworkWebHandleConfirm(void* result)
279 {
280     auto res = *reinterpret_cast<RefPtr<Result>*>(result);
281     res->Confirm();
282     FfiOHOSAceFrameworkWebReleaseResult(result);
283 }
284 
FfiOHOSAceFrameworkWebHandlePromptConfirm(void * result,const char * message)285 void FfiOHOSAceFrameworkWebHandlePromptConfirm(void* result, const char* message)
286 {
287     auto res = *reinterpret_cast<RefPtr<Result>*>(result);
288     res->Confirm(message);
289     FfiOHOSAceFrameworkWebReleaseResult(result);
290 }
291 
FfiOHOSAceFrameworkWebReleaseResult(void * result)292 void FfiOHOSAceFrameworkWebReleaseResult(void* result)
293 {
294     if (result != nullptr) {
295         RefPtr<Result>* res = reinterpret_cast<RefPtr<Result>*>(result);
296         delete res;
297     }
298 }
299 
FfiOHOSAceFrameworkWebFileAccessEnabled(bool isFileAccessEnabled)300 void FfiOHOSAceFrameworkWebFileAccessEnabled(bool isFileAccessEnabled)
301 {
302     WebModel::GetInstance()->SetFileAccessEnabled(isFileAccessEnabled);
303 }
304 
FfiOHOSAceFrameworkWebDomStorageAccessEnabled(bool isDomStorageAccessEnabled)305 void FfiOHOSAceFrameworkWebDomStorageAccessEnabled(bool isDomStorageAccessEnabled)
306 {
307     WebModel::GetInstance()->SetDomStorageAccessEnabled(isDomStorageAccessEnabled);
308 }
309 
FfiOHOSAceFrameworkWebImageAccessEnabled(bool isImageAccessEnabled)310 void FfiOHOSAceFrameworkWebImageAccessEnabled(bool isImageAccessEnabled)
311 {
312     WebModel::GetInstance()->SetImageAccessEnabled(isImageAccessEnabled);
313 }
314 
FfiOHOSAceFrameworkWebOnlineImageAccessEnabled(bool isImageAccessEnabled)315 void FfiOHOSAceFrameworkWebOnlineImageAccessEnabled(bool isImageAccessEnabled)
316 {
317     WebModel::GetInstance()->SetOnLineImageAccessEnabled(isImageAccessEnabled);
318 }
319 
FfiOHOSAceFrameworkWebMixedMode(int32_t mixedModeNum)320 void FfiOHOSAceFrameworkWebMixedMode(int32_t mixedModeNum)
321 {
322     auto mixedContentMode = MixedModeContent::MIXED_CONTENT_NEVER_ALLOW;
323     switch (mixedModeNum) {
324         case 0:
325             mixedContentMode = MixedModeContent::MIXED_CONTENT_ALWAYS_ALLOW;
326             break;
327         case 1:
328             mixedContentMode = MixedModeContent::MIXED_CONTENT_COMPATIBILITY_MODE;
329             break;
330         default:
331             mixedContentMode = MixedModeContent::MIXED_CONTENT_NEVER_ALLOW;
332             break;
333     }
334     WebModel::GetInstance()->SetMixedMode(mixedContentMode);
335 }
336 
FfiOHOSAceFrameworkWebZoomAccessEnabled(bool isZoomAccessEnabled)337 void FfiOHOSAceFrameworkWebZoomAccessEnabled(bool isZoomAccessEnabled)
338 {
339     WebModel::GetInstance()->SetZoomAccessEnabled(isZoomAccessEnabled);
340 }
341 
FfiOHOSAceFrameworkWebGeolocationAccessEnabled(bool isGeolocationAccessEnabled)342 void FfiOHOSAceFrameworkWebGeolocationAccessEnabled(bool isGeolocationAccessEnabled)
343 {
344     WebModel::GetInstance()->SetGeolocationAccessEnabled(isGeolocationAccessEnabled);
345 }
346 
FfiOHOSAceFrameworkWebVerticalScrollBarAccessEnabled(bool isVerticalScrollBarAccess)347 void FfiOHOSAceFrameworkWebVerticalScrollBarAccessEnabled(bool isVerticalScrollBarAccess)
348 {
349     WebModel::GetInstance()->SetVerticalScrollBarAccessEnabled(isVerticalScrollBarAccess);
350 }
351 
GetNestedScrollModeValue(int32_t value)352 NestedScrollMode GetNestedScrollModeValue(int32_t value)
353 {
354     auto ret = NestedScrollMode::SELF_ONLY;
355     switch (value) {
356         case 0:
357             ret = NestedScrollMode::SELF_ONLY;
358             break;
359         case 1:
360             ret = NestedScrollMode::SELF_FIRST;
361             break;
362         case PARENT_FIRST_VALUE:
363             ret = NestedScrollMode::PARENT_FIRST;
364             break;
365         default:
366             ret = NestedScrollMode::PARALLEL;
367             break;
368     }
369     return ret;
370 }
371 
FfiOHOSAceFrameworkNestedScroll(int32_t nestedScrollNum,int32_t scrollBackwardNum)372 void FfiOHOSAceFrameworkNestedScroll(int32_t nestedScrollNum, int32_t scrollBackwardNum)
373 {
374     NestedScrollOptions nestedOpt = {
375         .forward = GetNestedScrollModeValue(nestedScrollNum),
376         .backward = GetNestedScrollModeValue(scrollBackwardNum),
377     };
378     WebModel::GetInstance()->SetNestedScroll(nestedOpt);
379 }
380 
FfiOHOSAceFrameworkWebUserAgent(const std::string & userAgent)381 void FfiOHOSAceFrameworkWebUserAgent(const std::string& userAgent)
382 {
383     WebModel::GetInstance()->SetUserAgent(userAgent);
384 }
385 
FfiOHOSAceFrameworkWebBackgroundColor(uint32_t color)386 void FfiOHOSAceFrameworkWebBackgroundColor(uint32_t color)
387 {
388     WebModel::GetInstance()->SetBackgroundColor(Color(color));
389 }
390 
OnCommonDialog(bool (* callback)(FfiWebEvent event),int64_t dialogEventType)391 void OnCommonDialog(bool (*callback)(FfiWebEvent event), int64_t dialogEventType)
392 {
393     auto instanceId = Container::CurrentId();
394     auto onDialog = [webCallback = CJLambda::Create(callback), instanceId](const BaseEventInfo* info) -> bool {
395         ContainerScope scope(instanceId);
396         FfiWebEvent cjEvent {};
397         auto* eventInfo = TypeInfoHelper::DynamicCast<WebDialogEvent>(info);
398         cjEvent.url = eventInfo->GetUrl().c_str();
399         cjEvent.message = eventInfo->GetMessage().c_str();
400         if (eventInfo->GetType() == DialogEventType::DIALOG_EVENT_PROMPT) {
401             cjEvent.value = eventInfo->GetValue().c_str();
402         }
403         auto result = new RefPtr<Result>(eventInfo->GetResult());
404         cjEvent.result = result;
405         auto res = webCallback(cjEvent);
406         delete result;
407         return res;
408     };
409     WebModel::GetInstance()->SetOnCommonDialog(std::move(onDialog), dialogEventType);
410 }
411 
FfiOHOSAceFrameworkWebOnAlert(bool (* callback)(FfiWebEvent event))412 void FfiOHOSAceFrameworkWebOnAlert(bool (*callback)(FfiWebEvent event))
413 {
414     OnCommonDialog(callback, DialogEventType::DIALOG_EVENT_ALERT);
415 }
416 
FfiOHOSAceFrameworkWebOnPageStart(void (* callback)(const char * url))417 void FfiOHOSAceFrameworkWebOnPageStart(void (*callback)(const char* url))
418 {
419     auto instanceId = Container::CurrentId();
420     auto onStart = [func = CJLambda::Create(callback), instanceId](const BaseEventInfo* info) {
421         ContainerScope scope(instanceId);
422         auto* eventInfo = TypeInfoHelper::DynamicCast<LoadWebPageStartEvent>(info);
423         func(eventInfo->GetLoadedUrl().c_str());
424     };
425     WebModel::GetInstance()->SetOnPageStart(std::move(onStart));
426 }
427 
WebRequestHeadersToMapToCFFIArray(const RefPtr<WebRequest> & webRequest,MapToCFFIArray & res)428 bool WebRequestHeadersToMapToCFFIArray(const RefPtr<WebRequest>& webRequest, MapToCFFIArray& res)
429 {
430     std::map<std::string, std::string> header = webRequest->GetHeaders();
431     auto key = (const char**)malloc(sizeof(const char*) * header.size());
432     auto value = (const char**)malloc(sizeof(const char*) * header.size());
433     if (key == NULL || value == NULL) {
434         if (key != NULL) {
435             free(key);
436         }
437         if (value != NULL) {
438             free(value);
439         }
440         LOGE("FfiOHOSAceFrameworkGetHeaders fail, malloc fail");
441         return false;
442     }
443     size_t i = 0;
444     res.size = header.size();
445     res.key = key;
446     res.value = value;
447     for (auto it = header.begin(); it != header.end(); ++it, ++i) {
448         res.key[i] = it->first.c_str();
449         res.value[i] = it->second.c_str();
450     }
451     return true;
452 }
453 
MapToCFFIArrayToFreeMemory(MapToCFFIArray & mapToCFFIArray)454 void MapToCFFIArrayToFreeMemory(MapToCFFIArray& mapToCFFIArray)
455 {
456     free(mapToCFFIArray.key);
457     free(mapToCFFIArray.value);
458 }
459 
FfiOHOSAceFrameworkWebOnLoadIntercept(bool (* callback)(FfiWebResourceRequest event))460 void FfiOHOSAceFrameworkWebOnLoadIntercept(bool (*callback)(FfiWebResourceRequest event))
461 {
462     auto instanceId = Container::CurrentId();
463     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
464     auto onLoadIntercept = [func = CJLambda::Create(callback), instanceId, node = frameNode](
465         const BaseEventInfo* info) -> bool  {
466         ContainerScope scope(instanceId);
467         auto pipelineContext = PipelineContext::GetCurrentContext();
468         CHECK_NULL_RETURN(pipelineContext, false);
469         pipelineContext->UpdateCurrentActiveNode(node);
470 
471         FfiWebResourceRequest cjWebResourceRequest {};
472         auto* eventInfo = TypeInfoHelper::DynamicCast<LoadInterceptEvent>(info);
473         auto request = eventInfo->GetRequest();
474         MapToCFFIArray mapToCFFIArray;
475         auto wirteSuccess = WebRequestHeadersToMapToCFFIArray(request, mapToCFFIArray);
476         if (!wirteSuccess) {
477             return false;
478         }
479         cjWebResourceRequest.url = request->GetUrl().c_str();
480         cjWebResourceRequest.isMainFrame = request->IsMainFrame();
481         cjWebResourceRequest.isRedirect = request->IsRedirect();
482         cjWebResourceRequest.hasGesture = request->HasGesture();
483         cjWebResourceRequest.method = request->GetMethod().c_str();
484         cjWebResourceRequest.mapToCFFIArray = &mapToCFFIArray;
485         auto res = func(cjWebResourceRequest);
486         MapToCFFIArrayToFreeMemory(mapToCFFIArray);
487         return res;
488     };
489     WebModel::GetInstance()->SetOnLoadIntercept(std::move(onLoadIntercept));
490 }
491 
FfiOHOSAceFrameworkWebOnPageFinish(void (* callback)(const char * url))492 void FfiOHOSAceFrameworkWebOnPageFinish(void (*callback)(const char* url))
493 {
494     auto instanceId = Container::CurrentId();
495     auto onFinish = [func = CJLambda::Create(callback), instanceId](const BaseEventInfo* info) {
496         ContainerScope scope(instanceId);
497         auto* eventInfo = TypeInfoHelper::DynamicCast<LoadWebPageFinishEvent>(info);
498         func(eventInfo->GetLoadedUrl().c_str());
499     };
500     WebModel::GetInstance()->SetOnPageFinish(std::move(onFinish));
501 }
502 
FfiOHOSAceFrameworkWebJavaScriptProxy(VectorInt64Handle funcList,const char * name,VectorStringHandle methodList,int64_t controllerId)503 CJ_EXPORT void FfiOHOSAceFrameworkWebJavaScriptProxy(
504     VectorInt64Handle funcList, const char* name, VectorStringHandle methodList, int64_t controllerId)
505 {
506 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
507     auto controller = FFIData::GetData<WebviewControllerImpl>(controllerId);
508     if (controller) {
509         auto& funcs = *reinterpret_cast<std::vector<int64_t>*>(funcList);
510         std::vector<std::function<char*(const char*)>> cFuncs;
511         for (int64_t i = 0; i < static_cast<int64_t>(funcs.size()); i++) {
512             auto cFunc = reinterpret_cast<char* (*)(const char*)>(funcs[i]);
513             auto wrapper = [lambda = CJLambda::Create(cFunc)](const char* str) -> char* { return lambda(str); };
514             cFuncs.push_back(wrapper);
515         }
516         std::string cName = std::string(name);
517         auto& methods = *reinterpret_cast<std::vector<std::string>*>(methodList);
518         auto jsProxyCallback = [controller, cFuncs, cName, methods]() {
519             controller->SetNWebJavaScriptResultCallBack();
520             controller->RegisterJavaScriptProxy(cFuncs, cName, methods);
521         };
522         WebModel::GetInstance()->SetJsProxyCallback(jsProxyCallback);
523     }
524 #endif
525 }
526 
FfiOHOSAceFrameworkWebDarkMode(int32_t darkMode)527 void FfiOHOSAceFrameworkWebDarkMode(int32_t darkMode)
528 {
529     auto mode = WebDarkMode::Off;
530     switch (darkMode) {
531         case 0:
532             mode = WebDarkMode::Off;
533             break;
534         case 1:
535             mode = WebDarkMode::On;
536             break;
537         case 2:
538             mode = WebDarkMode::Auto;
539             break;
540         default:
541             mode = WebDarkMode::Off;
542             break;
543     }
544     WebModel::GetInstance()->SetDarkMode(mode);
545 }
546 
FfiOHOSAceFrameworkWebForceDarkAccess(bool access)547 void FfiOHOSAceFrameworkWebForceDarkAccess(bool access)
548 {
549     WebModel::GetInstance()->SetForceDarkAccess(access);
550 }
551 }