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