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