Merge "Add APIs for intercepting http request in web view." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / web-view / web-view-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "web-view-impl.h"
20
21 // EXTERNAL INCLUDES
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-form-repost-decision.h>
26 #include <dali/devel-api/adaptor-framework/web-engine-request-interceptor.h>
27 #include <dali/devel-api/adaptor-framework/web-engine-settings.h>
28 #include <dali/devel-api/common/stage.h>
29 #include <dali/devel-api/scripting/enum-helper.h>
30 #include <dali/devel-api/scripting/scripting.h>
31 #include <dali/public-api/adaptor-framework/native-image-source.h>
32 #include <dali/public-api/object/type-registry-helper.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <cstring>
35 #include <memory>
36
37 // INTERNAL INCLUDES
38 #include <dali-toolkit/devel-api/controls/control-devel.h>
39 #include <dali-toolkit/devel-api/controls/web-view/web-back-forward-list.h>
40 #include <dali-toolkit/devel-api/controls/web-view/web-context.h>
41 #include <dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h>
42 #include <dali-toolkit/devel-api/controls/web-view/web-form-repost-decision.h>
43 #include <dali-toolkit/devel-api/controls/web-view/web-settings.h>
44 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
45 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
46 #include <dali-toolkit/public-api/image-loader/image.h>
47 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
48
49 namespace Dali
50 {
51 namespace Toolkit
52 {
53 namespace Internal
54 {
55 namespace
56 {
57 BaseHandle Create()
58 {
59   return Toolkit::WebView::New();
60 }
61
62 // clang-format off
63 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::WebView, Toolkit::Control, Create)
64
65 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "url",                     STRING,  URL                       )
66 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "userAgent",               STRING,  USER_AGENT                )
67 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "scrollPosition",          VECTOR2, SCROLL_POSITION           )
68 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "scrollSize",              VECTOR2, SCROLL_SIZE               )
69 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "contentSize",             VECTOR2, CONTENT_SIZE              )
70 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "title",                   STRING,  TITLE                     )
71 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "videoHoleEnabled",        BOOLEAN, VIDEO_HOLE_ENABLED        )
72 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "mouseEventsEnabled",      BOOLEAN, MOUSE_EVENTS_ENABLED      )
73 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "keyEventsEnabled",        BOOLEAN, KEY_EVENTS_ENABLED        )
74 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "documentBackgroundColor", VECTOR4, DOCUMENT_BACKGROUND_COLOR )
75 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "tilesClearedWhenHidden",  BOOLEAN, TILES_CLEARED_WHEN_HIDDEN )
76 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "tileCoverAreaMultiplier", FLOAT,   TILE_COVER_AREA_MULTIPLIER)
77 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "cursorEnabledByClient",   BOOLEAN, CURSOR_ENABLED_BY_CLIENT  )
78 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "selectedText",            STRING,  SELECTED_TEXT             )
79 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "pageZoomFactor",          FLOAT,   PAGE_ZOOM_FACTOR          )
80 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "textZoomFactor",          FLOAT,   TEXT_ZOOM_FACTOR          )
81 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "loadProgressPercentage",  FLOAT,   LOAD_PROGRESS_PERCENTAGE  )
82
83 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadStarted",    PAGE_LOAD_STARTED_SIGNAL    )
84 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadInProgress", PAGE_LOAD_IN_PROGRESS_SIGNAL)
85 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadFinished",   PAGE_LOAD_FINISHED_SIGNAL   )
86 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadError",      PAGE_LOAD_ERROR_SIGNAL      )
87 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "scrollEdgeReached",  SCROLL_EDGE_REACHED_SIGNAL  )
88 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "urlChanged",         URL_CHANGED_SIGNAL          )
89 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "formRepostDecision", FORM_REPOST_DECISION_SIGNAL )
90 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "frameRendered",      FRAME_RENDERED_SIGNAL       )
91 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "requestInterceptor", REQUEST_INTERCEPTOR_SIGNAL  )
92
93 DALI_TYPE_REGISTRATION_END()
94 // clang-format on
95
96 const std::string kEmptyString;
97
98 } // namespace
99
100 #define GET_ENUM_STRING(structName, inputExp) \
101   Scripting::GetLinearEnumerationName<Toolkit::WebView::structName::Type>(static_cast<Toolkit::WebView::structName::Type>(inputExp), structName##_TABLE, structName##_TABLE_COUNT)
102
103 #define GET_ENUM_VALUE(structName, inputExp, outputExp) \
104   Scripting::GetEnumerationProperty<Toolkit::WebView::structName::Type>(inputExp, structName##_TABLE, structName##_TABLE_COUNT, outputExp)
105
106 WebView::WebView(const std::string& locale, const std::string& timezoneId)
107 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
108   mUrl(),
109   mVisual(),
110   mWebViewSize(Stage::GetCurrent().GetSize()),
111   mWebEngine(),
112   mPageLoadStartedSignal(),
113   mPageLoadFinishedSignal(),
114   mPageLoadErrorSignal(),
115   mUrlChangedSignal(),
116   mVideoHoleEnabled(true),
117   mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height),
118   mMouseEventsEnabled(true),
119   mKeyEventsEnabled(true)
120 {
121   mWebEngine = Dali::WebEngine::New();
122
123   // WebEngine is empty when it is not properly initialized.
124   if(mWebEngine)
125   {
126     mWebEngine.Create(mWebViewSize.width, mWebViewSize.height, locale, timezoneId);
127   }
128 }
129
130 WebView::WebView(int argc, char** argv)
131 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
132   mUrl(),
133   mVisual(),
134   mWebViewSize(Stage::GetCurrent().GetSize()),
135   mWebEngine(),
136   mPageLoadStartedSignal(),
137   mPageLoadFinishedSignal(),
138   mPageLoadErrorSignal(),
139   mUrlChangedSignal(),
140   mVideoHoleEnabled(true),
141   mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height),
142   mMouseEventsEnabled(true),
143   mKeyEventsEnabled(true)
144 {
145   mWebEngine = Dali::WebEngine::New();
146
147   // WebEngine is empty when it is not properly initialized.
148   if(mWebEngine)
149   {
150     mWebEngine.Create(mWebViewSize.width, mWebViewSize.height, argc, argv);
151   }
152 }
153
154 WebView::WebView()
155 : WebView("", "")
156 {
157 }
158
159 WebView::~WebView()
160 {
161   if(mWebEngine)
162   {
163     mWebEngine.Destroy();
164   }
165 }
166
167 Toolkit::WebView WebView::New()
168 {
169   WebView*         impl   = new WebView();
170   Toolkit::WebView handle = Toolkit::WebView(*impl);
171
172   impl->Initialize();
173   return handle;
174 }
175
176 Toolkit::WebView WebView::New(const std::string& locale, const std::string& timezoneId)
177 {
178   WebView*         impl   = new WebView(locale, timezoneId);
179   Toolkit::WebView handle = Toolkit::WebView(*impl);
180
181   impl->Initialize();
182   return handle;
183 }
184
185 Toolkit::WebView WebView::New(int argc, char** argv)
186 {
187   WebView*         impl   = new WebView(argc, argv);
188   Toolkit::WebView handle = Toolkit::WebView(*impl);
189
190   impl->Initialize();
191   return handle;
192 }
193
194 void WebView::OnInitialize()
195 {
196   Actor self = Self();
197
198   self.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
199   self.TouchedSignal().Connect(this, &WebView::OnTouchEvent);
200   self.HoveredSignal().Connect(this, &WebView::OnHoverEvent);
201   self.WheelEventSignal().Connect(this, &WebView::OnWheelEvent);
202   Dali::DevelActor::VisibilityChangedSignal(self).Connect(this, &WebView::OnVisibilityChanged);
203
204   mPositionUpdateNotification = self.AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
205   mSizeUpdateNotification     = self.AddPropertyNotification(Actor::Property::SIZE, StepCondition(1.0f, 1.0f));
206   mScaleUpdateNotification    = self.AddPropertyNotification(Actor::Property::WORLD_SCALE, StepCondition(0.1f, 1.0f));
207   mPositionUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
208   mSizeUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
209   mScaleUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
210
211   if(mWebEngine)
212   {
213     mWebEngine.PageLoadStartedSignal().Connect(this, &WebView::OnPageLoadStarted);
214     mWebEngine.PageLoadInProgressSignal().Connect(this, &WebView::OnPageLoadInProgress);
215     mWebEngine.PageLoadFinishedSignal().Connect(this, &WebView::OnPageLoadFinished);
216     mWebEngine.PageLoadErrorSignal().Connect(this, &WebView::OnPageLoadError);
217     mWebEngine.ScrollEdgeReachedSignal().Connect(this, &WebView::OnScrollEdgeReached);
218     mWebEngine.UrlChangedSignal().Connect(this, &WebView::OnUrlChanged);
219     mWebEngine.FormRepostDecisionSignal().Connect(this, &WebView::OnFormRepostDecision);
220     mWebEngine.FrameRenderedSignal().Connect(this, &WebView::OnFrameRendered);
221     mWebEngine.RequestInterceptorSignal().Connect(this, &WebView::OnInterceptRequest);
222
223     mWebContext         = std::unique_ptr<Dali::Toolkit::WebContext>(new WebContext(mWebEngine.GetContext()));
224     mWebCookieManager   = std::unique_ptr<Dali::Toolkit::WebCookieManager>(new WebCookieManager(mWebEngine.GetCookieManager()));
225     mWebSettings        = std::unique_ptr<Dali::Toolkit::WebSettings>(new WebSettings(mWebEngine.GetSettings()));
226     mWebBackForwardList = std::unique_ptr<Dali::Toolkit::WebBackForwardList>(new WebBackForwardList(mWebEngine.GetBackForwardList()));
227   }
228 }
229
230 Dali::Toolkit::WebSettings* WebView::GetSettings() const
231 {
232   return mWebSettings.get();
233 }
234
235 Dali::Toolkit::WebContext* WebView::GetContext() const
236 {
237   return mWebContext.get();
238 }
239
240 Dali::Toolkit::WebCookieManager* WebView::GetCookieManager() const
241 {
242   return mWebCookieManager.get();
243 }
244
245 Dali::Toolkit::WebBackForwardList* WebView::GetBackForwardList() const
246 {
247   return mWebBackForwardList.get();
248 }
249
250 Dali::Toolkit::ImageView& WebView::GetFavicon()
251 {
252   if(mWebEngine)
253   {
254     Dali::PixelData pixelData = mWebEngine.GetFavicon();
255     mFaviconView              = CreateImageView(pixelData);
256   }
257   return mFaviconView;
258 }
259
260 void WebView::LoadUrl(const std::string& url)
261 {
262   mUrl = url;
263   if(mWebEngine)
264   {
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}});
270
271     if(mVisual)
272     {
273       // Clean up previously registered visual and add new one.
274       DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
275       mWebEngine.LoadUrl(url);
276     }
277
278     if(mVideoHoleEnabled)
279     {
280       EnableBlendMode(false);
281     }
282   }
283 }
284
285 void WebView::LoadHtmlString(const std::string& htmlString)
286 {
287   if(mWebEngine)
288   {
289     Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
290     const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
291     mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
292       {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
293        {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
294
295     if(mVisual)
296     {
297       DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
298       mWebEngine.LoadHtmlString(htmlString);
299     }
300
301     if(mVideoHoleEnabled)
302     {
303       EnableBlendMode(false);
304     }
305   }
306 }
307
308 bool WebView::LoadHtmlStringOverrideCurrentEntry(const std::string& html, const std::string& basicUri, const std::string& unreachableUrl)
309 {
310   if(!mWebEngine)
311     return false;
312
313   Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
314   const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
315   mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
316     {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
317      {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
318
319   bool result = false;
320   if(mVisual)
321   {
322     DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
323     result = mWebEngine.LoadHtmlStringOverrideCurrentEntry(html, basicUri, unreachableUrl);
324   }
325
326   if(mVideoHoleEnabled)
327   {
328     EnableBlendMode(false);
329   }
330   return result;
331 }
332
333 bool WebView::LoadContents(const std::string& contents, uint32_t contentSize, const std::string& mimeType, const std::string& encoding, const std::string& baseUri)
334 {
335   if(!mWebEngine)
336     return false;
337
338   Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
339   const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
340   mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
341     {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
342      {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
343
344   bool result = false;
345   if(mVisual)
346   {
347     DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
348     result = mWebEngine.LoadContents(contents, contentSize, mimeType, encoding, baseUri);
349   }
350
351   if(mVideoHoleEnabled)
352   {
353     EnableBlendMode(false);
354   }
355   return result;
356 }
357
358 void WebView::Reload()
359 {
360   if(mWebEngine)
361   {
362     mWebEngine.Reload();
363   }
364 }
365
366 bool WebView::ReloadWithoutCache()
367 {
368   return mWebEngine ? mWebEngine.ReloadWithoutCache() : false;
369 }
370
371 void WebView::StopLoading()
372 {
373   if(mWebEngine)
374   {
375     mWebEngine.StopLoading();
376   }
377 }
378
379 void WebView::Suspend()
380 {
381   if(mWebEngine)
382   {
383     mWebEngine.Suspend();
384   }
385 }
386
387 void WebView::Resume()
388 {
389   if(mWebEngine)
390   {
391     mWebEngine.Resume();
392   }
393 }
394
395 void WebView::SuspendNetworkLoading()
396 {
397   if(mWebEngine)
398   {
399     mWebEngine.SuspendNetworkLoading();
400   }
401 }
402
403 void WebView::ResumeNetworkLoading()
404 {
405   if(mWebEngine)
406   {
407     mWebEngine.ResumeNetworkLoading();
408   }
409 }
410
411 bool WebView::AddCustomHeader(const std::string& name, const std::string& value)
412 {
413   return mWebEngine ? mWebEngine.AddCustomHeader(name, value) : false;
414 }
415
416 bool WebView::RemoveCustomHeader(const std::string& name)
417 {
418   return mWebEngine ? mWebEngine.RemoveCustomHeader(name) : false;
419 }
420
421 uint32_t WebView::StartInspectorServer(uint32_t port)
422 {
423   return mWebEngine ? mWebEngine.StartInspectorServer(port) : false;
424 }
425
426 bool WebView::StopInspectorServer()
427 {
428   return mWebEngine ? mWebEngine.StopInspectorServer() : false;
429 }
430
431 void WebView::ScrollBy(int deltaX, int deltaY)
432 {
433   if(mWebEngine)
434   {
435     mWebEngine.ScrollBy(deltaX, deltaY);
436   }
437 }
438
439 bool WebView::ScrollEdgeBy(int deltaX, int deltaY)
440 {
441   return mWebEngine ? mWebEngine.ScrollEdgeBy(deltaX, deltaY) : false;
442 }
443
444 bool WebView::CanGoForward()
445 {
446   return mWebEngine ? mWebEngine.CanGoForward() : false;
447 }
448
449 void WebView::GoForward()
450 {
451   if(mWebEngine)
452   {
453     mWebEngine.GoForward();
454   }
455 }
456
457 bool WebView::CanGoBack()
458 {
459   return mWebEngine ? mWebEngine.CanGoBack() : false;
460 }
461
462 void WebView::GoBack()
463 {
464   if(mWebEngine)
465   {
466     mWebEngine.GoBack();
467   }
468 }
469
470 void WebView::EvaluateJavaScript(const std::string& script, std::function<void(const std::string&)> resultHandler)
471 {
472   if(mWebEngine)
473   {
474     mWebEngine.EvaluateJavaScript(script, resultHandler);
475   }
476 }
477
478 void WebView::AddJavaScriptMessageHandler(const std::string& exposedObjectName, std::function<void(const std::string&)> handler)
479 {
480   if(mWebEngine)
481   {
482     mWebEngine.AddJavaScriptMessageHandler(exposedObjectName, handler);
483   }
484 }
485
486 void WebView::RegisterJavaScriptAlertCallback(Dali::WebEnginePlugin::JavaScriptAlertCallback callback)
487 {
488   if(mWebEngine)
489   {
490     mWebEngine.RegisterJavaScriptAlertCallback(callback);
491   }
492 }
493
494 void WebView::JavaScriptAlertReply()
495 {
496   if(mWebEngine)
497   {
498     mWebEngine.JavaScriptAlertReply();
499   }
500 }
501
502 void WebView::RegisterJavaScriptConfirmCallback(Dali::WebEnginePlugin::JavaScriptConfirmCallback callback)
503 {
504   if(mWebEngine)
505   {
506     mWebEngine.RegisterJavaScriptConfirmCallback(callback);
507   }
508 }
509
510 void WebView::JavaScriptConfirmReply(bool confirmed)
511 {
512   if(mWebEngine)
513   {
514     mWebEngine.JavaScriptConfirmReply(confirmed);
515   }
516 }
517
518 void WebView::RegisterJavaScriptPromptCallback(Dali::WebEnginePlugin::JavaScriptPromptCallback callback)
519 {
520   if(mWebEngine)
521   {
522     mWebEngine.RegisterJavaScriptPromptCallback(callback);
523   }
524 }
525
526 void WebView::JavaScriptPromptReply(const std::string& result)
527 {
528   if(mWebEngine)
529   {
530     mWebEngine.JavaScriptPromptReply(result);
531   }
532 }
533
534 void WebView::ClearHistory()
535 {
536   if(mWebEngine)
537   {
538     mWebEngine.ClearHistory();
539   }
540 }
541
542 void WebView::ClearAllTilesResources()
543 {
544   if(mWebEngine)
545   {
546     mWebEngine.ClearAllTilesResources();
547   }
548 }
549
550 void WebView::SetScaleFactor(float scaleFactor, Dali::Vector2 point)
551 {
552   if(mWebEngine)
553   {
554     mWebEngine.SetScaleFactor(scaleFactor, point);
555   }
556 }
557
558 float WebView::GetScaleFactor() const
559 {
560   return mWebEngine ? mWebEngine.GetScaleFactor() : 0.0f;
561 }
562
563 void WebView::ActivateAccessibility(bool activated)
564 {
565   if(mWebEngine)
566   {
567     mWebEngine.ActivateAccessibility(activated);
568   }
569 }
570
571 bool WebView::HighlightText(const std::string& text, Dali::WebEnginePlugin::FindOption options, uint32_t maxMatchCount)
572 {
573   return mWebEngine ? mWebEngine.HighlightText(text, options, maxMatchCount) : false;
574 }
575
576 void WebView::AddDynamicCertificatePath(const std::string& host, const std::string& certPath)
577 {
578   if(mWebEngine)
579   {
580     mWebEngine.AddDynamicCertificatePath(host, certPath);
581   }
582 }
583
584 Dali::Toolkit::ImageView WebView::GetScreenshot(Dali::Rect<int> viewArea, float scaleFactor)
585 {
586   Dali::Toolkit::ImageView imageView;
587   if(mWebEngine)
588   {
589     Dali::PixelData pixelData = mWebEngine.GetScreenshot(viewArea, scaleFactor);
590     imageView                 = CreateImageView(pixelData);
591   }
592   return imageView;
593 }
594
595 bool WebView::GetScreenshotAsynchronously(Dali::Rect<int> viewArea, float scaleFactor, Dali::Toolkit::WebView::WebViewScreenshotCapturedCallback callback)
596 {
597   mScreenshotCapturedCallback = callback;
598   return mWebEngine ? mWebEngine.GetScreenshotAsynchronously(viewArea, scaleFactor, std::bind(&WebView::OnScreenshotCaptured, this, std::placeholders::_1)) : false;
599 }
600
601 bool WebView::CheckVideoPlayingAsynchronously(Dali::WebEnginePlugin::VideoPlayingCallback callback)
602 {
603   return mWebEngine ? mWebEngine.CheckVideoPlayingAsynchronously(callback) : false;
604 }
605
606 void WebView::RegisterGeolocationPermissionCallback(Dali::WebEnginePlugin::GeolocationPermissionCallback callback)
607 {
608   if(mWebEngine)
609   {
610     mWebEngine.RegisterGeolocationPermissionCallback(callback);
611   }
612 }
613
614 void WebView::UpdateDisplayArea(Dali::PropertyNotification& /*source*/)
615 {
616   if(!mWebEngine)
617     return;
618
619   Actor self(Self());
620
621   bool    positionUsesAnchorPoint = self.GetProperty<bool>(Actor::Property::POSITION_USES_ANCHOR_POINT);
622   Vector3 actorSize               = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * self.GetCurrentProperty<Vector3>(Actor::Property::SCALE);
623   Vector3 anchorPointOffSet       = actorSize * (positionUsesAnchorPoint ? self.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
624   Vector2 screenPosition          = self.GetProperty<Vector2>(Actor::Property::SCREEN_POSITION);
625
626   Dali::Rect<int> displayArea;
627   displayArea.x      = screenPosition.x - anchorPointOffSet.x;
628   displayArea.y      = screenPosition.y - anchorPointOffSet.y;
629   displayArea.width  = actorSize.x;
630   displayArea.height = actorSize.y;
631
632   Size displaySize = Size(displayArea.width, displayArea.height);
633   if(mWebViewSize != displaySize)
634   {
635     mWebViewSize = displaySize;
636   }
637
638   if(mWebViewArea != displayArea)
639   {
640     mWebViewArea = displayArea;
641     mWebEngine.UpdateDisplayArea(mWebViewArea);
642   }
643 }
644
645 void WebView::EnableVideoHole(bool enabled)
646 {
647   mVideoHoleEnabled = enabled;
648
649   EnableBlendMode(!mVideoHoleEnabled);
650
651   if(mWebEngine)
652   {
653     mWebEngine.EnableVideoHole(mVideoHoleEnabled);
654   }
655 }
656
657 void WebView::EnableBlendMode(bool blendEnabled)
658 {
659   Actor self = Self();
660   for(uint32_t i = 0; i < self.GetRendererCount(); i++)
661   {
662     Dali::Renderer render = self.GetRendererAt(i);
663     render.SetProperty(Renderer::Property::BLEND_MODE, blendEnabled ? BlendMode::ON : BlendMode::OFF);
664   }
665 }
666
667 Dali::Toolkit::ImageView WebView::CreateImageView(Dali::PixelData pixel)
668 {
669   std::string              url       = Dali::Toolkit::Image::GenerateUrl(pixel);
670   Dali::Toolkit::ImageView imageView = Dali::Toolkit::ImageView::New(url);
671   imageView.SetProperty(Dali::Actor::Property::SIZE, Vector2(pixel.GetWidth(), pixel.GetHeight()));
672   return imageView;
673 }
674
675 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadStartedSignal()
676 {
677   return mPageLoadStartedSignal;
678 }
679
680 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadInProgressSignal()
681 {
682   return mPageLoadInProgressSignal;
683 }
684
685 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadFinishedSignal()
686 {
687   return mPageLoadFinishedSignal;
688 }
689
690 Dali::Toolkit::WebView::WebViewPageLoadErrorSignalType& WebView::PageLoadErrorSignal()
691 {
692   return mPageLoadErrorSignal;
693 }
694
695 Dali::Toolkit::WebView::WebViewScrollEdgeReachedSignalType& WebView::ScrollEdgeReachedSignal()
696 {
697   return mScrollEdgeReachedSignal;
698 }
699
700 Dali::Toolkit::WebView::WebViewUrlChangedSignalType& WebView::UrlChangedSignal()
701 {
702   return mUrlChangedSignal;
703 }
704
705 Dali::Toolkit::WebView::WebViewFormRepostDecisionSignalType& WebView::FormRepostDecisionSignal()
706 {
707   return mFormRepostDecisionSignal;
708 }
709
710 Dali::Toolkit::WebView::WebViewFrameRenderedSignalType& WebView::FrameRenderedSignal()
711 {
712   return mFrameRenderedSignal;
713 }
714
715 Dali::Toolkit::WebView::WebViewRequestInterceptorSignalType& WebView::RequestInterceptorSignal()
716 {
717   return mRequestInterceptorSignal;
718 }
719
720 void WebView::OnPageLoadStarted(const std::string& url)
721 {
722   if(!mPageLoadStartedSignal.Empty())
723   {
724     Dali::Toolkit::WebView handle(GetOwner());
725     mPageLoadStartedSignal.Emit(handle, url);
726   }
727 }
728
729 void WebView::OnPageLoadInProgress(const std::string& url)
730 {
731   if(!mPageLoadInProgressSignal.Empty())
732   {
733     Dali::Toolkit::WebView handle(GetOwner());
734     mPageLoadInProgressSignal.Emit(handle, url);
735   }
736 }
737
738 void WebView::OnPageLoadFinished(const std::string& url)
739 {
740   if(!mPageLoadFinishedSignal.Empty())
741   {
742     Dali::Toolkit::WebView handle(GetOwner());
743     mPageLoadFinishedSignal.Emit(handle, url);
744   }
745 }
746
747 void WebView::OnPageLoadError(const std::string& url, int errorCode)
748 {
749   if(!mPageLoadErrorSignal.Empty())
750   {
751     Dali::Toolkit::WebView handle(GetOwner());
752     mPageLoadErrorSignal.Emit(handle, url, static_cast<Toolkit::WebView::LoadErrorCode>(errorCode));
753   }
754 }
755
756 void WebView::OnScrollEdgeReached(Dali::WebEnginePlugin::ScrollEdge edge)
757 {
758   if(!mScrollEdgeReachedSignal.Empty())
759   {
760     Dali::Toolkit::WebView handle(GetOwner());
761     mScrollEdgeReachedSignal.Emit(handle, edge);
762   }
763 }
764
765 void WebView::OnUrlChanged(const std::string& url)
766 {
767   if(!mUrlChangedSignal.Empty())
768   {
769     Dali::Toolkit::WebView handle(GetOwner());
770     mUrlChangedSignal.Emit(handle, url);
771   }
772 }
773
774 void WebView::OnFormRepostDecision(std::shared_ptr<Dali::WebEngineFormRepostDecision> decision)
775 {
776   if(!mFormRepostDecisionSignal.Empty())
777   {
778     Dali::Toolkit::WebView                                handle(GetOwner());
779     std::shared_ptr<Dali::Toolkit::WebFormRepostDecision> repostDecision(new Dali::Toolkit::WebFormRepostDecision(decision));
780     mFormRepostDecisionSignal.Emit(handle, std::move(repostDecision));
781   }
782 }
783
784 void WebView::OnFrameRendered()
785 {
786   if(!mFrameRenderedSignal.Empty())
787   {
788     Dali::Toolkit::WebView handle(GetOwner());
789     mFrameRenderedSignal.Emit(handle);
790   }
791 }
792
793 void WebView::OnVisibilityChanged(Actor actor, bool isVisible, Dali::DevelActor::VisibilityChange::Type type)
794 {
795   if(type == Dali::DevelActor::VisibilityChange::Type::SELF)
796   {
797     SetVisibility(isVisible);
798   }
799 }
800
801 void WebView::OnScreenshotCaptured(Dali::PixelData pixel)
802 {
803   if(mScreenshotCapturedCallback)
804   {
805     Dali::Toolkit::ImageView imageView = CreateImageView(pixel);
806     mScreenshotCapturedCallback(imageView);
807   }
808 }
809
810 void WebView::OnInterceptRequest(std::shared_ptr<Dali::WebEngineRequestInterceptor> interceptor)
811 {
812   if(!mRequestInterceptorSignal.Empty())
813   {
814     Dali::Toolkit::WebView handle(GetOwner());
815     mRequestInterceptorSignal.Emit(handle, std::move(interceptor));
816   }
817 }
818
819 bool WebView::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
820 {
821   Dali::BaseHandle handle(object);
822
823   bool             connected = false;
824   Toolkit::WebView webView   = Toolkit::WebView::DownCast(handle);
825
826   if(0 == strcmp(signalName.c_str(), PAGE_LOAD_STARTED_SIGNAL))
827   {
828     webView.PageLoadStartedSignal().Connect(tracker, functor);
829     connected = true;
830   }
831   else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_IN_PROGRESS_SIGNAL))
832   {
833     webView.PageLoadInProgressSignal().Connect(tracker, functor);
834     connected = true;
835   }
836   else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_FINISHED_SIGNAL))
837   {
838     webView.PageLoadFinishedSignal().Connect(tracker, functor);
839     connected = true;
840   }
841   else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_ERROR_SIGNAL))
842   {
843     webView.PageLoadErrorSignal().Connect(tracker, functor);
844     connected = true;
845   }
846   else if(0 == strcmp(signalName.c_str(), SCROLL_EDGE_REACHED_SIGNAL))
847   {
848     webView.ScrollEdgeReachedSignal().Connect(tracker, functor);
849     connected = true;
850   }
851   else if(0 == strcmp(signalName.c_str(), URL_CHANGED_SIGNAL))
852   {
853     webView.UrlChangedSignal().Connect(tracker, functor);
854     connected = true;
855   }
856   else if(0 == strcmp(signalName.c_str(), FORM_REPOST_DECISION_SIGNAL))
857   {
858     webView.FormRepostDecisionSignal().Connect(tracker, functor);
859     connected = true;
860   }
861   else if(0 == strcmp(signalName.c_str(), FRAME_RENDERED_SIGNAL))
862   {
863     webView.FrameRenderedSignal().Connect(tracker, functor);
864     connected = true;
865   }
866   else if(0 == strcmp(signalName.c_str(), REQUEST_INTERCEPTOR_SIGNAL))
867   {
868     webView.RequestInterceptorSignal().Connect(tracker, functor);
869     connected = true;
870   }
871
872   return connected;
873 }
874
875 Vector3 WebView::GetNaturalSize()
876 {
877   if(mVisual)
878   {
879     Vector2 rendererNaturalSize;
880     mVisual.GetNaturalSize(rendererNaturalSize);
881     return Vector3(rendererNaturalSize);
882   }
883
884   return Vector3(mWebViewSize);
885 }
886
887 void WebView::OnSceneConnection(int depth)
888 {
889   Control::OnSceneConnection(depth);
890
891   EnableBlendMode(!mVideoHoleEnabled);
892 }
893
894 void WebView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
895 {
896   Toolkit::WebView webView = Toolkit::WebView::DownCast(Dali::BaseHandle(object));
897
898   if(webView)
899   {
900     WebView& impl = GetImpl(webView);
901     switch(index)
902     {
903       case Toolkit::WebView::Property::URL:
904       {
905         std::string url;
906         if(value.Get(url))
907         {
908           impl.LoadUrl(url);
909         }
910         break;
911       }
912       case Toolkit::WebView::Property::USER_AGENT:
913       {
914         std::string input;
915         if(value.Get(input))
916         {
917           impl.SetUserAgent(input);
918         }
919         break;
920       }
921       case Toolkit::WebView::Property::SCROLL_POSITION:
922       {
923         Vector2 input;
924         if(value.Get(input))
925         {
926           impl.SetScrollPosition(input.x, input.y);
927         }
928         break;
929       }
930       case Toolkit::WebView::Property::VIDEO_HOLE_ENABLED:
931       {
932         bool input;
933         if(value.Get(input))
934         {
935           impl.EnableVideoHole(input);
936         }
937         break;
938       }
939       case Toolkit::WebView::Property::MOUSE_EVENTS_ENABLED:
940       {
941         bool input;
942         if(value.Get(input))
943         {
944           impl.EnableMouseEvents(input);
945         }
946         break;
947       }
948       case Toolkit::WebView::Property::KEY_EVENTS_ENABLED:
949       {
950         bool input;
951         if(value.Get(input))
952         {
953           impl.EnableKeyEvents(input);
954         }
955         break;
956       }
957       case Toolkit::WebView::Property::DOCUMENT_BACKGROUND_COLOR:
958       {
959         Vector4 input;
960         if(value.Get(input))
961         {
962           impl.SetDocumentBackgroundColor(input);
963         }
964         break;
965       }
966       case Toolkit::WebView::Property::TILES_CLEARED_WHEN_HIDDEN:
967       {
968         bool input;
969         if(value.Get(input))
970         {
971           impl.ClearTilesWhenHidden(input);
972         }
973         break;
974       }
975       case Toolkit::WebView::Property::TILE_COVER_AREA_MULTIPLIER:
976       {
977         float input;
978         if(value.Get(input))
979         {
980           impl.SetTileCoverAreaMultiplier(input);
981         }
982         break;
983       }
984       case Toolkit::WebView::Property::CURSOR_ENABLED_BY_CLIENT:
985       {
986         bool input;
987         if(value.Get(input))
988         {
989           impl.EnableCursorByClient(input);
990         }
991         break;
992       }
993       case Toolkit::WebView::Property::PAGE_ZOOM_FACTOR:
994       {
995         float input;
996         if(value.Get(input))
997         {
998           impl.SetPageZoomFactor(input);
999         }
1000         break;
1001       }
1002       case Toolkit::WebView::Property::TEXT_ZOOM_FACTOR:
1003       {
1004         float input;
1005         if(value.Get(input))
1006         {
1007           impl.SetTextZoomFactor(input);
1008         }
1009         break;
1010       }
1011       default:
1012         break;
1013     }
1014   }
1015 }
1016
1017 Property::Value WebView::GetProperty(BaseObject* object, Property::Index propertyIndex)
1018 {
1019   Property::Value value;
1020
1021   Toolkit::WebView webView = Toolkit::WebView::DownCast(Dali::BaseHandle(object));
1022
1023   if(webView)
1024   {
1025     WebView& impl = GetImpl(webView);
1026     switch(propertyIndex)
1027     {
1028       case Toolkit::WebView::Property::URL:
1029       {
1030         value = impl.mUrl;
1031         break;
1032       }
1033       case Toolkit::WebView::Property::USER_AGENT:
1034       {
1035         value = impl.GetUserAgent();
1036         break;
1037       }
1038       case Toolkit::WebView::Property::SCROLL_POSITION:
1039       {
1040         value = impl.GetScrollPosition();
1041         break;
1042       }
1043       case Toolkit::WebView::Property::SCROLL_SIZE:
1044       {
1045         value = impl.GetScrollSize();
1046         break;
1047       }
1048       case Toolkit::WebView::Property::CONTENT_SIZE:
1049       {
1050         value = impl.GetContentSize();
1051         break;
1052       }
1053       case Toolkit::WebView::Property::TITLE:
1054       {
1055         value = impl.GetTitle();
1056         break;
1057       }
1058       case Toolkit::WebView::Property::VIDEO_HOLE_ENABLED:
1059       {
1060         value = impl.mVideoHoleEnabled;
1061         break;
1062       }
1063       case Toolkit::WebView::Property::MOUSE_EVENTS_ENABLED:
1064       {
1065         value = impl.mMouseEventsEnabled;
1066         break;
1067       }
1068       case Toolkit::WebView::Property::KEY_EVENTS_ENABLED:
1069       {
1070         value = impl.mKeyEventsEnabled;
1071         break;
1072       }
1073       case Toolkit::WebView::Property::SELECTED_TEXT:
1074       {
1075         value = impl.GetSelectedText();
1076         break;
1077       }
1078       case Toolkit::WebView::Property::PAGE_ZOOM_FACTOR:
1079       {
1080         value = impl.GetPageZoomFactor();
1081         break;
1082       }
1083       case Toolkit::WebView::Property::TEXT_ZOOM_FACTOR:
1084       {
1085         value = impl.GetTextZoomFactor();
1086         break;
1087       }
1088       case Toolkit::WebView::Property::LOAD_PROGRESS_PERCENTAGE:
1089       {
1090         value = impl.GetLoadProgressPercentage();
1091         break;
1092       }
1093       default:
1094         break;
1095     }
1096   }
1097
1098   return value;
1099 }
1100
1101 bool WebView::OnTouchEvent(Actor actor, const Dali::TouchEvent& touch)
1102 {
1103   bool result = false;
1104
1105   if(mWebEngine)
1106   {
1107     result = mWebEngine.SendTouchEvent(touch);
1108   }
1109   return result;
1110 }
1111
1112 bool WebView::OnKeyEvent(const Dali::KeyEvent& event)
1113 {
1114   bool result = false;
1115
1116   if(mWebEngine)
1117   {
1118     result = mWebEngine.SendKeyEvent(event);
1119   }
1120   return result;
1121 }
1122
1123 bool WebView::OnHoverEvent(Actor actor, const Dali::HoverEvent& hover)
1124 {
1125   bool result = false;
1126   if(mWebEngine)
1127   {
1128     result = mWebEngine.SendHoverEvent(hover);
1129   }
1130   return result;
1131 }
1132
1133 bool WebView::OnWheelEvent(Actor actor, const Dali::WheelEvent& wheel)
1134 {
1135   bool result = false;
1136   if(mWebEngine)
1137   {
1138     result = mWebEngine.SendWheelEvent(wheel);
1139   }
1140   return result;
1141 }
1142
1143 void WebView::OnKeyInputFocusGained()
1144 {
1145   if(mWebEngine)
1146   {
1147     mWebEngine.SetFocus(true);
1148   }
1149
1150   EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
1151 }
1152
1153 void WebView::OnKeyInputFocusLost()
1154 {
1155   if(mWebEngine)
1156   {
1157     mWebEngine.SetFocus(false);
1158   }
1159
1160   EmitKeyInputFocusSignal(false); // Calls back into the Control hence done last.
1161 }
1162
1163 void WebView::SetScrollPosition(int x, int y)
1164 {
1165   if(mWebEngine)
1166   {
1167     mWebEngine.SetScrollPosition(x, y);
1168   }
1169 }
1170
1171 Dali::Vector2 WebView::GetScrollPosition() const
1172 {
1173   return mWebEngine ? mWebEngine.GetScrollPosition() : Dali::Vector2::ZERO;
1174 }
1175
1176 Dali::Vector2 WebView::GetScrollSize() const
1177 {
1178   return mWebEngine ? mWebEngine.GetScrollSize() : Dali::Vector2::ZERO;
1179 }
1180
1181 Dali::Vector2 WebView::GetContentSize() const
1182 {
1183   return mWebEngine ? mWebEngine.GetContentSize() : Dali::Vector2::ZERO;
1184 }
1185
1186 std::string WebView::GetTitle() const
1187 {
1188   return mWebEngine ? mWebEngine.GetTitle() : kEmptyString;
1189 }
1190
1191 void WebView::SetDocumentBackgroundColor(Dali::Vector4 color)
1192 {
1193   if(mWebEngine)
1194   {
1195     mWebEngine.SetDocumentBackgroundColor(color);
1196   }
1197 }
1198
1199 void WebView::ClearTilesWhenHidden(bool cleared)
1200 {
1201   if(mWebEngine)
1202   {
1203     mWebEngine.ClearTilesWhenHidden(cleared);
1204   }
1205 }
1206
1207 void WebView::SetTileCoverAreaMultiplier(float multiplier)
1208 {
1209   if(mWebEngine)
1210   {
1211     mWebEngine.SetTileCoverAreaMultiplier(multiplier);
1212   }
1213 }
1214
1215 void WebView::EnableCursorByClient(bool enabled)
1216 {
1217   if(mWebEngine)
1218   {
1219     mWebEngine.EnableCursorByClient(enabled);
1220   }
1221 }
1222
1223 std::string WebView::GetSelectedText() const
1224 {
1225   return mWebEngine ? mWebEngine.GetSelectedText() : kEmptyString;
1226 }
1227
1228 const std::string& WebView::GetUserAgent() const
1229 {
1230   return mWebEngine ? mWebEngine.GetUserAgent() : kEmptyString;
1231 }
1232
1233 void WebView::SetUserAgent(const std::string& userAgent)
1234 {
1235   if(mWebEngine)
1236   {
1237     mWebEngine.SetUserAgent(userAgent);
1238   }
1239 }
1240
1241 void WebView::EnableMouseEvents(bool enabled)
1242 {
1243   if(mWebEngine)
1244   {
1245     mMouseEventsEnabled = enabled;
1246     mWebEngine.EnableMouseEvents(enabled);
1247   }
1248 }
1249
1250 void WebView::EnableKeyEvents(bool enabled)
1251 {
1252   if(mWebEngine)
1253   {
1254     mKeyEventsEnabled = enabled;
1255     mWebEngine.EnableKeyEvents(enabled);
1256   }
1257 }
1258
1259 void WebView::SetPageZoomFactor(float zoomFactor)
1260 {
1261   if(mWebEngine)
1262   {
1263     mWebEngine.SetPageZoomFactor(zoomFactor);
1264   }
1265 }
1266
1267 float WebView::GetPageZoomFactor() const
1268 {
1269   return mWebEngine ? mWebEngine.GetPageZoomFactor() : 0.0f;
1270 }
1271
1272 void WebView::SetTextZoomFactor(float zoomFactor)
1273 {
1274   if(mWebEngine)
1275   {
1276     mWebEngine.SetTextZoomFactor(zoomFactor);
1277   }
1278 }
1279
1280 float WebView::GetTextZoomFactor() const
1281 {
1282   return mWebEngine ? mWebEngine.GetTextZoomFactor() : 0.0f;
1283 }
1284
1285 float WebView::GetLoadProgressPercentage() const
1286 {
1287   return mWebEngine ? mWebEngine.GetLoadProgressPercentage() : 0.0f;
1288 }
1289
1290 bool WebView::SetVisibility(bool visible)
1291 {
1292   return mWebEngine ? mWebEngine.SetVisibility(visible) : false;
1293 }
1294
1295 #undef GET_ENUM_STRING
1296 #undef GET_ENUM_VALUE
1297
1298 } // namespace Internal
1299
1300 } // namespace Toolkit
1301
1302 } // namespace Dali