• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "frameworks/bridge/declarative_frontend/jsview/js_web_controller.h"
17 
18 #include "base/log/ace_scoring_log.h"
19 #include "base/utils/linear_map.h"
20 #include "base/utils/utils.h"
21 #include "bridge/declarative_frontend/engine/functions/js_webview_function.h"
22 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
23 #include "core/components_ng/base/view_stack_processor.h"
24 
25 namespace OHOS::Ace::Framework {
26 namespace {
ToJsValueHelper(const EcmaVM * vm,std::shared_ptr<WebJSValue> argument)27 panda::Local<panda::JSValueRef> ToJsValueHelper(const EcmaVM* vm, std::shared_ptr<WebJSValue> argument)
28 {
29     if (!argument || !vm) {
30         TAG_LOGE(AceLogTag::ACE_WEB, "ToJsValueHelper: argument or vm is null");
31         return panda::JSValueRef::Undefined(vm);
32     }
33     switch (argument->GetType()) {
34         case WebJSValue::Type::INTEGER:
35             return ToJSValue(argument->GetInt());
36         case WebJSValue::Type::DOUBLE:
37             return ToJSValue(argument->GetDouble());
38         case WebJSValue::Type::BOOLEAN:
39             return ToJSValue(argument->GetBoolean());
40         case WebJSValue::Type::STRING:
41             return ToJSValue(argument->GetString());
42         case WebJSValue::Type::LIST: {
43             size_t length = argument->GetListValueSize();
44             auto arr = panda::ArrayRef::New(vm, length);
45             for (size_t i = 0; i < length; ++i) {
46                 auto nPtr = std::make_shared<WebJSValue>(argument->GetListValue(i));
47                 if (!panda::ArrayRef::SetValueAt(vm, arr, i, ToJsValueHelper(vm, nPtr))) {
48                     TAG_LOGE(AceLogTag::ACE_WEB, "ToJsValueHelper: SetValueAt api call failed");
49                     return panda::JSValueRef::Undefined(vm);
50                 }
51             }
52             return arr;
53         }
54         case WebJSValue::Type::DICTIONARY: {
55             auto obj = panda::ObjectRef::New(vm);
56             auto dict = argument->GetDictionaryValue();
57             for (auto& item : dict) {
58                 auto nPtr = std::make_shared<WebJSValue>(item.second);
59                 obj->Set(vm, panda::StringRef::NewFromUtf8(vm, item.first.c_str()), ToJsValueHelper(vm, nPtr));
60             }
61             return obj;
62         }
63         case WebJSValue::Type::BINARY: {
64             auto size = argument->GetBinaryValueSize();
65             auto buff = argument->GetBinaryValue();
66             return panda::ArrayBufferRef::New(vm, (void*)buff, (int32_t)size, nullptr, (void*)buff);
67         }
68         case WebJSValue::Type::NONE:
69             return panda::JSValueRef::Undefined(vm);
70         default:
71             TAG_LOGE(AceLogTag::ACE_WEB, "ToJsValueHelper: jsvalue type not support!");
72             break;
73     }
74     return panda::JSValueRef::Undefined(vm);
75 }
76 
ParseWebViewValueToJsValue(std::shared_ptr<WebJSValue> value,std::vector<JSRef<JSVal>> & argv)77 void ParseWebViewValueToJsValue(std::shared_ptr<WebJSValue> value, std::vector<JSRef<JSVal>>& argv)
78 {
79     if (!value) {
80         return;
81     }
82     auto vm = GetEcmaVm();
83     argv.push_back(JSRef<JSVal>::Make(ToJsValueHelper(vm, value)));
84 }
85 
ParseValue(const JSRef<JSVal> & resultValue,std::shared_ptr<WebJSValue> webviewValue)86 std::shared_ptr<WebJSValue> ParseValue(const JSRef<JSVal>& resultValue, std::shared_ptr<WebJSValue> webviewValue)
87 {
88     if (!webviewValue) {
89         TAG_LOGE(AceLogTag::ACE_WEB, "ParseValue: webviewValue or resultValue is null");
90         return std::make_shared<WebJSValue>();
91     }
92 
93     webviewValue->error_ = static_cast<int>(WebJavaScriptBridgeError::NO_ERROR);
94     if (resultValue->IsBoolean()) {
95         webviewValue->SetType(WebJSValue::Type::BOOLEAN);
96         webviewValue->SetBoolean(resultValue->ToBoolean());
97     } else if (resultValue->IsNull()) {
98         webviewValue->SetType(WebJSValue::Type::NONE);
99     } else if (resultValue->IsString()) {
100         webviewValue->SetType(WebJSValue::Type::STRING);
101         webviewValue->SetString(resultValue->ToString());
102     } else if (resultValue->IsNumber()) {
103         webviewValue->SetType(WebJSValue::Type::DOUBLE);
104         webviewValue->SetDouble(resultValue->ToNumber<double>());
105     } else if (resultValue->IsArray()) {
106         webviewValue->SetType(WebJSValue::Type::LIST);
107         JSRef<JSArray> array = JSRef<JSArray>::Cast(resultValue);
108         for (size_t i = 0; i < array->Length(); i++) {
109             JSRef<JSVal> value = array->GetValueAt(i);
110             auto nVal = std::make_shared<WebJSValue>();
111             webviewValue->AddListValue(*ParseValue(value, nVal));
112         }
113     } else if (resultValue->IsObject()) {
114         webviewValue->SetType(WebJSValue::Type::DICTIONARY);
115         JSRef<JSObject> dic = JSRef<JSObject>::Cast(resultValue);
116         auto names = dic->GetPropertyNames();
117         for (size_t i = 0; i < names->Length(); i++) {
118             JSRef<JSVal> key = names->GetValueAt(i);
119             if (!(key->IsString())) {
120                 continue;
121             }
122             JSRef<JSVal> property = dic->GetProperty(key->ToString().c_str());
123             auto nwebValueTmp = std::make_shared<WebJSValue>();
124             auto nwebKeyTmp = std::make_shared<WebJSValue>();
125             ParseValue(key, nwebKeyTmp);
126             ParseValue(property, nwebValueTmp);
127             webviewValue->AddDictionaryValue(nwebKeyTmp->GetString(), *nwebValueTmp);
128         }
129     } else if (resultValue->IsFunction()) {
130         TAG_LOGE(AceLogTag::ACE_WEB, "ParseValue: object is not supported");
131         webviewValue->SetType(WebJSValue::Type::NONE);
132     } else if (resultValue->IsUndefined()) {
133         webviewValue->SetType(WebJSValue::Type::NONE);
134         webviewValue->error_ = static_cast<int>(WebJavaScriptBridgeError::OBJECT_IS_GONE);
135     }
136     return webviewValue;
137 }
138 } // namespace
139 
140 class JSWebCookie : public Referenced {
141 public:
JSBind(BindingTarget globalObj)142     static void JSBind(BindingTarget globalObj)
143     {
144         JSClass<JSWebCookie>::Declare("WebCookie");
145         JSClass<JSWebCookie>::CustomMethod("setCookie", &JSWebCookie::SetCookie);
146         JSClass<JSWebCookie>::CustomMethod("getCookie", &JSWebCookie::GetCookie);
147         JSClass<JSWebCookie>::CustomMethod("deleteEntireCookie", &JSWebCookie::DeleteEntirelyCookie);
148         JSClass<JSWebCookie>::CustomMethod("saveCookie", &JSWebCookie::SaveCookieSync);
149         JSClass<JSWebCookie>::Bind(globalObj, JSWebCookie::Constructor, JSWebCookie::Destructor);
150     }
151 
SetWebCookie(WebCookie * manager)152     void SetWebCookie(WebCookie* manager)
153     {
154         if (manager != nullptr) {
155             manager_ = manager;
156         }
157     }
158 
SetCookie(const JSCallbackInfo & args)159     void SetCookie(const JSCallbackInfo& args)
160     {
161         std::string url;
162         std::string value;
163         bool result = false;
164         if (args.Length() >= 2 && args[0]->IsString() && args[1]->IsString()) {
165             url = args[0]->ToString();
166             value = args[1]->ToString();
167             if (manager_ != nullptr) {
168                 result = manager_->SetCookie(url, value);
169             }
170         }
171         auto jsVal = JSVal(ToJSValue(result));
172         auto returnValue = JSRef<JSVal>::Make(jsVal);
173         args.SetReturnValue(returnValue);
174     }
175 
GetCookie(const JSCallbackInfo & args)176     void GetCookie(const JSCallbackInfo& args)
177     {
178         std::string result = "";
179         if (manager_ != nullptr && args.Length() >= 1 && args[0]->IsString()) {
180             std::string url = args[0]->ToString();
181             result = manager_->GetCookie(url);
182         }
183         auto jsVal = JSVal(ToJSValue(result));
184         auto returnValue = JSRef<JSVal>::Make(jsVal);
185         args.SetReturnValue(returnValue);
186     }
187 
DeleteEntirelyCookie(const JSCallbackInfo & args)188     void DeleteEntirelyCookie(const JSCallbackInfo& args)
189     {
190         if (manager_ == nullptr) {
191             return;
192         }
193         manager_->DeleteEntirelyCookie();
194     }
195 
SaveCookieSync(const JSCallbackInfo & args)196     void SaveCookieSync(const JSCallbackInfo& args)
197     {
198         bool result = false;
199         if (manager_ != nullptr) {
200             result = manager_->SaveCookieSync();
201         }
202         auto jsVal = JSVal(ToJSValue(result));
203         auto returnValue = JSRef<JSVal>::Make(jsVal);
204         args.SetReturnValue(returnValue);
205     }
206 
207 private:
Constructor(const JSCallbackInfo & args)208     static void Constructor(const JSCallbackInfo& args)
209     {
210         auto jsWebCookie = Referenced::MakeRefPtr<JSWebCookie>();
211         jsWebCookie->IncRefCount();
212         args.SetReturnValue(Referenced::RawPtr(jsWebCookie));
213     }
214 
Destructor(JSWebCookie * jsWebCookie)215     static void Destructor(JSWebCookie* jsWebCookie)
216     {
217         if (jsWebCookie != nullptr) {
218             jsWebCookie->DecRefCount();
219         }
220     }
221     WebCookie* manager_;
222 };
223 
224 class JSHitTestValue : public Referenced {
225 public:
JSBind(BindingTarget globalObj)226     static void JSBind(BindingTarget globalObj)
227     {
228         JSClass<JSHitTestValue>::Declare("HitTestValue");
229         JSClass<JSHitTestValue>::CustomMethod("getType", &JSHitTestValue::GetType);
230         JSClass<JSHitTestValue>::CustomMethod("getExtra", &JSHitTestValue::GetExtra);
231         JSClass<JSHitTestValue>::Bind(globalObj, JSHitTestValue::Constructor, JSHitTestValue::Destructor);
232     }
233 
SetType(int type)234     void SetType(int type)
235     {
236         type_ = type;
237     }
238 
SetExtra(const std::string & extra)239     void SetExtra(const std::string& extra)
240     {
241         extra_ = extra;
242     }
243 
GetType(const JSCallbackInfo & args)244     void GetType(const JSCallbackInfo& args)
245     {
246         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(type_)));
247     }
248 
GetExtra(const JSCallbackInfo & args)249     void GetExtra(const JSCallbackInfo& args)
250     {
251         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(extra_)));
252     }
253 
254 private:
Constructor(const JSCallbackInfo & args)255     static void Constructor(const JSCallbackInfo& args)
256     {
257         auto jSHitTestResult = Referenced::MakeRefPtr<JSHitTestValue>();
258         jSHitTestResult->IncRefCount();
259         args.SetReturnValue(Referenced::RawPtr(jSHitTestResult));
260     }
261 
Destructor(JSHitTestValue * jSHitTestResult)262     static void Destructor(JSHitTestValue* jSHitTestResult)
263     {
264         if (jSHitTestResult != nullptr) {
265             jSHitTestResult->DecRefCount();
266         }
267     }
268 
269     std::string extra_;
270     int type_ = static_cast<int>(WebHitTestType::UNKNOWN);
271 };
272 
JSWebController()273 JSWebController::JSWebController()
274 {
275     instanceId_ = Container::CurrentId();
276 }
277 
GetJavaScriptResult(const std::string & objectName,const std::string & objectMethod,const std::vector<std::shared_ptr<WebJSValue>> & args)278 std::shared_ptr<WebJSValue> JSWebController::GetJavaScriptResult(const std::string& objectName,
279     const std::string& objectMethod, const std::vector<std::shared_ptr<WebJSValue>>& args)
280 {
281     std::vector<JSRef<JSVal>> argv = {};
282     std::shared_ptr<WebJSValue> jsResult = std::make_shared<WebJSValue>(WebJSValue::Type::NONE);
283     if (objectorMap_.find(objectName) == objectorMap_.end()) {
284         return jsResult;
285     }
286     auto jsObject = objectorMap_[objectName];
287     if (jsObject->IsEmpty()) {
288         return jsResult;
289     }
290     for (std::shared_ptr<WebJSValue> input : args) {
291         ParseWebViewValueToJsValue(input, argv);
292     }
293 
294     if (jsObject->GetProperty(objectMethod.c_str())->IsEmpty() ||
295         !(jsObject->GetProperty(objectMethod.c_str())->IsFunction())) {
296         return jsResult;
297     }
298 
299     JSRef<JSFunc> func = JSRef<JSFunc>::Cast(jsObject->GetProperty(objectMethod.c_str()));
300     if (func->IsEmpty()) {
301         jsResult->error_ = static_cast<int>(WebJavaScriptBridgeError::OBJECT_IS_GONE);
302         return jsResult;
303     }
304     JSRef<JSVal> result = argv.empty() ? func->Call(jsObject, 0, {}) : func->Call(jsObject, argv.size(), &argv[0]);
305     return ParseValue(result, jsResult);
306 }
307 
308 class JSWebMessageEvent;
309 class JSWebMessagePort : public Referenced {
310 public:
JSBind(BindingTarget globalObj)311     static void JSBind(BindingTarget globalObj)
312     {
313         JSClass<JSWebMessagePort>::Declare("WebMessagePort");
314         JSClass<JSWebMessagePort>::CustomMethod("close", &JSWebMessagePort::Close);
315         JSClass<JSWebMessagePort>::CustomMethod("postMessageEvent", &JSWebMessagePort::PostMessage);
316         JSClass<JSWebMessagePort>::CustomMethod("onMessageEvent", &JSWebMessagePort::SetWebMessageCallback);
317         JSClass<JSWebMessagePort>::Bind(globalObj, JSWebMessagePort::Constructor, JSWebMessagePort::Destructor);
318     }
319 
320     void PostMessage(const JSCallbackInfo& args);
321 
Close(const JSCallbackInfo & args)322     void Close(const JSCallbackInfo& args)
323     {
324         if (port_ != nullptr) {
325             port_->Close();
326         }
327     }
328 
SetWebMessageCallback(const JSCallbackInfo & args)329     void SetWebMessageCallback(const JSCallbackInfo& args)
330     {
331         if (args.Length() < 1 || !args[0]->IsObject()) {
332             return;
333         }
334 
335         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
336         JSRef<JSVal> tsCallback = JSRef<JSVal>::Cast(obj);
337         std::function<void(std::string)> callback = nullptr;
338         if (tsCallback->IsFunction()) {
339             WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
340             auto jsCallback = AceType::MakeRefPtr<JsWebViewFunction>(JSRef<JSFunc>::Cast(tsCallback));
341             callback = [execCtx = args.GetExecutionContext(), func = std::move(jsCallback), node = frameNode](
342                             std::string result) {
343                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
344                 ACE_SCORING_EVENT("onMessageEvent CallBack");
345                 auto pipelineContext = PipelineContext::GetCurrentContext();
346                 CHECK_NULL_VOID(pipelineContext);
347                 pipelineContext->UpdateCurrentActiveNode(node);
348                 func->Execute(result);
349             };
350             if (port_ != nullptr) {
351                 port_->SetWebMessageCallback(std::move(callback));
352             }
353         }
354     }
355 
SetWebMessagePort(const RefPtr<WebMessagePort> & port)356     void SetWebMessagePort(const RefPtr<WebMessagePort>& port)
357     {
358         port_ = port;
359     }
360 
GetWebMessagePort()361     RefPtr<WebMessagePort> GetWebMessagePort()
362     {
363         return port_;
364     }
365 
366 private:
367     RefPtr<WebMessagePort> port_;
368 
Constructor(const JSCallbackInfo & args)369     static void Constructor(const JSCallbackInfo& args)
370     {
371         auto jsWebMessagePort = Referenced::MakeRefPtr<JSWebMessagePort>();
372         jsWebMessagePort->IncRefCount();
373         args.SetReturnValue(Referenced::RawPtr(jsWebMessagePort));
374     }
375 
Destructor(JSWebMessagePort * jsWebMessagePort)376     static void Destructor(JSWebMessagePort* jsWebMessagePort)
377     {
378         if (jsWebMessagePort != nullptr) {
379             jsWebMessagePort->DecRefCount();
380         }
381     }
382 };
383 
384 class JSWebMessageEvent : public Referenced {
385 public:
JSBind(BindingTarget globalObj)386     static void JSBind(BindingTarget globalObj)
387     {
388         JSClass<JSWebMessageEvent>::Declare("WebMessageEvent");
389         JSClass<JSWebMessageEvent>::CustomMethod("getData", &JSWebMessageEvent::GetData);
390         JSClass<JSWebMessageEvent>::CustomMethod("setData", &JSWebMessageEvent::SetData);
391         JSClass<JSWebMessageEvent>::CustomMethod("getPorts", &JSWebMessageEvent::GetPorts);
392         JSClass<JSWebMessageEvent>::CustomMethod("setPorts", &JSWebMessageEvent::SetPorts);
393         JSClass<JSWebMessageEvent>::Bind(globalObj, JSWebMessageEvent::Constructor, JSWebMessageEvent::Destructor);
394     }
395 
GetData(const JSCallbackInfo & args)396     void GetData(const JSCallbackInfo& args)
397     {
398         auto jsVal = JSVal(ToJSValue(data_));
399         auto retVal = JSRef<JSVal>::Make(jsVal);
400         args.SetReturnValue(retVal);
401     }
402 
SetData(const JSCallbackInfo & args)403     void SetData(const JSCallbackInfo& args)
404     {
405         if (args.Length() < 1 || !args[0]->IsString()) {
406             return;
407         }
408         data_ = args[0]->ToString();
409     }
410 
SetPorts(const JSCallbackInfo & args)411     void SetPorts(const JSCallbackInfo& args)
412     {
413         if (args.Length() <= 0) {
414             return;
415         }
416         JSRef<JSArray> jsPorts = JSRef<JSArray>::Cast(args[0]);
417         std::vector<RefPtr<WebMessagePort>> sendPorts;
418         if (jsPorts->IsArray()) {
419             JSRef<JSArray> array = JSRef<JSArray>::Cast(jsPorts);
420             for (size_t i = 0; i < array->Length(); i++) {
421                 JSRef<JSVal> jsValue = array->GetValueAt(i);
422                 if (!jsValue->IsObject()) {
423                     continue;
424                 }
425                 JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
426                 RefPtr<JSWebMessagePort> jswebPort = Referenced::Claim(jsObj->Unwrap<JSWebMessagePort>());
427                 if (jswebPort) {
428                     ports_.push_back(jswebPort);
429                 }
430             }
431         }
432     }
433 
GetPorts(const JSCallbackInfo & args)434     void GetPorts(const JSCallbackInfo& args)
435     {
436         JSRef<JSArray> jsPorts = JSRef<JSArray>::New();
437         JSRef<JSObject> jsObj;
438         RefPtr<JSWebMessagePort> jswebPort;
439         for (size_t i = 0; i < ports_.size(); i++) {
440             jsObj = JSClass<JSWebMessagePort>::NewInstance();
441             jswebPort = Referenced::Claim(jsObj->Unwrap<JSWebMessagePort>());
442             jswebPort->SetWebMessagePort(ports_[i]->GetWebMessagePort());
443             jsPorts->SetValueAt(i, jsObj);
444         }
445         args.SetReturnValue(jsPorts);
446     }
447 
GetDataInternal()448     std::string GetDataInternal()
449     {
450         return data_;
451     }
452 
GetPortsInternal()453     std::vector<RefPtr<JSWebMessagePort>> GetPortsInternal()
454     {
455         return ports_;
456     }
457 
458 private:
459     std::string data_;
460     std::vector<RefPtr<JSWebMessagePort>> ports_;
461 
Constructor(const JSCallbackInfo & args)462     static void Constructor(const JSCallbackInfo& args)
463     {
464         auto jsWebMessageEvent = Referenced::MakeRefPtr<JSWebMessageEvent>();
465         jsWebMessageEvent->IncRefCount();
466         args.SetReturnValue(Referenced::RawPtr(jsWebMessageEvent));
467     }
468 
Destructor(JSWebMessageEvent * jsWebMessageEvent)469     static void Destructor(JSWebMessageEvent* jsWebMessageEvent)
470     {
471         if (jsWebMessageEvent != nullptr) {
472             jsWebMessageEvent->DecRefCount();
473         }
474     }
475 };
476 
PostMessage(const JSCallbackInfo & args)477 void JSWebMessagePort::PostMessage(const JSCallbackInfo& args)
478 {
479     if (args.Length() <= 0 || !(args[0]->IsObject())) {
480         return;
481     }
482     // get ports
483     JSRef<JSVal> jsPorts = JSRef<JSVal>::Cast(args[0]);
484     if (!jsPorts->IsObject()) {
485         return;
486     }
487     auto jsRes = Referenced::Claim(JSRef<JSObject>::Cast(jsPorts)->Unwrap<JSWebMessageEvent>());
488     std::string data = jsRes->GetDataInternal();
489     if (port_) {
490         port_->PostMessage(data);
491     }
492 }
493 
JSBind(BindingTarget globalObj)494 void JSWebController::JSBind(BindingTarget globalObj)
495 {
496     JSClass<JSWebController>::Declare("WebController");
497     JSClass<JSWebController>::CustomMethod("loadUrl", &JSWebController::LoadUrl);
498     JSClass<JSWebController>::CustomMethod("runJavaScript", &JSWebController::ExecuteTypeScript);
499     JSClass<JSWebController>::CustomMethod("refresh", &JSWebController::Refresh);
500     JSClass<JSWebController>::CustomMethod("stop", &JSWebController::StopLoading);
501     JSClass<JSWebController>::CustomMethod("getHitTest", &JSWebController::GetHitTestResult);
502     JSClass<JSWebController>::CustomMethod("registerJavaScriptProxy", &JSWebController::AddJavascriptInterface);
503     JSClass<JSWebController>::CustomMethod("deleteJavaScriptRegister", &JSWebController::RemoveJavascriptInterface);
504     JSClass<JSWebController>::CustomMethod("onInactive", &JSWebController::OnInactive);
505     JSClass<JSWebController>::CustomMethod("onActive", &JSWebController::OnActive);
506     JSClass<JSWebController>::CustomMethod("zoom", &JSWebController::Zoom);
507     JSClass<JSWebController>::CustomMethod("requestFocus", &JSWebController::RequestFocus);
508     JSClass<JSWebController>::CustomMethod("loadData", &JSWebController::LoadDataWithBaseUrl);
509     JSClass<JSWebController>::CustomMethod("backward", &JSWebController::Backward);
510     JSClass<JSWebController>::CustomMethod("forward", &JSWebController::Forward);
511     JSClass<JSWebController>::CustomMethod("accessStep", &JSWebController::AccessStep);
512     JSClass<JSWebController>::CustomMethod("accessForward", &JSWebController::AccessForward);
513     JSClass<JSWebController>::CustomMethod("accessBackward", &JSWebController::AccessBackward);
514     JSClass<JSWebController>::CustomMethod("clearHistory", &JSWebController::ClearHistory);
515     JSClass<JSWebController>::CustomMethod("clearSslCache", &JSWebController::ClearSslCache);
516     JSClass<JSWebController>::CustomMethod(
517         "clearClientAuthenticationCache", &JSWebController::ClearClientAuthenticationCache);
518     JSClass<JSWebController>::CustomMethod("getCookieManager", &JSWebController::GetCookieManager);
519     JSClass<JSWebController>::CustomMethod("getHitTestValue", &JSWebController::GetHitTestValue);
520     JSClass<JSWebController>::CustomMethod("backOrForward", &JSWebController::BackOrForward);
521     JSClass<JSWebController>::CustomMethod("zoomIn", &JSWebController::ZoomIn);
522     JSClass<JSWebController>::CustomMethod("zoomOut", &JSWebController::ZoomOut);
523     JSClass<JSWebController>::CustomMethod("getPageHeight", &JSWebController::GetPageHeight);
524     JSClass<JSWebController>::CustomMethod("getTitle", &JSWebController::GetTitle);
525     JSClass<JSWebController>::CustomMethod("createWebMessagePorts", &JSWebController::CreateWebMessagePorts);
526     JSClass<JSWebController>::CustomMethod("postMessage", &JSWebController::PostWebMessage);
527     JSClass<JSWebController>::CustomMethod("getWebId", &JSWebController::GetWebId);
528     JSClass<JSWebController>::CustomMethod("getDefaultUserAgent", &JSWebController::GetDefaultUserAgent);
529     JSClass<JSWebController>::CustomMethod("searchAllAsync", &JSWebController::SearchAllAsync);
530     JSClass<JSWebController>::CustomMethod("clearMatches", &JSWebController::ClearMatches);
531     JSClass<JSWebController>::CustomMethod("searchNext", &JSWebController::SearchNext);
532     JSClass<JSWebController>::CustomMethod("getUrl", &JSWebController::GetUrl);
533     JSClass<JSWebController>::Bind(globalObj, JSWebController::Constructor, JSWebController::Destructor);
534     JSWebCookie::JSBind(globalObj);
535     JSHitTestValue::JSBind(globalObj);
536     JSWebMessagePort::JSBind(globalObj);
537     JSWebMessageEvent::JSBind(globalObj);
538 }
539 
Constructor(const JSCallbackInfo & args)540 void JSWebController::Constructor(const JSCallbackInfo& args)
541 {
542     auto webController = Referenced::MakeRefPtr<JSWebController>();
543     webController->IncRefCount();
544     RefPtr<WebController> controller = AceType::MakeRefPtr<WebController>();
545     webController->SetController(controller);
546     args.SetReturnValue(Referenced::RawPtr(webController));
547 }
548 
Destructor(JSWebController * webController)549 void JSWebController::Destructor(JSWebController* webController)
550 {
551     if (webController != nullptr) {
552         webController->DecRefCount();
553     }
554 }
555 
Reload() const556 void JSWebController::Reload() const
557 {
558     if (webController_) {
559         webController_->Reload();
560     }
561 }
562 
CreateWebMessagePorts(const JSCallbackInfo & args)563 void JSWebController::CreateWebMessagePorts(const JSCallbackInfo& args)
564 {
565     ContainerScope scope(instanceId_);
566     if (webController_) {
567         std::vector<RefPtr<WebMessagePort>> ports;
568         webController_->CreateMsgPorts(ports);
569         JSRef<JSObject> jsPort0 = JSClass<JSWebMessagePort>::NewInstance();
570         auto port0 = Referenced::Claim(jsPort0->Unwrap<JSWebMessagePort>());
571         port0->SetWebMessagePort(ports.at(0));
572 
573         JSRef<JSObject> jsPort1 = JSClass<JSWebMessagePort>::NewInstance();
574         auto port1 = Referenced::Claim(jsPort1->Unwrap<JSWebMessagePort>());
575         port1->SetWebMessagePort(ports.at(1));
576 
577         JSRef<JSArray> result = JSRef<JSArray>::New();
578         result->SetValueAt(0, jsPort0);
579         result->SetValueAt(1, jsPort1);
580         args.SetReturnValue(result);
581     }
582 }
583 
PostWebMessage(const JSCallbackInfo & args)584 void JSWebController::PostWebMessage(const JSCallbackInfo& args)
585 {
586     if (args.Length() < 1 || !args[0]->IsObject()) {
587         return;
588     }
589 
590     JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
591     std::string uri;
592     if (!ConvertFromJSValue(obj->GetProperty("uri"), uri)) {
593         return;
594     }
595 
596     JSRef<JSVal> jsPorts = obj->GetProperty("message");
597     if (!jsPorts->IsObject()) {
598         return;
599     }
600     auto jsRes = Referenced::Claim(JSRef<JSObject>::Cast(jsPorts)->Unwrap<JSWebMessageEvent>());
601     std::string eventData = jsRes->GetDataInternal();
602     std::vector<RefPtr<JSWebMessagePort>> eventPorts = jsRes->GetPortsInternal();
603     std::vector<RefPtr<WebMessagePort>> sendPorts;
604     for (auto jsport : eventPorts) {
605         auto webPort = jsport->GetWebMessagePort();
606         if (webPort) {
607             sendPorts.push_back(webPort);
608         }
609     }
610 
611     if (webController_ && sendPorts.size() >= 1) {
612         webController_->PostWebMessage(eventData, sendPorts, uri);
613     }
614 }
615 
LoadUrl(const JSCallbackInfo & args)616 void JSWebController::LoadUrl(const JSCallbackInfo& args)
617 {
618     ContainerScope scope(instanceId_);
619     if (args.Length() < 1 || !args[0]->IsObject()) {
620         return;
621     }
622 
623     JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
624     JSRef<JSVal> valUrl = obj->GetProperty("url");
625     std::string url;
626     if (valUrl->IsObject()) {
627         // same as src process of JSWeb::Create
628         std::string webSrc;
629         if (!JSViewAbstract::ParseJsMedia(valUrl, webSrc)) {
630             return;
631         }
632         auto np = webSrc.find_first_of("/");
633         url = (np == std::string::npos) ? webSrc : webSrc.erase(np, 1);
634     } else if (!ConvertFromJSValue(valUrl, url)) {
635         return;
636     }
637 
638     JSRef<JSVal> headers = obj->GetProperty("headers");
639     std::map<std::string, std::string> httpHeaders;
640     if (headers->IsArray()) {
641         JSRef<JSArray> array = JSRef<JSArray>::Cast(headers);
642         for (size_t i = 0; i < array->Length(); i++) {
643             JSRef<JSVal> jsValue = array->GetValueAt(i);
644             if (!jsValue->IsObject()) {
645                 continue;
646             }
647             JSRef<JSObject> obj = JSRef<JSObject>::Cast(jsValue);
648             std::string key;
649             if (!ConvertFromJSValue(obj->GetProperty("headerKey"), key)) {
650                 continue;
651             }
652             std::string value;
653             if (!ConvertFromJSValue(obj->GetProperty("headerValue"), value)) {
654                 continue;
655             }
656             httpHeaders[key] = value;
657         }
658     }
659     if (webController_) {
660         webController_->LoadUrl(url, httpHeaders);
661     }
662 }
663 
ExecuteTypeScript(const JSCallbackInfo & args)664 void JSWebController::ExecuteTypeScript(const JSCallbackInfo& args)
665 {
666     ContainerScope scope(instanceId_);
667     if (args.Length() < 1 || !args[0]->IsObject()) {
668         return;
669     }
670 
671     JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
672     std::string script;
673     if (!ConvertFromJSValue(obj->GetProperty("script"), script)) {
674         return;
675     }
676     JSRef<JSVal> tsCallback = obj->GetProperty("callback");
677     std::function<void(std::string)> callback = nullptr;
678     if (tsCallback->IsFunction()) {
679         WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
680         auto jsCallback = AceType::MakeRefPtr<JsWebViewFunction>(JSRef<JSFunc>::Cast(tsCallback));
681         callback = [execCtx = args.GetExecutionContext(), func = std::move(jsCallback), node = frameNode](
682                         std::string result) {
683             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
684             ACE_SCORING_EVENT("ExecuteTypeScript CallBack");
685             auto pipelineContext = PipelineContext::GetCurrentContext();
686             CHECK_NULL_VOID(pipelineContext);
687             pipelineContext->UpdateCurrentActiveNode(node);
688             func->Execute(result);
689         };
690     }
691     if (webController_) {
692         webController_->ExecuteTypeScript(script, std::move(callback));
693     }
694 }
695 
LoadDataWithBaseUrl(const JSCallbackInfo & args)696 void JSWebController::LoadDataWithBaseUrl(const JSCallbackInfo& args)
697 {
698     ContainerScope scope(instanceId_);
699     if (args.Length() >= 1 && args[0]->IsObject()) {
700         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
701 
702         std::string data;
703         if (!ConvertFromJSValue(obj->GetProperty("data"), data)) {
704             return;
705         }
706 
707         std::string mimeType;
708         if (!ConvertFromJSValue(obj->GetProperty("mimeType"), mimeType)) {
709             return;
710         }
711 
712         std::string encoding;
713         if (!ConvertFromJSValue(obj->GetProperty("encoding"), encoding)) {
714             return;
715         }
716 
717         std::string baseUrl;
718         std::string historyUrl;
719         ConvertFromJSValue(obj->GetProperty("baseUrl"), baseUrl);
720         ConvertFromJSValue(obj->GetProperty("historyUrl"), historyUrl);
721         if (webController_) {
722             webController_->LoadDataWithBaseUrl(baseUrl, data, mimeType, encoding, historyUrl);
723         }
724     }
725 }
726 
Backward(const JSCallbackInfo & args)727 void JSWebController::Backward(const JSCallbackInfo& args)
728 {
729     ContainerScope scope(instanceId_);
730     if (webController_) {
731         webController_->Backward();
732     }
733 }
734 
Forward(const JSCallbackInfo & args)735 void JSWebController::Forward(const JSCallbackInfo& args)
736 {
737     ContainerScope scope(instanceId_);
738     if (webController_) {
739         webController_->Forward();
740     }
741 }
742 
AccessStep(const JSCallbackInfo & args)743 void JSWebController::AccessStep(const JSCallbackInfo& args)
744 {
745     ContainerScope scope(instanceId_);
746     int32_t step = 0;
747     if (args.Length() < 1 || !ConvertFromJSValue(args[0], step)) {
748         return;
749     }
750     if (webController_) {
751         auto canAccess = webController_->AccessStep(step);
752         auto jsVal = JSVal(ToJSValue(canAccess));
753         auto returnValue = JSRef<JSVal>::Make(jsVal);
754         args.SetReturnValue(returnValue);
755     }
756 }
757 
AccessBackward(const JSCallbackInfo & args)758 void JSWebController::AccessBackward(const JSCallbackInfo& args)
759 {
760     ContainerScope scope(instanceId_);
761     if (webController_) {
762         auto canAccess = webController_->AccessBackward();
763         auto jsVal = JSVal(ToJSValue(canAccess));
764         auto returnValue = JSRef<JSVal>::Make(jsVal);
765         args.SetReturnValue(returnValue);
766     }
767 }
768 
AccessForward(const JSCallbackInfo & args)769 void JSWebController::AccessForward(const JSCallbackInfo& args)
770 {
771     ContainerScope scope(instanceId_);
772     if (webController_) {
773         auto canAccess = webController_->AccessForward();
774         auto jsVal = JSVal(ToJSValue(canAccess));
775         auto returnValue = JSRef<JSVal>::Make(jsVal);
776         args.SetReturnValue(returnValue);
777     }
778 }
779 
ClearHistory(const JSCallbackInfo & args)780 void JSWebController::ClearHistory(const JSCallbackInfo& args)
781 {
782     ContainerScope scope(instanceId_);
783     if (webController_) {
784         webController_->ClearHistory();
785     }
786 }
787 
ClearSslCache(const JSCallbackInfo & args)788 void JSWebController::ClearSslCache(const JSCallbackInfo& args)
789 {
790     ContainerScope scope(instanceId_);
791     if (webController_) {
792         webController_->ClearSslCache();
793     }
794 }
795 
ClearClientAuthenticationCache(const JSCallbackInfo & args)796 void JSWebController::ClearClientAuthenticationCache(const JSCallbackInfo& args)
797 {
798     ContainerScope scope(instanceId_);
799     if (webController_) {
800         webController_->ClearClientAuthenticationCache();
801     }
802 }
803 
Refresh(const JSCallbackInfo & args)804 void JSWebController::Refresh(const JSCallbackInfo& args)
805 {
806     ContainerScope scope(instanceId_);
807     if (webController_) {
808         webController_->Refresh();
809     }
810 }
811 
StopLoading(const JSCallbackInfo & args)812 void JSWebController::StopLoading(const JSCallbackInfo& args)
813 {
814     ContainerScope scope(instanceId_);
815     if (webController_) {
816         webController_->StopLoading();
817     }
818 }
819 
GetHitTestResult(const JSCallbackInfo & args)820 void JSWebController::GetHitTestResult(const JSCallbackInfo& args)
821 {
822     ContainerScope scope(instanceId_);
823     if (webController_) {
824         int result = webController_->GetHitTestResult();
825         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
826     }
827 }
828 
GetHitTestValue(const JSCallbackInfo & args)829 void JSWebController::GetHitTestValue(const JSCallbackInfo& args)
830 {
831     ContainerScope scope(instanceId_);
832     if (!webController_) {
833         return;
834     }
835     HitTestResult hitResult;
836     webController_->GetHitTestValue(hitResult);
837     JSRef<JSObject> resultObj = JSClass<JSHitTestValue>::NewInstance();
838     auto result = Referenced::Claim(resultObj->Unwrap<JSHitTestValue>());
839     result->SetType(hitResult.GetHitType());
840     result->SetExtra(hitResult.GetExtraData());
841     args.SetReturnValue(resultObj);
842 }
843 
GetCookieManager(const JSCallbackInfo & args)844 void JSWebController::GetCookieManager(const JSCallbackInfo& args)
845 {
846     ContainerScope scope(instanceId_);
847     if (webController_) {
848         if (!webController_->GetCookieManager()) {
849             return;
850         }
851         if (!jsWebCookieInit_) {
852             jsWebCookie_ = JSClass<JSWebCookie>::NewInstance();
853             auto jsWebCookieVal = Referenced::Claim(jsWebCookie_->Unwrap<JSWebCookie>());
854             jsWebCookieVal->SetWebCookie(webController_->GetCookieManager());
855             jsWebCookieInit_ = true;
856         }
857         args.SetReturnValue(jsWebCookie_);
858     }
859 }
860 
BackOrForward(const JSCallbackInfo & args)861 void JSWebController::BackOrForward(const JSCallbackInfo& args)
862 {
863     ContainerScope scope(instanceId_);
864     int32_t step = 0;
865     if (args.Length() < 1 || !ConvertFromJSValue(args[0], step)) {
866         return;
867     }
868     if (webController_) {
869         webController_->BackOrForward(step);
870     }
871 }
872 
ZoomIn(const JSCallbackInfo & args)873 void JSWebController::ZoomIn(const JSCallbackInfo& args)
874 {
875     ContainerScope scope(instanceId_);
876     if (webController_) {
877         bool result = webController_->ZoomIn();
878         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
879     }
880 }
881 
ZoomOut(const JSCallbackInfo & args)882 void JSWebController::ZoomOut(const JSCallbackInfo& args)
883 {
884     ContainerScope scope(instanceId_);
885     if (webController_) {
886         bool result = webController_->ZoomOut();
887         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
888     }
889 }
890 
GetPageHeight(const JSCallbackInfo & args)891 void JSWebController::GetPageHeight(const JSCallbackInfo& args)
892 {
893     ContainerScope scope(instanceId_);
894     if (webController_) {
895         int result = webController_->GetPageHeight();
896         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
897     }
898 }
899 
GetTitle(const JSCallbackInfo & args)900 void JSWebController::GetTitle(const JSCallbackInfo& args)
901 {
902     ContainerScope scope(instanceId_);
903     if (webController_) {
904         std::string result = webController_->GetTitle();
905         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
906     }
907 }
908 
GetWebId(const JSCallbackInfo & args)909 void JSWebController::GetWebId(const JSCallbackInfo& args)
910 {
911     ContainerScope scope(instanceId_);
912     if (webController_) {
913         int result = webController_->GetWebId();
914         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
915     }
916 }
917 
GetDefaultUserAgent(const JSCallbackInfo & args)918 void JSWebController::GetDefaultUserAgent(const JSCallbackInfo& args)
919 {
920     ContainerScope scope(instanceId_);
921     if (webController_) {
922         std::string result = webController_->GetDefaultUserAgent();
923         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
924     }
925 }
926 
SetJavascriptCallBackImpl()927 void JSWebController::SetJavascriptCallBackImpl()
928 {
929     if (!webController_) {
930         return;
931     }
932 
933     WebController::JavaScriptCallBackImpl callback = [weak = WeakClaim(this)](const std::string& objectName,
934                                                          const std::string& objectMethod,
935                                                          const std::vector<std::shared_ptr<WebJSValue>>& args) {
936         auto jsWebController = weak.Upgrade();
937         if (jsWebController == nullptr) {
938             return std::make_shared<WebJSValue>(WebJSValue::Type::NONE);
939         }
940         return jsWebController->GetJavaScriptResult(objectName, objectMethod, args);
941     };
942     webController_->SetJavaScriptCallBackImpl(std::move(callback));
943 }
944 
AddJavascriptInterface(const JSCallbackInfo & args)945 void JSWebController::AddJavascriptInterface(const JSCallbackInfo& args)
946 {
947     ContainerScope scope(instanceId_);
948     if (args.Length() < 1 || !args[0]->IsObject()) {
949         return;
950     }
951     if (webController_ == nullptr) {
952         return;
953     }
954     // Init webview callback
955     SetJavascriptCallBackImpl();
956 
957     // options
958     JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
959     // options.name
960     std::string objName;
961     if (!ConvertFromJSValue(obj->GetProperty("name"), objName)) {
962         return;
963     }
964     // options.obj
965     JSRef<JSVal> jsClassObj = obj->GetProperty("object");
966     if (!jsClassObj->IsObject()) {
967         return;
968     }
969     if (objectorMap_.find(objName) == objectorMap_.end()) {
970         objectorMap_[objName] = JSRef<JSObject>::Cast(jsClassObj);
971     }
972     // options.methodList
973     std::vector<std::string> methods;
974     JSRef<JSVal> methodList = obj->GetProperty("methodList");
975     if (methodList->IsArray()) {
976         JSRef<JSArray> array = JSRef<JSArray>::Cast(methodList);
977         for (size_t i = 0; i < array->Length(); i++) {
978             JSRef<JSVal> method = array->GetValueAt(i);
979             if (method->IsString()) {
980                 methods.push_back(method->ToString());
981             }
982         }
983     }
984 
985     webController_->AddJavascriptInterface(objName, methods);
986 }
987 
InitJavascriptInterface()988 void JSWebController::InitJavascriptInterface()
989 {
990     if (!webController_) {
991         return;
992     }
993     // Init webview callback
994     SetJavascriptCallBackImpl();
995     for (auto& entry : methods_) {
996         webController_->AddJavascriptInterface(entry.first, entry.second);
997     }
998 }
999 
SetJavascriptInterface(const JSCallbackInfo & args)1000 void JSWebController::SetJavascriptInterface(const JSCallbackInfo& args)
1001 {
1002     if (args.Length() < 1 || !args[0]->IsObject()) {
1003         return;
1004     }
1005     if (!webController_) {
1006         return;
1007     }
1008     // options
1009     JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
1010     // options.name
1011     std::string objName;
1012     if (!ConvertFromJSValue(obj->GetProperty("name"), objName)) {
1013         return;
1014     }
1015     // options.obj
1016     JSRef<JSVal> jsClassObj = obj->GetProperty("object");
1017     if (!jsClassObj->IsObject()) {
1018         return;
1019     }
1020     objectorMap_[objName] = JSRef<JSObject>::Cast(jsClassObj);
1021     std::vector<std::string> methods;
1022     methods_.clear();
1023     JSRef<JSVal> methodList = obj->GetProperty("methodList");
1024     JSRef<JSArray> array = JSRef<JSArray>::Cast(methodList);
1025     if (array->IsArray()) {
1026         for (size_t i = 0; i < array->Length(); i++) {
1027             JSRef<JSVal> method = array->GetValueAt(i);
1028             if (method->IsString()) {
1029                 methods.emplace_back(method->ToString());
1030             }
1031         }
1032     }
1033     methods_[objName] = methods;
1034 
1035     webController_->SetInitJavascriptInterface([weak = WeakClaim(this)]() {
1036         auto jsWebcontroller = weak.Upgrade();
1037         if (jsWebcontroller) {
1038             jsWebcontroller->InitJavascriptInterface();
1039         }
1040     });
1041 }
1042 
RemoveJavascriptInterface(const JSCallbackInfo & args)1043 void JSWebController::RemoveJavascriptInterface(const JSCallbackInfo& args)
1044 {
1045     ContainerScope scope(instanceId_);
1046     std::string objName;
1047     if (args.Length() < 1 || !ConvertFromJSValue(args[0], objName)) {
1048         return;
1049     }
1050     if (objectorMap_.find(objName) == objectorMap_.end()) {
1051         return;
1052     }
1053     objectorMap_.erase(objName);
1054     if (webController_) {
1055         webController_->RemoveJavascriptInterface(objName, {});
1056     }
1057 }
1058 
OnInactive(const JSCallbackInfo & args)1059 void JSWebController::OnInactive(const JSCallbackInfo& args)
1060 {
1061     ContainerScope scope(instanceId_);
1062     if (webController_) {
1063         webController_->OnInactive();
1064     }
1065 }
1066 
OnActive(const JSCallbackInfo & args)1067 void JSWebController::OnActive(const JSCallbackInfo& args)
1068 {
1069     ContainerScope scope(instanceId_);
1070     if (webController_) {
1071         webController_->OnActive();
1072     }
1073 }
1074 
Zoom(const JSCallbackInfo & args)1075 void JSWebController::Zoom(const JSCallbackInfo& args)
1076 {
1077     ContainerScope scope(instanceId_);
1078     float factor = 1.0;
1079     if (args.Length() < 1 || !ConvertFromJSValue(args[0], factor)) {
1080         return;
1081     }
1082     if (webController_) {
1083         webController_->Zoom(factor);
1084     }
1085 }
1086 
RequestFocus(const JSCallbackInfo & args)1087 void JSWebController::RequestFocus(const JSCallbackInfo& args)
1088 {
1089     ContainerScope scope(instanceId_);
1090     if (webController_) {
1091         webController_->RequestFocus();
1092     }
1093 }
1094 
SearchAllAsync(const JSCallbackInfo & args)1095 void JSWebController::SearchAllAsync(const JSCallbackInfo& args)
1096 {
1097     ContainerScope scope(instanceId_);
1098     std::string searchStr;
1099     if (args.Length() < 1 || !ConvertFromJSValue(args[0], searchStr)) {
1100         return;
1101     }
1102     if (webController_) {
1103         webController_->SearchAllAsync(searchStr);
1104     }
1105 }
ClearMatches(const JSCallbackInfo & args)1106 void JSWebController::ClearMatches(const JSCallbackInfo& args)
1107 {
1108     ContainerScope scope(instanceId_);
1109     if (webController_) {
1110         webController_->ClearMatches();
1111     }
1112 }
SearchNext(const JSCallbackInfo & args)1113 void JSWebController::SearchNext(const JSCallbackInfo& args)
1114 {
1115     ContainerScope scope(instanceId_);
1116     bool forward = false;
1117     if (args.Length() < 1 || !ConvertFromJSValue(args[0], forward)) {
1118         return;
1119     }
1120 
1121     if (webController_) {
1122         webController_->SearchNext(forward);
1123     }
1124 }
GetUrl(const JSCallbackInfo & args)1125 void JSWebController::GetUrl(const JSCallbackInfo& args)
1126 {
1127     ContainerScope scope(instanceId_);
1128     if (webController_) {
1129         std::string result = webController_->GetUrl();
1130         args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
1131     }
1132 }
1133 
1134 } // namespace OHOS::Ace::Framework
1135