2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "web-view-impl.h"
22 #include <dali/devel-api/adaptor-framework/web-engine-back-forward-list.h>
23 #include <dali/devel-api/adaptor-framework/web-engine-context.h>
24 #include <dali/devel-api/adaptor-framework/web-engine-cookie-manager.h>
25 #include <dali/devel-api/adaptor-framework/web-engine-settings.h>
26 #include <dali/devel-api/common/stage.h>
27 #include <dali/devel-api/scripting/enum-helper.h>
28 #include <dali/devel-api/scripting/scripting.h>
29 #include <dali/public-api/adaptor-framework/native-image-source.h>
30 #include <dali/public-api/object/type-registry-helper.h>
31 #include <dali/public-api/object/type-registry.h>
35 #include <dali-toolkit/devel-api/controls/control-devel.h>
36 #include <dali-toolkit/devel-api/controls/web-view/web-back-forward-list.h>
37 #include <dali-toolkit/devel-api/controls/web-view/web-context.h>
38 #include <dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h>
39 #include <dali-toolkit/devel-api/controls/web-view/web-settings.h>
40 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
41 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
42 #include <dali-toolkit/public-api/image-loader/image.h>
43 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
55 return Toolkit::WebView::New();
59 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::WebView, Toolkit::Control, Create)
61 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "url", STRING, URL )
62 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "userAgent", STRING, USER_AGENT )
63 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "scrollPosition", VECTOR2, SCROLL_POSITION )
64 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "scrollSize", VECTOR2, SCROLL_SIZE )
65 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "contentSize", VECTOR2, CONTENT_SIZE )
66 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "title", STRING, TITLE )
67 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "videoHoleEnabled", BOOLEAN, VIDEO_HOLE_ENABLED)
69 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadStarted", PAGE_LOAD_STARTED_SIGNAL )
70 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadInProgress", PAGE_LOAD_IN_PROGRESS_SIGNAL)
71 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadFinished", PAGE_LOAD_FINISHED_SIGNAL )
72 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadError", PAGE_LOAD_ERROR_SIGNAL )
73 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "scrollEdgeReached", SCROLL_EDGE_REACHED_SIGNAL )
74 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "urlChanged", URL_CHANGED_SIGNAL )
76 DALI_TYPE_REGISTRATION_END()
79 const std::string kEmptyString;
83 #define GET_ENUM_STRING(structName, inputExp) \
84 Scripting::GetLinearEnumerationName<Toolkit::WebView::structName::Type>(static_cast<Toolkit::WebView::structName::Type>(inputExp), structName##_TABLE, structName##_TABLE_COUNT)
86 #define GET_ENUM_VALUE(structName, inputExp, outputExp) \
87 Scripting::GetEnumerationProperty<Toolkit::WebView::structName::Type>(inputExp, structName##_TABLE, structName##_TABLE_COUNT, outputExp)
89 WebView::WebView(const std::string& locale, const std::string& timezoneId)
90 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
93 mWebViewSize(Stage::GetCurrent().GetSize()),
95 mPageLoadStartedSignal(),
96 mPageLoadFinishedSignal(),
97 mPageLoadErrorSignal(),
98 mVideoHoleEnabled(true),
99 mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height),
102 mWebEngine = Dali::WebEngine::New();
104 // WebEngine is empty when it is not properly initialized.
107 mWebEngine.Create(mWebViewSize.width, mWebViewSize.height, locale, timezoneId);
111 WebView::WebView(int argc, char** argv)
112 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
115 mWebViewSize(Stage::GetCurrent().GetSize()),
117 mPageLoadStartedSignal(),
118 mPageLoadFinishedSignal(),
119 mPageLoadErrorSignal(),
120 mVideoHoleEnabled(true),
121 mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height),
124 mWebEngine = Dali::WebEngine::New();
126 // WebEngine is empty when it is not properly initialized.
129 mWebEngine.Create(mWebViewSize.width, mWebViewSize.height, argc, argv);
142 mWebEngine.Destroy();
146 Toolkit::WebView WebView::New()
148 WebView* impl = new WebView();
149 Toolkit::WebView handle = Toolkit::WebView(*impl);
155 Toolkit::WebView WebView::New(const std::string& locale, const std::string& timezoneId)
157 WebView* impl = new WebView(locale, timezoneId);
158 Toolkit::WebView handle = Toolkit::WebView(*impl);
164 Toolkit::WebView WebView::New(int argc, char** argv)
166 WebView* impl = new WebView(argc, argv);
167 Toolkit::WebView handle = Toolkit::WebView(*impl);
173 void WebView::OnInitialize()
177 self.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
178 self.TouchedSignal().Connect(this, &WebView::OnTouchEvent);
180 mPositionUpdateNotification = self.AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
181 mSizeUpdateNotification = self.AddPropertyNotification(Actor::Property::SIZE, StepCondition(1.0f, 1.0f));
182 mScaleUpdateNotification = self.AddPropertyNotification(Actor::Property::WORLD_SCALE, StepCondition(0.1f, 1.0f));
183 mPositionUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
184 mSizeUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
185 mScaleUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
189 mWebEngine.PageLoadStartedSignal().Connect( this, &WebView::OnPageLoadStarted );
190 mWebEngine.PageLoadInProgressSignal().Connect(this, &WebView::OnPageLoadInProgress);
191 mWebEngine.PageLoadFinishedSignal().Connect( this, &WebView::OnPageLoadFinished );
192 mWebEngine.PageLoadErrorSignal().Connect( this, &WebView::OnPageLoadError );
193 mWebEngine.ScrollEdgeReachedSignal().Connect( this, &WebView::OnScrollEdgeReached );
194 mWebEngine.UrlChangedSignal().Connect(this, &WebView::OnUrlChanged);
196 mWebContext = std::unique_ptr<Dali::Toolkit::WebContext>(new WebContext(mWebEngine.GetContext()));
197 mWebCookieManager = std::unique_ptr<Dali::Toolkit::WebCookieManager>(new WebCookieManager(mWebEngine.GetCookieManager()));
198 mWebSettings = std::unique_ptr<Dali::Toolkit::WebSettings>(new WebSettings(mWebEngine.GetSettings()));
199 mWebBackForwardList = std::unique_ptr<Dali::Toolkit::WebBackForwardList>(new WebBackForwardList(mWebEngine.GetBackForwardList()));
203 Dali::Toolkit::WebSettings* WebView::GetSettings() const
205 return mWebSettings.get();
208 Dali::Toolkit::WebContext* WebView::GetContext() const
210 return mWebContext.get();
213 Dali::Toolkit::WebCookieManager* WebView::GetCookieManager() const
215 return mWebCookieManager.get();
218 Dali::Toolkit::WebBackForwardList* WebView::GetBackForwardList() const
220 return mWebBackForwardList.get();
223 Dali::Toolkit::ImageView& WebView::GetFavicon()
227 Dali::PixelData pixelData = mWebEngine.GetFavicon();
228 std::string url = Dali::Toolkit::Image::GenerateUrl(pixelData);
229 mFaviconView = Dali::Toolkit::ImageView::New(url);
230 mFaviconView.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS);
231 mFaviconView.SetProperty(Dali::Actor::Property::SIZE, Vector2(pixelData.GetWidth(), pixelData.GetHeight()));
236 void WebView::LoadUrl(const std::string& url)
241 Texture texture = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
242 const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
243 mVisual = Toolkit::VisualFactory::Get().CreateVisual(
244 {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
245 {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
249 // Clean up previously registered visual and add new one.
250 DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
251 mWebEngine.LoadUrl(url);
254 if(mVideoHoleEnabled)
256 EnableBlendMode(false);
261 void WebView::LoadHtmlString(const std::string& htmlString)
265 Texture texture = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
266 const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
267 mVisual = Toolkit::VisualFactory::Get().CreateVisual(
268 {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
269 {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
273 DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
274 mWebEngine.LoadHtmlString(htmlString);
277 if(mVideoHoleEnabled)
279 EnableBlendMode(false);
284 void WebView::Reload()
292 void WebView::StopLoading()
296 mWebEngine.StopLoading();
300 void WebView::Suspend()
304 mWebEngine.Suspend();
308 void WebView::Resume()
316 void WebView::ScrollBy(int deltaX, int deltaY)
320 mWebEngine.ScrollBy(deltaX, deltaY);
324 bool WebView::CanGoForward()
326 return mWebEngine ? mWebEngine.CanGoForward() : false;
329 void WebView::GoForward()
333 mWebEngine.GoForward();
337 bool WebView::CanGoBack()
339 return mWebEngine ? mWebEngine.CanGoBack() : false;
342 void WebView::GoBack()
350 void WebView::EvaluateJavaScript(const std::string& script, std::function<void(const std::string&)> resultHandler)
354 mWebEngine.EvaluateJavaScript(script, resultHandler);
358 void WebView::AddJavaScriptMessageHandler(const std::string& exposedObjectName, std::function<void(const std::string&)> handler)
362 mWebEngine.AddJavaScriptMessageHandler(exposedObjectName, handler);
366 void WebView::RegisterJavaScriptAlertCallback( Dali::WebEnginePlugin::JavaScriptAlertCallback callback )
370 mWebEngine.RegisterJavaScriptAlertCallback( callback );
374 void WebView::JavaScriptAlertReply()
378 mWebEngine.JavaScriptAlertReply();
382 void WebView::RegisterJavaScriptConfirmCallback( Dali::WebEnginePlugin::JavaScriptConfirmCallback callback )
386 mWebEngine.RegisterJavaScriptConfirmCallback( callback );
390 void WebView::JavaScriptConfirmReply( bool confirmed )
394 mWebEngine.JavaScriptConfirmReply( confirmed );
398 void WebView::RegisterJavaScriptPromptCallback( Dali::WebEnginePlugin::JavaScriptPromptCallback callback )
402 mWebEngine.RegisterJavaScriptPromptCallback( callback );
406 void WebView::JavaScriptPromptReply( const std::string& result )
410 mWebEngine.JavaScriptPromptReply( result );
414 void WebView::ClearHistory()
418 mWebEngine.ClearHistory();
422 void WebView::UpdateDisplayArea(Dali::PropertyNotification& /*source*/)
429 bool positionUsesAnchorPoint = self.GetProperty<bool>(Actor::Property::POSITION_USES_ANCHOR_POINT);
430 Vector3 actorSize = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * self.GetCurrentProperty<Vector3>(Actor::Property::SCALE);
431 Vector3 anchorPointOffSet = actorSize * (positionUsesAnchorPoint ? self.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
432 Vector2 screenPosition = self.GetProperty<Vector2>(Actor::Property::SCREEN_POSITION);
434 Dali::Rect<int> displayArea;
435 displayArea.x = screenPosition.x - anchorPointOffSet.x;
436 displayArea.y = screenPosition.y - anchorPointOffSet.y;
437 displayArea.width = actorSize.x;
438 displayArea.height = actorSize.y;
440 Size displaySize = Size(displayArea.width, displayArea.height);
441 if(mWebViewSize != displaySize)
443 mWebViewSize = displaySize;
446 if(mWebViewArea != displayArea)
448 mWebViewArea = displayArea;
449 mWebEngine.UpdateDisplayArea(mWebViewArea);
453 void WebView::EnableVideoHole(bool enabled)
455 mVideoHoleEnabled = enabled;
457 EnableBlendMode(!mVideoHoleEnabled);
461 mWebEngine.EnableVideoHole(mVideoHoleEnabled);
465 void WebView::EnableBlendMode(bool blendEnabled)
468 for(uint32_t i = 0; i < self.GetRendererCount(); i++)
470 Dali::Renderer render = self.GetRendererAt(i);
471 render.SetProperty(Renderer::Property::BLEND_MODE, blendEnabled ? BlendMode::ON : BlendMode::OFF);
475 void WebView::ClearAllTilesResources()
479 mWebEngine.ClearAllTilesResources();
483 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadStartedSignal()
485 return mPageLoadStartedSignal;
488 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadInProgressSignal()
490 return mPageLoadInProgressSignal;
493 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadFinishedSignal()
495 return mPageLoadFinishedSignal;
498 Dali::Toolkit::WebView::WebViewPageLoadErrorSignalType& WebView::PageLoadErrorSignal()
500 return mPageLoadErrorSignal;
503 Dali::Toolkit::WebView::WebViewScrollEdgeReachedSignalType& WebView::ScrollEdgeReachedSignal()
505 return mScrollEdgeReachedSignal;
508 Dali::Toolkit::WebView::WebViewUrlChangedSignalType& WebView::UrlChangedSignal()
510 return mUrlChangedSignal;
513 void WebView::OnPageLoadStarted( const std::string& url )
515 if(!mPageLoadStartedSignal.Empty())
517 Dali::Toolkit::WebView handle(GetOwner());
518 mPageLoadStartedSignal.Emit(handle, url);
522 void WebView::OnPageLoadInProgress( const std::string& url )
524 if ( !mPageLoadInProgressSignal.Empty() )
526 Dali::Toolkit::WebView handle( GetOwner() );
527 mPageLoadInProgressSignal.Emit( handle, url );
531 void WebView::OnPageLoadFinished( const std::string& url )
533 if(!mPageLoadFinishedSignal.Empty())
535 Dali::Toolkit::WebView handle(GetOwner());
536 mPageLoadFinishedSignal.Emit(handle, url);
540 void WebView::OnPageLoadError(const std::string& url, int errorCode)
542 if(!mPageLoadErrorSignal.Empty())
544 Dali::Toolkit::WebView handle(GetOwner());
545 mPageLoadErrorSignal.Emit(handle, url, static_cast<Toolkit::WebView::LoadErrorCode>(errorCode));
549 void WebView::OnScrollEdgeReached(Dali::WebEnginePlugin::ScrollEdge edge)
551 if(!mScrollEdgeReachedSignal.Empty())
553 Dali::Toolkit::WebView handle(GetOwner());
554 mScrollEdgeReachedSignal.Emit(handle, edge);
558 void WebView::OnUrlChanged(const std::string& url)
560 if (!mUrlChangedSignal.Empty())
562 Dali::Toolkit::WebView handle(GetOwner());
563 mUrlChangedSignal.Emit(handle, url);
567 bool WebView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
569 Dali::BaseHandle handle(object);
571 bool connected = false;
572 Toolkit::WebView webView = Toolkit::WebView::DownCast(handle);
574 if(0 == strcmp(signalName.c_str(), PAGE_LOAD_STARTED_SIGNAL))
576 webView.PageLoadStartedSignal().Connect(tracker, functor);
579 else if (0 == strcmp(signalName.c_str(), PAGE_LOAD_IN_PROGRESS_SIGNAL))
581 webView.PageLoadInProgressSignal().Connect(tracker, functor);
584 else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_FINISHED_SIGNAL))
586 webView.PageLoadFinishedSignal().Connect(tracker, functor);
589 else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_ERROR_SIGNAL))
591 webView.PageLoadErrorSignal().Connect(tracker, functor);
594 else if(0 == strcmp(signalName.c_str(), SCROLL_EDGE_REACHED_SIGNAL))
596 webView.ScrollEdgeReachedSignal().Connect(tracker, functor);
599 else if (0 == strcmp(signalName.c_str(), URL_CHANGED_SIGNAL))
601 webView.UrlChangedSignal().Connect( tracker, functor );
608 Vector3 WebView::GetNaturalSize()
612 Vector2 rendererNaturalSize;
613 mVisual.GetNaturalSize(rendererNaturalSize);
614 return Vector3(rendererNaturalSize);
617 return Vector3(mWebViewSize);
620 void WebView::OnSceneConnection(int depth)
622 Control::OnSceneConnection(depth);
624 EnableBlendMode(!mVideoHoleEnabled);
627 void WebView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
629 Toolkit::WebView webView = Toolkit::WebView::DownCast(Dali::BaseHandle(object));
633 WebView& impl = GetImpl(webView);
636 case Toolkit::WebView::Property::URL:
645 case Toolkit::WebView::Property::USER_AGENT:
650 impl.SetUserAgent(input);
654 case Toolkit::WebView::Property::SCROLL_POSITION:
659 impl.SetScrollPosition(input.x, input.y);
663 case Toolkit::WebView::Property::VIDEO_HOLE_ENABLED:
668 impl.EnableVideoHole(input);
676 Property::Value WebView::GetProperty(BaseObject* object, Property::Index propertyIndex)
678 Property::Value value;
680 Toolkit::WebView webView = Toolkit::WebView::DownCast(Dali::BaseHandle(object));
684 WebView& impl = GetImpl(webView);
685 switch(propertyIndex)
687 case Toolkit::WebView::Property::URL:
692 case Toolkit::WebView::Property::USER_AGENT:
694 value = impl.GetUserAgent();
697 case Toolkit::WebView::Property::SCROLL_POSITION:
699 value = impl.GetScrollPosition();
702 case Toolkit::WebView::Property::SCROLL_SIZE:
704 value = impl.GetScrollSize();
707 case Toolkit::WebView::Property::CONTENT_SIZE:
709 value = impl.GetContentSize();
712 case Toolkit::WebView::Property::TITLE:
714 value = impl.GetTitle();
717 case Toolkit::WebView::Property::VIDEO_HOLE_ENABLED:
719 value = impl.mVideoHoleEnabled;
730 bool WebView::OnTouchEvent(Actor actor, const Dali::TouchEvent& touch)
736 result = mWebEngine.SendTouchEvent(touch);
741 bool WebView::OnKeyEvent(const Dali::KeyEvent& event)
747 result = mWebEngine.SendKeyEvent(event);
752 void WebView::OnKeyInputFocusGained()
756 mWebEngine.SetFocus(true);
759 EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
762 void WebView::OnKeyInputFocusLost()
766 mWebEngine.SetFocus(false);
769 EmitKeyInputFocusSignal(false); // Calls back into the Control hence done last.
772 void WebView::SetScrollPosition(int x, int y)
776 mWebEngine.SetScrollPosition(x, y);
780 Dali::Vector2 WebView::GetScrollPosition() const
782 return mWebEngine ? mWebEngine.GetScrollPosition() : Dali::Vector2::ZERO;
785 Dali::Vector2 WebView::GetScrollSize() const
787 return mWebEngine ? mWebEngine.GetScrollSize() : Dali::Vector2::ZERO;
790 Dali::Vector2 WebView::GetContentSize() const
792 return mWebEngine ? mWebEngine.GetContentSize() : Dali::Vector2::ZERO;
795 std::string WebView::GetTitle() const
797 return mWebEngine ? mWebEngine.GetTitle() : kEmptyString;
800 const std::string& WebView::GetUserAgent() const
802 return mWebEngine ? mWebEngine.GetUserAgent() : kEmptyString;
805 void WebView::SetUserAgent(const std::string& userAgent)
809 mWebEngine.SetUserAgent(userAgent);
813 #undef GET_ENUM_STRING
814 #undef GET_ENUM_VALUE
816 } // namespace Internal
818 } // namespace Toolkit