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 }