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