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