[M108 Migration] Enable video hole feature
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / eweb_view.cc
1 // Copyright 2014-2020 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "eweb_view.h"
6
7 #include <Ecore_Evas.h>
8 #include <Eina.h>
9 #include <Elementary.h>
10
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h"
15 #include "base/json/json_string_value_serializer.h"
16 #include "base/logging.h"
17 #include "base/pickle.h"
18 #include "base/strings/escape.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/task/task_runner_util.h"
21 #include "browser/javascript_dialog_manager_efl.h"
22 #include "browser/javascript_interface/gin_native_bridge_dispatcher_host.h"
23 #include "browser/navigation_policy_handler_efl.h"
24 #include "browser/quota_permission_context_efl.h"
25 #include "browser/selectpicker/popup_menu_item.h"
26 #include "browser/selectpicker/popup_menu_item_private.h"
27 #include "browser/web_view_browser_message_filter.h"
28 #include "browser/web_view_evas_handler.h"
29 #include "browser_context_efl.h"
30 #include "common/content_client_efl.h"
31 #include "common/render_messages_ewk.h"
32 #include "common/version_info.h"
33 #include "common/web_contents_utils.h"
34 #include "components/sessions/content/content_serialized_navigation_builder.h"
35 #include "components/sessions/core/serialized_navigation_entry.h"
36 #include "content/browser/renderer_host/render_view_host_impl.h"
37 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
38 #include "content/browser/renderer_host/ui_events_helper.h"
39 #include "content/browser/web_contents/web_contents_impl_efl.h"
40 #include "content/browser/web_contents/web_contents_view.h"
41 #include "content/browser/web_contents/web_contents_view_aura.h"
42 #include "content/browser/web_contents/web_contents_view_aura_helper_efl.h"
43 #include "content/common/content_client_export.h"
44 #include "content/public/browser/browser_message_filter.h"
45 #include "content/public/browser/browser_task_traits.h"
46 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/host_zoom_map.h"
48 #include "content/public/browser/navigation_controller.h"
49 #include "content/public/browser/navigation_entry.h"
50 #include "content/public/browser/navigation_handle.h"
51 #include "content/public/common/content_client.h"
52 #include "content/public/common/content_switches.h"
53 #include "content/public/common/mhtml_generation_params.h"
54 #include "content/public/common/user_agent.h"
55 #include "net/base/filename_util.h"
56 #include "permission_popup_manager.cc"
57 #include "private/ewk_app_control_private.h"
58 #include "private/ewk_back_forward_list_private.h"
59 #include "private/ewk_context_private.h"
60 #include "private/ewk_frame_private.h"
61 #include "private/ewk_policy_decision_private.h"
62 #include "private/ewk_quota_permission_request_private.h"
63 #include "private/ewk_settings_private.h"
64 #include "private/webview_delegate_ewk.h"
65 #include "public/ewk_hit_test_internal.h"
66 #include "services/network/public/cpp/features.h"
67 #include "services/network/public/cpp/resource_request_body.h"
68 #include "services/network/public/mojom/network_context.mojom.h"
69 #include "skia/ext/platform_canvas.h"
70 #include "third_party/blink/public/common/page/page_zoom.h"
71 #include "third_party/blink/public/platform/web_string.h"
72 #include "tizen/system_info.h"
73 #include "ui/aura/env.h"
74 #include "ui/aura/test/test_focus_client.h"
75 #include "ui/aura/test/test_window_parenting_client.h"
76 #include "ui/aura/window.h"
77 #include "ui/base/clipboard/clipboard_helper_efl.h"
78 #include "ui/base/l10n/l10n_util.h"
79 #include "ui/display/screen.h"
80 #include "ui/events/event_switches.h"
81 #include "ui/gfx/geometry/dip_util.h"
82 #include "ui/gfx/geometry/vector2d_f.h"
83 #include "ui/platform_window/platform_window_init_properties.h"
84 #include "web_contents_delegate_efl.h"
85 #include "web_contents_efl_delegate_ewk.h"
86
87 #include <iostream>
88
89 #if defined(TIZEN_ATK_SUPPORT)
90 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
91 #include "eweb_accessibility.h"
92 #include "eweb_accessibility_util.h"
93 #endif
94
95 using namespace content;
96 using web_contents_utils::WebViewFromWebContents;
97
98 namespace {
99
100 const int kTitleLengthMax = 80;
101 const base::FilePath::CharType kMHTMLFileNameExtension[] =
102     FILE_PATH_LITERAL(".mhtml");
103 const base::FilePath::CharType kMHTMLExtension[] = FILE_PATH_LITERAL("mhtml");
104 const base::FilePath::CharType kDefaultFileName[] =
105     FILE_PATH_LITERAL("saved_page");
106 const char kReplaceChars[] = " ";
107 const char kReplaceWith[] = "_";
108
109 static const char* kRendererCrashedHTMLMessage =
110     "<html><body><h1>Renderer process has crashed!</h1></body></html>";
111
112 inline void SetDefaultStringIfNull(const char*& variable,
113                                    const char* default_string) {
114   if (!variable) {
115     variable = default_string;
116   }
117 }
118
119 void GetEinaRectFromGfxRect(const gfx::Rect& gfx_rect,
120                             Eina_Rectangle* eina_rect) {
121   eina_rect->x = gfx_rect.x();
122   eina_rect->y = gfx_rect.y();
123   eina_rect->w = gfx_rect.width();
124   eina_rect->h = gfx_rect.height();
125 }
126
127 static content::WebContents* NullCreateWebContents(void*) {
128   return NULL;
129 }
130
131 base::FilePath GenerateMHTMLFilePath(const GURL& url,
132                                      const std::string& title,
133                                      const std::string& base_path) {
134   base::FilePath file_path(base_path);
135
136   if (base::DirectoryExists(file_path)) {
137     std::string title_part(title.substr(0, kTitleLengthMax));
138     base::ReplaceChars(title_part, kReplaceChars, kReplaceWith, &title_part);
139     base::FilePath file_name =
140         net::GenerateFileName(url, std::string(), std::string(), title_part,
141                               std::string(), kDefaultFileName);
142     DCHECK(!file_name.empty());
143     file_path = file_path.Append(file_name);
144   }
145
146   if (file_path.Extension().empty())
147     file_path = file_path.AddExtension(kMHTMLExtension);
148   else if (!file_path.MatchesExtension(kMHTMLFileNameExtension))
149     file_path = file_path.ReplaceExtension(kMHTMLExtension);
150
151   if (!base::PathExists(file_path))
152     return file_path;
153
154   int uniquifier = base::GetUniquePathNumber(file_path);
155   if (uniquifier > 0) {
156     return file_path.InsertBeforeExtensionASCII(
157         base::StringPrintf(" (%d)", uniquifier));
158   }
159
160   return base::FilePath();
161 }
162
163 }  // namespace
164
165 class WebViewAsyncRequestHitTestDataCallback {
166  public:
167   WebViewAsyncRequestHitTestDataCallback(int x, int y, Ewk_Hit_Test_Mode mode)
168       : x_(x), y_(y), mode_(mode) {}
169   virtual ~WebViewAsyncRequestHitTestDataCallback(){};
170
171   virtual void Run(_Ewk_Hit_Test* hit_test, EWebView* web_view) = 0;
172
173  protected:
174   int GetX() const { return x_; }
175   int GetY() const { return y_; }
176   Ewk_Hit_Test_Mode GetMode() const { return mode_; }
177
178  private:
179   int x_;
180   int y_;
181   Ewk_Hit_Test_Mode mode_;
182 };
183
184 class WebViewAsyncRequestHitTestDataUserCallback
185     : public WebViewAsyncRequestHitTestDataCallback {
186  public:
187   WebViewAsyncRequestHitTestDataUserCallback(
188       int x,
189       int y,
190       Ewk_Hit_Test_Mode mode,
191       Ewk_View_Hit_Test_Request_Callback callback,
192       void* user_data)
193       : WebViewAsyncRequestHitTestDataCallback(x, y, mode),
194         callback_(callback),
195         user_data_(user_data) {}
196
197   void Run(_Ewk_Hit_Test* hit_test, EWebView* web_view) override {
198     DCHECK(callback_);
199     callback_(web_view->evas_object(), GetX(), GetY(), GetMode(), hit_test,
200               user_data_);
201   }
202
203  private:
204   Ewk_View_Hit_Test_Request_Callback callback_;
205   void* user_data_;
206 };
207
208 #if defined(TIZEN_ATK_SUPPORT)
209 class EWebAccessibilityObserver : public EWebAccessibility::Observer {
210  public:
211   explicit EWebAccessibilityObserver(EWebView* webview) : webview_(webview) {}
212   virtual ~EWebAccessibilityObserver() {}
213
214   // EWebAccessibility::Observer implementation
215   void OnSpatialNavigationStatusChanged(Eina_Bool enable) override {
216     webview_->UpdateSpatialNavigationStatus(enable);
217   }
218
219   void OnAccessibilityStatusChanged(Eina_Bool enable) override {
220     webview_->UpdateAccessibilityStatus(enable);
221   }
222
223  private:
224   EWebView* webview_;
225 };
226 #endif
227
228 int EWebView::find_request_id_counter_ = 0;
229 content::WebContentsEflDelegate::WebContentsCreateCallback
230     EWebView::create_new_window_web_contents_cb_ =
231         base::BindRepeating(&NullCreateWebContents);
232
233 EWebView* EWebView::FromEvasObject(Evas_Object* eo) {
234   return WebViewDelegateEwk::GetInstance().GetWebViewFromEvasObject(eo);
235 }
236
237 #if !defined(USE_AURA)
238 RenderWidgetHostViewEfl* EWebView::rwhv() const {
239   return static_cast<RenderWidgetHostViewEfl*>(
240       web_contents_->GetRenderWidgetHostView());
241 }
242 #endif
243
244 void EWebView::OnViewFocusIn(void* data, Evas*, Evas_Object*, void*) {
245   auto view = static_cast<EWebView*>(data);
246   view->SetFocus(EINA_TRUE);
247 }
248
249 void EWebView::OnViewFocusOut(void* data, Evas*, Evas_Object*, void*) {
250   auto view = static_cast<EWebView*>(data);
251   view->SetFocus(EINA_FALSE);
252 }
253
254 EWebView::EWebView(Ewk_Context* context, Evas_Object* object)
255     : context_(context),
256       evas_object_(object),
257       native_view_(object),
258       touch_events_enabled_(false),
259       mouse_events_enabled_(false),
260       text_zoom_factor_(1.0),
261       formIsNavigating_(false),
262       current_find_request_id_(find_request_id_counter_++),
263       progress_(0.0),
264       hit_test_completion_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
265                            base::WaitableEvent::InitialState::NOT_SIGNALED),
266       page_scale_factor_(1.0),
267       x_delta_(0.0),
268       y_delta_(0.0),
269       is_initialized_(false) {
270  if (evas_object_) {
271     evas_object_event_callback_add(evas_object_, EVAS_CALLBACK_FOCUS_IN,
272                                    OnViewFocusIn, this);
273     evas_object_event_callback_add(evas_object_, EVAS_CALLBACK_FOCUS_OUT,
274                                    OnViewFocusOut, this);
275   }
276 }
277
278 void EWebView::Initialize() {
279   if (is_initialized_) {
280     return;
281   }
282
283   InitializeContent();
284
285   evas_event_handler_ = new WebViewEvasEventHandler(this);
286
287   scroll_detector_.reset(new ScrollDetector(this));
288
289   DCHECK(web_contents_->GetRenderViewHost());
290   // Settings (content::WebPreferences) will be initalized by
291   // RenderViewHostImpl::ComputeWebkitPrefs() based on command line switches.
292   settings_.reset(new Ewk_Settings(evas_object_,
293                                    web_contents_->GetOrCreateWebPreferences()));
294 #if defined(TIZEN_ATK_SUPPORT)
295   std::unique_ptr<EWebAccessibilityObserver> observer(
296       new EWebAccessibilityObserver(this));
297   eweb_accessibility_.reset(new EWebAccessibility(
298       evas_object_, web_contents_.get(), std::move(observer)));
299   lazy_initialize_atk_ = true;
300 #endif
301
302   base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
303   if (cmdline->HasSwitch(switches::kTouchEventFeatureDetection)) {
304     SetTouchEventsEnabled(
305         cmdline->GetSwitchValueASCII(switches::kTouchEventFeatureDetection) ==
306         switches::kTouchEventFeatureDetectionEnabled);
307   } else {
308     SetMouseEventsEnabled(true);
309   }
310
311   std::string user_agent =
312       EflWebView::VersionInfo::GetInstance()->DefaultUserAgent();
313   web_contents_->SetUserAgentOverride(
314       blink::UserAgentOverride::UserAgentOnly(user_agent),
315       false /* override_in_new_tabs */);
316
317   popupMenuItems_ = 0;
318   popupPicker_ = 0;
319
320   formNavigation_.count = 1;
321   formNavigation_.position = 0;
322   formNavigation_.prevState = false;
323   formNavigation_.nextState = false;
324
325   // allow this object and its children to get a focus
326   elm_object_tree_focus_allow_set(native_view_, EINA_TRUE);
327   is_initialized_ = true;
328
329   auto cbce = static_cast<ContentBrowserClientEfl*>(
330       content::GetContentClientExport()->browser());
331   // Initialize accept languages
332   SyncAcceptLanguages(cbce->GetAcceptLangs(nullptr));
333   accept_langs_changed_callback_ =
334       base::BindOnce(&EWebView::SyncAcceptLanguages, base::Unretained(this));
335   cbce->AddAcceptLangsChangedCallback(
336       std::move(accept_langs_changed_callback_));
337
338   // If EWebView is created by window.open, RenderView is already created
339   // before initializing WebContents. So we should manually invoke
340   // EWebView::RenderViewReady here.
341   if (web_contents_->GetPrimaryMainFrame() &&
342       web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive()) {
343     RenderViewReady();
344   }
345 }
346
347 EWebView::~EWebView() {
348   auto cbce = static_cast<ContentBrowserClientEfl*>(
349       content::GetContentClientExport()->browser());
350 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
351   cbce->RemoveAcceptLangsChangedCallback(
352       std::move(accept_langs_changed_callback_));
353 #endif
354
355 #if defined(USE_WAYLAND) && !BUILDFLAG(IS_TIZEN_TV)
356   ClipboardHelperEfl::GetInstance()->MaybeInvalidateActiveWebview(this);
357 #endif
358
359   std::map<int64_t, WebViewAsyncRequestHitTestDataCallback*>::iterator
360       hit_test_callback_iterator;
361   for (hit_test_callback_iterator = hit_test_callback_.begin();
362        hit_test_callback_iterator != hit_test_callback_.end();
363        hit_test_callback_iterator++)
364     delete hit_test_callback_iterator->second;
365   hit_test_callback_.clear();
366
367   for (auto iter = delayed_messages_.begin(); iter != delayed_messages_.end();
368        ++iter)
369     delete *iter;
370
371   delayed_messages_.clear();
372
373   if (!is_initialized_) {
374     return;
375   }
376
377 #if defined(TIZEN_ATK_SUPPORT)
378   eweb_accessibility_.reset();
379 #endif
380
381   context_menu_.reset();
382   mhtml_callback_map_.Clear();
383
384   ReleasePopupMenuList();
385
386   if (popupPicker_)
387     popup_picker_del(popupPicker_);
388
389   formNavigation_.count = 1;
390   formNavigation_.position = 0;
391   formNavigation_.prevState = false;
392   formNavigation_.nextState = false;
393
394   //  evas_object_del(evas_object());
395
396   // Release manually those scoped pointers to
397   // make sure they are released in correct order
398   web_contents_.reset();
399   web_contents_delegate_.reset();
400
401   // This code must be executed after WebContents deletion
402   // because WebContents depends on BrowserContext which
403   // is deleted along with EwkContext.
404   CHECK(!web_contents_);
405
406   permission_popup_manager_.reset();
407
408   gin_native_bridge_dispatcher_host_.reset();
409
410   if (evas_object_) {
411     evas_object_event_callback_del(evas_object_, EVAS_CALLBACK_FOCUS_IN,
412                                    OnViewFocusIn);
413     evas_object_event_callback_del(evas_object_, EVAS_CALLBACK_FOCUS_OUT,
414                                    OnViewFocusOut);
415   }
416 }
417
418 void EWebView::ReleasePopupMenuList() {
419   if (!popupMenuItems_)
420     return;
421
422   void* dummyItem;
423   EINA_LIST_FREE(popupMenuItems_, dummyItem) {
424     delete static_cast<Popup_Menu_Item*>(dummyItem);
425   }
426
427   popupMenuItems_ = 0;
428 }
429
430 content::RenderWidgetHostViewAura* EWebView::rwhva() const {
431   return static_cast<content::RenderWidgetHostViewAura*>(
432       web_contents_->GetRenderWidgetHostView());
433 }
434
435 content::WebContentsViewAura* EWebView::wcva() const {
436   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
437   return static_cast<WebContentsViewAura*>(wc->GetView());
438 }
439
440 void EWebView::ResetContextMenuController() {
441   return context_menu_.reset();
442 }
443
444 void EWebView::SetFocus(Eina_Bool focus) {
445   if (!web_contents_ || !rwhva() || (HasFocus() == focus))
446     return;
447
448   rwhva()->offscreen_helper()->Focus(focus);
449 }
450
451 Eina_Bool EWebView::HasFocus() const {
452   if (!rwhva())
453     return EINA_FALSE;
454
455   return rwhva()->offscreen_helper()->HasFocus() ? EINA_TRUE : EINA_FALSE;
456 }
457
458 Eina_Bool EWebView::AddJavaScriptMessageHandler(
459     Evas_Object* view,
460     Ewk_View_Script_Message_Cb callback,
461     std::string name) {
462   if (!gin_native_bridge_dispatcher_host_)
463     return EINA_FALSE;
464
465   return gin_native_bridge_dispatcher_host_->AddNamedObject(view, callback,
466                                                             name);
467 }
468
469 bool EWebView::SetPageVisibility(
470     Ewk_Page_Visibility_State page_visibility_state) {
471   if (!rwhva())
472     return false;
473
474   // TODO: We should able to set 'prerender' or 'unloaded' as visibility state.
475   // http://www.w3.org/TR/page-visibility/#dom-document-visibilitystate
476   switch (page_visibility_state) {
477     case EWK_PAGE_VISIBILITY_STATE_VISIBLE:
478       rwhva()->offscreen_helper()->SetPageVisibility(true);
479       break;
480     case EWK_PAGE_VISIBILITY_STATE_HIDDEN:
481       rwhva()->offscreen_helper()->SetPageVisibility(false);
482       break;
483     case EWK_PAGE_VISIBILITY_STATE_PRERENDER:
484       NOTIMPLEMENTED();
485       break;
486     default:
487       return false;
488   }
489
490   return true;
491 }
492
493 bool EWebView::CreateNewWindow(
494     content::WebContentsEflDelegate::WebContentsCreateCallback cb) {
495   create_new_window_web_contents_cb_ = cb;
496   Evas_Object* new_object = NULL;
497   SmartCallback<EWebViewCallbacks::CreateNewWindow>().call(&new_object);
498   create_new_window_web_contents_cb_ =
499       base::BindRepeating(&NullCreateWebContents);
500   return !!new_object;
501 }
502
503 // static
504 Evas_Object* EWebView::GetHostWindowDelegate(const content::WebContents* wc) {
505   EWebView* thiz = WebViewFromWebContents(wc);
506   DCHECK(thiz->evas_object_);
507   Evas_Object* parent = evas_object_above_get(thiz->evas_object_);
508   if (!parent) {
509     LOG(WARNING) << "Could not find and visual parents for EWK smart object!.";
510     return thiz->evas_object_;
511   }
512
513   if (elm_object_widget_check(parent)) {
514     Evas_Object* elm_parent = elm_object_top_widget_get(parent);
515     if (elm_parent)
516       return elm_parent;
517     return parent;
518   }
519
520   LOG(WARNING) << "Could not find elementary parent for WebView object!";
521   return thiz->evas_object_;
522 }
523
524 Evas_Object* EWebView::GetElmWindow() const {
525   Evas_Object* parent = elm_object_parent_widget_get(evas_object_);
526   return parent ? elm_object_top_widget_get(parent) : nullptr;
527 }
528
529 void EWebView::SetURL(const GURL& url, bool from_api) {
530   NavigationController::LoadURLParams params(url);
531
532   if (from_api) {
533     params.transition_type = ui::PageTransitionFromInt(
534         ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_API);
535   }
536
537   params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
538   web_contents_->GetController().LoadURLWithParams(params);
539 }
540
541 const GURL& EWebView::GetURL() const {
542   return web_contents_->GetVisibleURL();
543 }
544
545 const GURL& EWebView::GetOriginalURL() const {
546   const auto entry = web_contents_->GetController().GetVisibleEntry();
547   if (entry)
548     return entry->GetOriginalRequestURL();
549
550   return web_contents_->GetVisibleURL();
551 }
552
553 void EWebView::Reload() {
554   web_contents_->GetController().Reload(content::ReloadType::NORMAL, true);
555 }
556
557 void EWebView::ReloadBypassingCache() {
558   web_contents_->GetController().Reload(content::ReloadType::BYPASSING_CACHE,
559                                         true);
560 }
561
562 Eina_Bool EWebView::CanGoBack() {
563   return web_contents_->GetController().CanGoBack();
564 }
565
566 Eina_Bool EWebView::CanGoForward() {
567   return web_contents_->GetController().CanGoForward();
568 }
569
570 Eina_Bool EWebView::GoBack() {
571   if (!web_contents_->GetController().CanGoBack())
572     return EINA_FALSE;
573
574   web_contents_->GetController().GoBack();
575   return EINA_TRUE;
576 }
577
578 Eina_Bool EWebView::GoForward() {
579   if (!web_contents_->GetController().CanGoForward())
580     return EINA_FALSE;
581
582   web_contents_->GetController().GoForward();
583   return EINA_TRUE;
584 }
585
586 void EWebView::Stop() {
587   if (web_contents_->IsLoading())
588     web_contents_->Stop();
589 }
590
591 void EWebView::Suspend() {
592   CHECK(web_contents_);
593   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
594   RenderFrameHost* rfh = web_contents_->GetPrimaryMainFrame();
595   CHECK(rvh);
596   CHECK(rfh);
597 #if !defined(EWK_BRINGUP)  // FIXME: m69 bringup
598   rfh->BlockRequestsForFrame();
599 #endif
600 #if 0
601   content::BrowserThread::PostTask(
602       content::BrowserThread::IO, FROM_HERE,
603       base::BindOnce(&content::ResourceDispatcherHost::BlockRequestsForFrameFromUI,
604                  rfh));
605
606   if (rvh)
607     rvh->Send(new EwkViewMsg_SuspendScheduledTask(rvh->GetRoutingID()));
608 #endif
609 }
610
611 void EWebView::Resume() {
612   CHECK(web_contents_);
613   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
614   RenderFrameHost* rfh = web_contents_->GetPrimaryMainFrame();
615   CHECK(rvh);
616   CHECK(rfh);
617 #if !defined(EWK_BRINGUP)  // FIXME: m69 bringup
618   rfh->ResumeBlockedRequestsForFrame();
619 #endif
620 #if 0
621   content::BrowserThread::PostTask(
622       content::BrowserThread::IO, FROM_HERE,
623       base::BindOnce(
624           &content::ResourceDispatcherHost::ResumeBlockedRequestsForFrameFromUI,
625           rfh));
626
627   if (rvh)
628     rvh->Send(new EwkViewMsg_ResumeScheduledTasks(rvh->GetRoutingID()));
629 #endif
630 }
631
632 double EWebView::GetTextZoomFactor() const {
633   if (text_zoom_factor_ < 0.0)
634     return -1.0;
635
636   return text_zoom_factor_;
637 }
638
639 void EWebView::SetTextZoomFactor(double text_zoom_factor) {
640   if (text_zoom_factor_ == text_zoom_factor || text_zoom_factor < 0.0)
641     return;
642
643   text_zoom_factor_ = text_zoom_factor;
644   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
645   if (!render_view_host)
646     return;
647 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
648   render_view_host->Send(new ViewMsg_SetTextZoomFactor(
649       render_view_host->GetRoutingID(), text_zoom_factor));
650 #endif
651 }
652
653 double EWebView::GetPageZoomFactor() const {
654   return blink::PageZoomLevelToZoomFactor(
655       content::HostZoomMap::GetZoomLevel(web_contents_.get()));
656 }
657
658 void EWebView::SetPageZoomFactor(double page_zoom_factor) {
659   content::HostZoomMap::SetZoomLevel(
660       web_contents_.get(), blink::PageZoomFactorToZoomLevel(page_zoom_factor));
661 }
662
663 void EWebView::ExecuteEditCommand(const char* command, const char* value) {
664   EINA_SAFETY_ON_NULL_RETURN(command);
665
666   value = (value == nullptr) ? "" : value;
667
668   absl::optional<std::u16string> optional_value =
669       absl::make_optional(base::ASCIIToUTF16(value));
670
671   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
672   if (wc) {
673     wc->GetFocusedFrameWidgetInputHandler()->ExecuteEditCommand(
674         std::string(command), optional_value);
675   }
676 }
677
678 void EWebView::SetOrientation(int orientation) {
679   if (GetOrientation() == orientation)
680     return;
681
682   if (orientation == 0 || orientation == 90 || orientation == 180 ||
683       orientation == 270) {
684 #if !defined(USE_AURA)
685     GetWebContentsViewEfl()->SetOrientation(orientation);
686 #endif
687     int width = 0;
688     int height = 0;
689     const Ecore_Evas* ee =
690         ecore_evas_ecore_evas_get(evas_object_evas_get(evas_object_));
691     ecore_evas_screen_geometry_get(ee, nullptr, nullptr, &width, &height);
692     if (orientation == 90 || orientation == 270)
693       std::swap(width, height);
694
695     if (context_menu_)
696       context_menu_->SetPopupSize(width, height);
697     if (popup_controller_)
698       popup_controller_->SetPopupSize(width, height);
699     if (JavaScriptDialogManagerEfl* dialogMG = GetJavaScriptDialogManagerEfl())
700       dialogMG->SetPopupSize(width, height);
701     if (popupPicker_)
702       popup_picker_resize(popupPicker_, width, height);
703   }
704 }
705
706 int EWebView::GetOrientation() {
707 #if !defined(USE_AURA)
708   return GetWebContentsViewEfl()->GetOrientation();
709 #else
710   return 0;
711 #endif
712 }
713
714 void EWebView::Show() {
715   evas_object_show(native_view_);
716   web_contents_->WasShown();
717 }
718
719 void EWebView::Hide() {
720   evas_object_hide(native_view_);
721   web_contents_->WasHidden();
722 }
723
724 void EWebView::SetViewAuthCallback(Ewk_View_Authentication_Callback callback,
725                                    void* user_data) {
726   authentication_cb_.Set(callback, user_data);
727 }
728
729 void EWebView::InvokeAuthCallback(LoginDelegateEfl* login_delegate,
730                                   const GURL& url,
731                                   const std::string& realm) {
732   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
733
734   auth_challenge_.reset(new _Ewk_Auth_Challenge(login_delegate, url, realm));
735   authentication_cb_.Run(evas_object_, auth_challenge_.get());
736
737   if (!auth_challenge_->is_decided && !auth_challenge_->is_suspended) {
738     auth_challenge_->is_decided = true;
739     auth_challenge_->login_delegate->Cancel();
740   }
741 }
742
743 void EWebView::InvokePolicyResponseCallback(
744     _Ewk_Policy_Decision* policy_decision,
745     bool* defer) {
746   SmartCallback<EWebViewCallbacks::PolicyResponseDecide>().call(
747       policy_decision);
748
749   if (policy_decision->isSuspended()) {
750     *defer = true;
751     return;
752   }
753
754   if (!policy_decision->isDecided())
755     policy_decision->Use();
756
757   policy_decision->SelfDeleteIfNecessary();
758 }
759
760 void EWebView::InvokePolicyNavigationCallback(
761     const NavigationPolicyParams& params,
762     bool* handled) {
763   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
764
765   SmartCallback<EWebViewCallbacks::SaveSessionData>().call();
766
767   std::unique_ptr<_Ewk_Policy_Decision> policy_decision(
768       new _Ewk_Policy_Decision(params));
769
770   SmartCallback<EWebViewCallbacks::NavigationPolicyDecision>().call(
771       policy_decision.get());
772
773   CHECK(!policy_decision->isSuspended());
774
775   // TODO: Navigation can't be suspended
776   // this aproach is synchronous and requires immediate response
777   // Maybe there is different approach (like resource throttle response
778   // mechanism) that allows us to
779   // suspend navigation
780   if (!policy_decision->isDecided())
781     policy_decision->Use();
782
783   *handled = policy_decision->GetNavigationPolicyHandler()->GetDecision() ==
784              NavigationPolicyHandlerEfl::Handled;
785 }
786
787 void EWebView::HandleTouchEvents(Ewk_Touch_Event_Type type,
788                                  const Eina_List* points,
789                                  const Evas_Modifier* modifiers) {
790 #if !defined(USE_AURA)
791   const Eina_List* l;
792   void* data;
793   EINA_LIST_FOREACH(points, l, data) {
794     const Ewk_Touch_Point* point = static_cast<Ewk_Touch_Point*>(data);
795     if (point->state == EVAS_TOUCH_POINT_STILL) {
796       // Chromium doesn't expect (and doesn't like) these events.
797       continue;
798     }
799     if (rwhv()) {
800       Evas_Coord_Point pt;
801       pt.x = point->x;
802       pt.y = point->y;
803       ui::TouchEvent touch_event =
804           MakeTouchEvent(pt, point->state, point->id, evas_object());
805       rwhv()->HandleTouchEvent(&touch_event);
806     }
807   }
808 #endif
809 }
810
811 bool EWebView::TouchEventsEnabled() const {
812   return touch_events_enabled_;
813 }
814
815 // TODO: Touch events use the same mouse events in EFL API.
816 // Figure out how to distinguish touch and mouse events on touch&mice devices.
817 // Currently mouse and touch support is mutually exclusive.
818 void EWebView::SetTouchEventsEnabled(bool enabled) {
819   if (touch_events_enabled_ == enabled)
820     return;
821
822   touch_events_enabled_ = enabled;
823 #if !defined(USE_AURA)
824   GetWebContentsViewEfl()->SetTouchEventsEnabled(enabled);
825 #endif
826 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
827   // there is no flag touch_enabled in web preferences
828   GetSettings()->getPreferences().touch_enabled = enabled;
829   GetSettings()->getPreferences().double_tap_to_zoom_enabled = enabled;
830   GetSettings()->getPreferences().editing_behavior =
831       enabled ? content::EDITING_BEHAVIOR_ANDROID
832               : content::EDITING_BEHAVIOR_UNIX;
833 #endif
834   UpdateWebKitPreferences();
835 }
836
837 bool EWebView::MouseEventsEnabled() const {
838   return mouse_events_enabled_;
839 }
840
841 void EWebView::SetMouseEventsEnabled(bool enabled) {
842   if (mouse_events_enabled_ == enabled)
843     return;
844
845   mouse_events_enabled_ = enabled;
846 #if !defined(USE_AURA)
847   GetWebContentsViewEfl()->SetTouchEventsEnabled(!enabled);
848 #endif
849 }
850
851 namespace {
852
853 class JavaScriptCallbackDetails {
854  public:
855   JavaScriptCallbackDetails(Ewk_View_Script_Execute_Callback callback_func,
856                             void* user_data,
857                             Evas_Object* view)
858       : callback_func_(callback_func), user_data_(user_data), view_(view) {}
859
860   Ewk_View_Script_Execute_Callback callback_func_;
861   void* user_data_;
862   Evas_Object* view_;
863 };
864
865 void JavaScriptComplete(JavaScriptCallbackDetails* script_callback_data,
866                         base::Value result) {
867   if (!script_callback_data->callback_func_)
868     return;
869
870   std::string return_string;
871   if (result.is_string()) {
872     // We don't want to serialize strings with JSONStringValueSerializer
873     // to avoid quotation marks.
874     return_string = result.GetString();
875   } else if (result.is_none()) {
876     // Value::TYPE_NULL is for lack of value, undefined, null
877     return_string = "";
878   } else {
879     JSONStringValueSerializer serializer(&return_string);
880     serializer.Serialize(result);
881   }
882
883   script_callback_data->callback_func_(script_callback_data->view_,
884                                        return_string.c_str(),
885                                        script_callback_data->user_data_);
886 }
887
888 }  // namespace
889
890 bool EWebView::ExecuteJavaScript(const char* script,
891                                  Ewk_View_Script_Execute_Callback callback,
892                                  void* userdata) {
893   LOG(INFO) << __FUNCTION__;
894   if (!web_contents_) {
895     LOG(ERROR) << __FUNCTION__ << "web_contents_ is null";
896     return false;
897   }
898
899   RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
900   if (!render_frame_host) {
901     LOG(ERROR) << __FUNCTION__ << " render_frame_host is null";
902     return false;
903   }
904
905   // Note: M37. Execute JavaScript, |script| with
906   // |RenderFrameHost::ExecuteJavaScript|.
907   // @see also https://codereview.chromium.org/188893005 for more details.
908   std::u16string js_script;
909   base::UTF8ToUTF16(script, strlen(script), &js_script);
910   if (callback) {
911     JavaScriptCallbackDetails* script_callback_data =
912         new JavaScriptCallbackDetails(callback, userdata, evas_object_);
913     RenderFrameHost::JavaScriptResultCallback js_callback =
914         base::BindOnce(&JavaScriptComplete, base::Owned(script_callback_data));
915     // In M47, it isn't possible anymore to execute javascript in the generic
916     // case. We need to call ExecuteJavaScriptForTests to keep the behaviour
917     // unchanged @see https://codereview.chromium.org/1123783002
918     render_frame_host->ExecuteJavaScriptWithUserGestureForTests(
919         js_script, std::move(js_callback));
920   } else {
921     // We use ExecuteJavaScriptWithUserGestureForTests instead of
922     // ExecuteJavaScript because
923     // ExecuteJavaScriptWithUserGestureForTests sets user_gesture to true. This
924     // was the
925     // behaviour is m34, and we want to keep it that way.
926     render_frame_host->ExecuteJavaScriptWithUserGestureForTests(
927         js_script, base::NullCallback());
928   }
929
930   return true;
931 }
932
933 bool EWebView::SetUserAgent(const char* userAgent) {
934   content::NavigationController& controller = web_contents_->GetController();
935   bool override = userAgent && strlen(userAgent);
936   for (int i = 0; i < controller.GetEntryCount(); ++i)
937     controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(override);
938   // TODO: Check if override_in_new_tabs has to be true.
939   web_contents_->SetUserAgentOverride(
940       blink::UserAgentOverride::UserAgentOnly(userAgent),
941       false /* override_in_new_tabs */);
942   return true;
943 }
944
945 bool EWebView::SetUserAgentAppName(const char* application_name) {
946   EflWebView::VersionInfo::GetInstance()->UpdateUserAgentWithAppName(
947       application_name ? application_name : "");
948   std::string user_agent =
949       EflWebView::VersionInfo::GetInstance()->DefaultUserAgent();
950   web_contents_->SetUserAgentOverride(
951       blink::UserAgentOverride::UserAgentOnly(user_agent),
952       false /* override_in_new_tabs */);
953   return true;
954 }
955
956 void EWebView::set_magnifier(bool status) {
957 #if !defined(USE_AURA)
958   rwhv()->set_magnifier(status);
959 #endif
960 }
961
962 #if BUILDFLAG(IS_TIZEN)
963 bool EWebView::SetPrivateBrowsing(bool incognito) {
964   if (context_->GetImpl()->browser_context()->IsOffTheRecord() == incognito)
965     return false;
966   context_->GetImpl()->browser_context()->SetOffTheRecord(incognito);
967   return true;
968 }
969
970 bool EWebView::GetPrivateBrowsing() const {
971   return context_->GetImpl()->browser_context()->IsOffTheRecord();
972 }
973 #endif
974
975 const char* EWebView::GetUserAgent() const {
976   std::string user_agent =
977       web_contents_->GetUserAgentOverride().ua_string_override;
978   if (user_agent.empty())
979     user_agent_ = content::GetContentClientExport()->browser()->GetUserAgent();
980   else
981     user_agent_ = user_agent;
982
983   return user_agent_.c_str();
984 }
985
986 const char* EWebView::GetUserAgentAppName() const {
987   user_agent_app_name_ = EflWebView::VersionInfo::GetInstance()->AppName();
988   return user_agent_app_name_.c_str();
989 }
990
991 const char* EWebView::CacheSelectedText() {
992   if (!rwhva())
993     return "";
994
995   selected_text_cached_ = base::UTF16ToUTF8(rwhva()->GetSelectedText());
996   return selected_text_cached_.c_str();
997 }
998
999 _Ewk_Frame* EWebView::GetMainFrame() {
1000   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1001
1002   if (!frame_.get())
1003     frame_.reset(new _Ewk_Frame(web_contents_->GetPrimaryMainFrame()));
1004
1005   return frame_.get();
1006 }
1007
1008 void EWebView::UpdateWebKitPreferences() {
1009   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1010
1011   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1012   if (!render_view_host)
1013     return;
1014
1015   web_contents_delegate_->OnUpdateSettings(settings_.get());
1016 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1017   render_view_host->UpdateWebkitPreferences(settings_->getPreferences());
1018 #endif
1019   UpdateWebkitPreferencesEfl(render_view_host);
1020 }
1021
1022 void EWebView::UpdateWebkitPreferencesEfl(RenderViewHost* render_view_host) {
1023   DCHECK(render_view_host);
1024 #if !defined(EWK_BRINGUP)  // FIXME: m108 bringup
1025   IPC::Message* message = new EwkSettingsMsg_UpdateWebKitPreferencesEfl(
1026       render_view_host->GetRoutingID(), settings_->getPreferencesEfl());
1027
1028   if (render_view_host->IsRenderViewLive()) {
1029 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1030     render_view_host->Send(message);
1031 #endif
1032   } else {
1033     delayed_messages_.push_back(message);
1034   }
1035 #endif
1036 }
1037
1038 void EWebView::SetContentSecurityPolicy(const char* policy,
1039                                         Ewk_CSP_Header_Type type) {
1040   web_contents_delegate_->SetContentSecurityPolicy(
1041       (policy ? policy : std::string()), type);
1042 }
1043
1044 void EWebView::LoadHTMLString(const char* html,
1045                               const char* base_uri,
1046                               const char* unreachable_uri) {
1047   LoadData(html, std::string::npos, NULL, NULL, base_uri, unreachable_uri);
1048 }
1049
1050 void EWebView::LoadPlainTextString(const char* plain_text) {
1051   LoadData(plain_text, std::string::npos, "text/plain", NULL, NULL, NULL);
1052 }
1053
1054 void EWebView::LoadData(const char* data,
1055                         size_t size,
1056                         const char* mime_type,
1057                         const char* encoding,
1058                         const char* base_uri,
1059                         const char* unreachable_uri) {
1060   SetDefaultStringIfNull(mime_type, "text/html");
1061   SetDefaultStringIfNull(encoding, "utf-8");
1062   SetDefaultStringIfNull(base_uri, "about:blank");  // Webkit2 compatible
1063   SetDefaultStringIfNull(unreachable_uri, "");
1064
1065   std::string str_data = data;
1066
1067   if (size < str_data.length())
1068     str_data = str_data.substr(0, size);
1069
1070   std::string url_str("data:");
1071   url_str.append(mime_type);
1072   url_str.append(";charset=");
1073   url_str.append(encoding);
1074   url_str.append(",");
1075
1076   // GURL constructor performs canonicalization of url string, but this is not
1077   // enough for correctly escaping contents of "data:" url.
1078   url_str.append(base::EscapeUrlEncodedData(str_data, false));
1079
1080   NavigationController::LoadURLParams data_params(GURL(url_str.c_str()));
1081
1082   data_params.base_url_for_data_url = GURL(base_uri);
1083   data_params.virtual_url_for_data_url = GURL(unreachable_uri);
1084
1085   data_params.load_type = NavigationController::LOAD_TYPE_DATA;
1086   data_params.should_replace_current_entry = false;
1087   data_params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
1088   web_contents_->GetController().LoadURLWithParams(data_params);
1089 }
1090
1091 void EWebView::InvokeLoadError(const GURL& url,
1092                                int error_code,
1093                                bool is_cancellation) {
1094   _Ewk_Error err(error_code, is_cancellation,
1095                  url.possibly_invalid_spec().c_str());
1096
1097   SmartCallback<EWebViewCallbacks::LoadError>().call(&err);
1098 }
1099
1100 void EWebView::HandlePopupMenu(std::vector<blink::mojom::MenuItemPtr> items,
1101                                int selectedIndex,
1102                                bool multiple) {
1103   // Request form navigation information as early as possible,
1104   // given that is renderer will ping-back with actual requested data.
1105   RenderFrameHostImpl* render_frame_host =
1106       static_cast<RenderFrameHostImpl*>(web_contents_->GetPrimaryMainFrame());
1107   if (render_frame_host)
1108     render_frame_host->Send(new EwkFrameMsg_RequestSelectCollectionInformation(
1109         render_frame_host->GetRoutingID()));
1110
1111   Eina_List* popupItems = 0;
1112   const size_t size = items.size();
1113   for (size_t i = 0; i < size; ++i) {
1114     popupItems =
1115         eina_list_append(popupItems, new Popup_Menu_Item(std::move(items[i])));
1116   }
1117
1118   ReleasePopupMenuList();
1119   popupMenuItems_ = popupItems;
1120
1121   if (popupPicker_ && FormIsNavigating()) {
1122     popupPicker_->multiSelect = multiple;
1123     PopupMenuUpdate(popupMenuItems_, selectedIndex);
1124     SetFormIsNavigating(false);
1125     return;
1126   }
1127
1128   if (popupPicker_)
1129     popup_picker_del(popupPicker_);
1130   popupPicker_ = 0;
1131
1132   if (multiple)
1133     popupPicker_ =
1134         popup_picker_new(this, evas_object(), popupMenuItems_, 0, multiple);
1135   else
1136     popupPicker_ = popup_picker_new(this, evas_object(), popupMenuItems_,
1137                                     selectedIndex, multiple);
1138
1139   popup_picker_buttons_update(popupPicker_, formNavigation_.position,
1140                               formNavigation_.count, false);
1141
1142   // Picker has been shown on top of webview and the page content gets
1143   // partially overlapped. Decrease viewport while showing picker.
1144   AdjustViewPortHeightToPopupMenu(true /* is_popup_menu_visible */);
1145   ScrollFocusedNodeIntoView();
1146 }
1147
1148 void EWebView::HidePopupMenu() {
1149   if (!popupPicker_)
1150     return;
1151
1152   if (FormIsNavigating())
1153     return;
1154
1155   AdjustViewPortHeightToPopupMenu(false /* is_popup_menu_visible */);
1156   popup_picker_del(popupPicker_);
1157   popupPicker_ = 0;
1158 }
1159
1160 void EWebView::UpdateFormNavigation(int formElementCount,
1161                                     int currentNodeIndex,
1162                                     bool prevState,
1163                                     bool nextState) {
1164   formNavigation_.count = formElementCount;
1165   formNavigation_.position = currentNodeIndex;
1166   formNavigation_.prevState = prevState;
1167   formNavigation_.nextState = nextState;
1168 }
1169
1170 void EWebView::SetFormIsNavigating(bool formIsNavigating) {
1171   formIsNavigating_ = formIsNavigating;
1172 }
1173
1174 Eina_Bool EWebView::PopupMenuUpdate(Eina_List* items, int selectedIndex) {
1175   if (!popupPicker_)
1176     return false;
1177
1178   popup_picker_update(evas_object(), popupPicker_, items, selectedIndex);
1179   popup_picker_buttons_update(popupPicker_, formNavigation_.position,
1180                               formNavigation_.count, false);
1181   return true;
1182 }
1183
1184 void EWebView::FormNavigate(bool direction) {
1185   RenderFrameHostImpl* render_frame_host =
1186       static_cast<RenderFrameHostImpl*>(web_contents_->GetPrimaryMainFrame());
1187   if (!render_frame_host)
1188     return;
1189
1190   popup_picker_buttons_update(popupPicker_, formNavigation_.position,
1191                               formNavigation_.count, true);
1192
1193   if ((direction && formNavigation_.nextState) ||
1194       (!direction && formNavigation_.prevState))
1195     SetFormIsNavigating(true);
1196
1197   listClosed(popupPicker_, 0, 0, 0);
1198   render_frame_host->Send(new EwkFrameMsg_MoveToNextOrPreviousSelectElement(
1199       render_frame_host->GetRoutingID(), direction));
1200 }
1201
1202 Eina_Bool EWebView::DidSelectPopupMenuItem(int selectedIndex) {
1203   RenderFrameHostImpl* render_frame_host =
1204       static_cast<RenderFrameHostImpl*>(web_contents_->GetPrimaryMainFrame());
1205   if (!render_frame_host)
1206     return false;
1207
1208   if (!popupMenuItems_)
1209     return false;
1210
1211   // When user select empty space then no index is selected, so selectedIndex
1212   // value is -1
1213   // In that case we should call valueChanged() with -1 index.That in turn call
1214   // popupDidHide()
1215   // in didChangeSelectedIndex() for reseting the value of m_popupIsVisible in
1216   // RenderMenuList.
1217   if (selectedIndex != -1 &&
1218       selectedIndex >= (int)eina_list_count(popupMenuItems_))
1219     return false;
1220
1221   // In order to reuse RenderFrameHostImpl::DidSelectPopupMenuItems() method in
1222   // Android,
1223   // put selectedIndex into std::vector<int>.
1224   std::vector<int> selectedIndices;
1225   selectedIndices.push_back(selectedIndex);
1226 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1227   render_frame_host->DidSelectPopupMenuItems(selectedIndices);
1228 #endif
1229   return true;
1230 }
1231
1232 Eina_Bool EWebView::DidMultipleSelectPopupMenuItem(
1233     std::vector<int>& selectedIndices) {
1234   RenderFrameHostImpl* render_frame_host =
1235       static_cast<RenderFrameHostImpl*>(web_contents_->GetPrimaryMainFrame());
1236   if (!render_frame_host)
1237     return false;
1238
1239   if (!popupMenuItems_)
1240     return false;
1241 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1242   render_frame_host->DidSelectPopupMenuItems(selectedIndices);
1243 #endif
1244   return true;
1245 }
1246
1247 void EWebView::PopupMenuClose() {
1248   HidePopupMenu();
1249   ReleasePopupMenuList();
1250   wcva()->wcva_helper()->DidCancelPopupMenu();
1251 }
1252
1253 void EWebView::HandleLongPressGesture(
1254     const content::ContextMenuParams& params) {
1255 #if !defined(USE_AURA)
1256   // This menu is created in renderer process and it does not now anything about
1257   // view scaling factor and it has another calling sequence, so coordinates is
1258   // not updated.
1259   content::ContextMenuParams convertedParams = params;
1260   gfx::Point convertedPoint =
1261       rwhv()->ConvertPointInViewPix(gfx::Point(params.x, params.y));
1262   convertedParams.x = convertedPoint.x();
1263   convertedParams.y = convertedPoint.y();
1264
1265   Evas_Coord x, y;
1266   evas_object_geometry_get(evas_object(), &x, &y, 0, 0);
1267   convertedParams.x += x;
1268   convertedParams.y += y;
1269
1270   if (GetSelectionController() && GetSelectionController()->GetLongPressed()) {
1271     bool show_context_menu_now =
1272         !GetSelectionController()->HandleLongPressEvent(convertedPoint,
1273                                                         convertedParams);
1274     if (show_context_menu_now)
1275       ShowContextMenuInternal(convertedParams);
1276   }
1277 #endif
1278 }
1279
1280 void EWebView::ShowContextMenu(const content::ContextMenuParams& params) {
1281 #if !defined(USE_AURA)
1282   // This menu is created in renderer process and it does not now anything about
1283   // view scaling factor and it has another calling sequence, so coordinates is
1284   // not updated.
1285   content::ContextMenuParams convertedParams = params;
1286   gfx::Point convertedPoint =
1287       rwhv()->ConvertPointInViewPix(gfx::Point(params.x, params.y));
1288   convertedParams.x = convertedPoint.x();
1289   convertedParams.y = convertedPoint.y();
1290
1291   Evas_Coord x, y;
1292   evas_object_geometry_get(evas_object(), &x, &y, 0, 0);
1293   convertedParams.x += x;
1294   convertedParams.y += y;
1295
1296   context_menu_position_ = gfx::Point(convertedParams.x, convertedParams.y);
1297
1298   ShowContextMenuInternal(convertedParams);
1299 #endif
1300 }
1301
1302 void EWebView::ShowContextMenuInternal(
1303     const content::ContextMenuParams& params) {
1304   context_menu_.reset(
1305       new content::ContextMenuControllerEfl(this, *web_contents_.get()));
1306   if (!context_menu_->PopulateAndShowContextMenu(params)) {
1307     context_menu_.reset();
1308     if (GetSelectionController())
1309       GetSelectionController()->HideHandles();
1310   }
1311 }
1312
1313 void EWebView::CancelContextMenu(int request_id) {
1314   if (context_menu_)
1315     context_menu_->HideContextMenu();
1316 }
1317
1318 void EWebView::Find(const char* text, Ewk_Find_Options ewk_find_options) {
1319   std::u16string find_text = base::UTF8ToUTF16(text);
1320   bool find_next = (previous_text_ == find_text);
1321
1322   if (!find_next) {
1323     current_find_request_id_ = find_request_id_counter_++;
1324     previous_text_ = find_text;
1325   }
1326
1327   auto find_options = blink::mojom::FindOptions::New();
1328   find_options->forward = !(ewk_find_options & EWK_FIND_OPTIONS_BACKWARDS);
1329   find_options->match_case =
1330       !(ewk_find_options & EWK_FIND_OPTIONS_CASE_INSENSITIVE);
1331
1332   web_contents_->Find(current_find_request_id_, find_text,
1333                       std::move(find_options));
1334 }
1335
1336 void EWebView::SetScale(double scale_factor) {
1337   // Do not cache |scale_factor| here as it may be discarded by Blink's
1338   // minimumPageScaleFactor and maximumPageScaleFactor.
1339   // |scale_factor| is cached as responde to DidChangePageScaleFactor.
1340   WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents_.get());
1341   wci->GetPrimaryMainFrame()->GetAssociatedLocalMainFrame()->SetScaleFactor(
1342       scale_factor);
1343 }
1344
1345 void EWebView::ScrollFocusedNodeIntoView() {
1346   if (RenderViewHost* render_view_host = web_contents_->GetRenderViewHost()) {
1347     if (auto& broadcast = static_cast<RenderViewHostImpl*>(render_view_host)
1348                               ->GetAssociatedPageBroadcast())
1349       broadcast->ScrollFocusedNodeIntoView();
1350   }
1351 }
1352
1353 void EWebView::AdjustViewPortHeightToPopupMenu(bool is_popup_menu_visible) {
1354   DCHECK(popupPicker_);
1355
1356   int picker_height = 0;
1357   popup_picker_geometry_get(popupPicker_, 0, 0, 0, &picker_height);
1358
1359   gfx::Rect rect = rwhva()->offscreen_helper()->GetViewBounds();
1360   // FIXME(g.czajkowski): detect the need of resizing viewport.
1361   // Checking the position of focused <select> element and do resize only when
1362   // the picker overlaps the element will prevent Blink from doing re-layout.
1363   // Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=15488.
1364   rwhva()->offscreen_helper()->SetCustomViewportSize(gfx::Size(
1365       rect.width(), is_popup_menu_visible ? rect.height() - picker_height
1366                                           : rect.height() + picker_height));
1367 }
1368
1369 void EWebView::SetScaleChangedCallback(Ewk_View_Scale_Changed_Callback callback,
1370                                        void* user_data) {
1371   scale_changed_cb_.Set(callback, user_data);
1372 }
1373
1374 bool EWebView::GetScrollPosition(int* x, int* y) const {
1375   if (!rwhva()) {
1376     LOG(ERROR) << "rwhva() returns nullptr";
1377     return false;
1378   }
1379   if (scroll_detector_->IsScrollOffsetChanged()) {
1380     if (x)
1381       *x = previous_scroll_position_.x();
1382     if (y)
1383       *y = previous_scroll_position_.y();
1384   } else {
1385     const gfx::Vector2d scroll_position_dip =
1386         scroll_detector_->GetLastScrollPosition();
1387     const float device_scale_factor = display::Screen::GetScreen()
1388                                           ->GetPrimaryDisplay()
1389                                           .device_scale_factor();
1390     if (x) {
1391       *x = base::ClampRound((scroll_position_dip.x() - x_delta_) *
1392                             device_scale_factor);
1393     }
1394     if (y) {
1395       *y = base::ClampRound((scroll_position_dip.y() - y_delta_) *
1396                             device_scale_factor);
1397     }
1398   }
1399   return true;
1400 }
1401
1402 void EWebView::ChangeScroll(int& x, int& y) {
1403   if (!rwhva()) {
1404     LOG(ERROR) << "rwhva() returns nullptr";
1405     return;
1406   }
1407   int max_x = 0;
1408   int max_y = 0;
1409   GetScrollSize(&max_x, &max_y);
1410   previous_scroll_position_.set_x(std::min(std::max(x, 0), max_x));
1411   previous_scroll_position_.set_y(std::min(std::max(y, 0), max_y));
1412
1413   const float device_scale_factor = display::Screen::GetScreen()
1414                                         ->GetPrimaryDisplay()
1415                                         .device_scale_factor();
1416   int x_input = x;
1417   int y_input = y;
1418
1419   x = base::ClampCeil(x / device_scale_factor);
1420   y = base::ClampCeil(y / device_scale_factor);
1421
1422   x_delta_ = x - (x_input / device_scale_factor);
1423   y_delta_ = y - (y_input / device_scale_factor);
1424
1425   scroll_detector_->SetScrollOffsetChanged();
1426 }
1427
1428 void EWebView::SetScroll(int x, int y) {
1429   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1430   if (!render_view_host)
1431     return;
1432
1433   ChangeScroll(x, y);
1434 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1435   render_view_host->Send(
1436       new EwkViewMsg_SetScroll(render_view_host->GetRoutingID(), x, y));
1437 #endif
1438 }
1439
1440 void EWebView::UseSettingsFont() {
1441 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1442   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1443   if (render_view_host)
1444     render_view_host->Send(
1445         new EwkViewMsg_UseSettingsFont(render_view_host->GetRoutingID()));
1446 #endif
1447 }
1448
1449 void EWebView::DidChangeContentsSize(int width, int height) {
1450   contents_size_ = gfx::Size(width, height);
1451   SmartCallback<EWebViewCallbacks::ContentsSizeChanged>().call();
1452   SetScaledContentsSize();
1453 }
1454
1455 const Eina_Rectangle EWebView::GetContentsSize() const {
1456   Eina_Rectangle rect;
1457   EINA_RECTANGLE_SET(&rect, 0, 0, contents_size_.width(),
1458                      contents_size_.height());
1459   return rect;
1460 }
1461
1462 void EWebView::SetScaledContentsSize() {
1463   if (!rwhva())
1464     return;  // LCOV_EXCL_LINE
1465
1466   const float device_scale_factor =
1467       display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1468   gfx::SizeF scaled_contents_size = gfx::ConvertSizeToPixels(
1469       contents_size_, device_scale_factor * page_scale_factor_);
1470   rwhva()->offscreen_helper()->SetScaledContentSize(scaled_contents_size);
1471 }
1472
1473 void EWebView::GetScrollSize(int* width, int* height) {
1474   int w = 0, h = 0;
1475   if (width) {
1476     *width = (rwhva() &&
1477               (w = rwhva()->offscreen_helper()->GetScrollableSize().width()))
1478                  ? w
1479                  : 0;
1480   }
1481   if (height) {
1482     *height = (rwhva() &&
1483                (h = rwhva()->offscreen_helper()->GetScrollableSize().height()))
1484                   ? h
1485                   : 0;
1486   }
1487 }
1488
1489 void EWebView::MoveCaret(const gfx::Point& point) {
1490 #if !defined(USE_AURA)
1491   if (rwhv())
1492     rwhv()->MoveCaret(point);
1493 #endif
1494 }
1495
1496 SelectionControllerEfl* EWebView::GetSelectionController() const {
1497   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1498   RenderWidgetHostViewAura* view = static_cast<RenderWidgetHostViewAura*>(
1499       render_view_host->GetWidget()->GetView());
1500   return view ? view->offscreen_helper()->GetSelectionController() : 0;
1501 }
1502
1503 void EWebView::SelectLinkText(const gfx::Point& touch_point) {
1504 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1505   float device_scale_factor =
1506       display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1507   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1508   render_view_host->Send(new ViewMsg_SelectLinkText(
1509       render_view_host->GetRoutingID(),
1510       gfx::Point(touch_point.x() / device_scale_factor,
1511                  touch_point.y() / device_scale_factor)));
1512 #endif
1513 }
1514
1515 bool EWebView::GetSelectionRange(Eina_Rectangle* left_rect,
1516                                  Eina_Rectangle* right_rect) {
1517   if (left_rect && right_rect) {
1518     gfx::Rect left, right;
1519     if (GetSelectionController()) {
1520       GetSelectionController()->GetSelectionBounds(&left, &right);
1521       GetEinaRectFromGfxRect(left, left_rect);
1522       GetEinaRectFromGfxRect(right, right_rect);
1523       return true;
1524     }
1525   }
1526   return false;
1527 }
1528
1529 Eina_Bool EWebView::ClearSelection() {
1530   if (!rwhva())
1531     return EINA_FALSE;
1532
1533   ResetContextMenuController();
1534   rwhva()->offscreen_helper()->SelectionChanged(std::u16string(), 0,
1535                                                 gfx::Range());
1536
1537   if (GetSelectionController())
1538     return GetSelectionController()->ClearSelectionViaEWebView();
1539
1540   return EINA_FALSE;
1541 }
1542
1543 _Ewk_Hit_Test* EWebView::RequestHitTestDataAt(int x,
1544                                               int y,
1545                                               Ewk_Hit_Test_Mode mode) {
1546   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1547
1548   int view_x, view_y;
1549   EvasToBlinkCords(x, y, &view_x, &view_y);
1550
1551   return RequestHitTestDataAtBlinkCoords(view_x, view_y, mode);
1552 }
1553
1554 Eina_Bool EWebView::AsyncRequestHitTestDataAt(
1555     int x,
1556     int y,
1557     Ewk_Hit_Test_Mode mode,
1558     Ewk_View_Hit_Test_Request_Callback callback,
1559     void* user_data) {
1560   int view_x, view_y;
1561   EvasToBlinkCords(x, y, &view_x, &view_y);
1562   return AsyncRequestHitTestDataAtBlinkCords(
1563       view_x, view_y, mode,
1564       new WebViewAsyncRequestHitTestDataUserCallback(x, y, mode, callback,
1565                                                      user_data));
1566 }
1567
1568 Eina_Bool EWebView::AsyncRequestHitTestDataAtBlinkCords(
1569     int x,
1570     int y,
1571     Ewk_Hit_Test_Mode mode,
1572     Ewk_View_Hit_Test_Request_Callback callback,
1573     void* user_data) {
1574   return AsyncRequestHitTestDataAtBlinkCords(
1575       x, y, mode,
1576       new WebViewAsyncRequestHitTestDataUserCallback(x, y, mode, callback,
1577                                                      user_data));
1578 }
1579
1580 Eina_Bool EWebView::AsyncRequestHitTestDataAtBlinkCords(
1581     int x,
1582     int y,
1583     Ewk_Hit_Test_Mode mode,
1584     WebViewAsyncRequestHitTestDataCallback* cb) {
1585   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1586   DCHECK(cb);
1587
1588   static int64_t request_id = 1;
1589
1590   if (cb) {
1591     RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1592     DCHECK(render_view_host);
1593
1594     if (render_view_host) {
1595 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1596       render_view_host->Send(new EwkViewMsg_DoHitTestAsync(
1597           render_view_host->GetRoutingID(), x, y, mode, request_id));
1598 #endif
1599       hit_test_callback_[request_id] = cb;
1600       ++request_id;
1601       return EINA_TRUE;
1602     }
1603   }
1604
1605   // if failed we delete callback as it is not needed anymore
1606   delete cb;
1607   return EINA_FALSE;
1608 }
1609
1610 void EWebView::DispatchAsyncHitTestData(const Hit_Test_Params& params,
1611                                         int64_t request_id) {
1612   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1613
1614   std::map<int64_t, WebViewAsyncRequestHitTestDataCallback*>::iterator it =
1615       hit_test_callback_.find(request_id);
1616
1617   if (it == hit_test_callback_.end())
1618     return;
1619   std::unique_ptr<_Ewk_Hit_Test> hit_test(new _Ewk_Hit_Test(params));
1620
1621   it->second->Run(hit_test.get(), this);
1622   delete it->second;
1623   hit_test_callback_.erase(it);
1624 }
1625
1626 _Ewk_Hit_Test* EWebView::RequestHitTestDataAtBlinkCoords(
1627     int x,
1628     int y,
1629     Ewk_Hit_Test_Mode mode) {
1630   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1631
1632   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1633
1634   if (render_view_host) {
1635     // We wait on UI thread till hit test data is updated.
1636 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1637     render_view_host->Send(
1638         new EwkViewMsg_DoHitTest(render_view_host->GetRoutingID(), x, y, mode));
1639 #endif
1640     hit_test_completion_.Wait();
1641     return new _Ewk_Hit_Test(hit_test_params_);
1642   }
1643
1644   return nullptr;
1645 }
1646
1647 void EWebView::EvasToBlinkCords(int x, int y, int* view_x, int* view_y) {
1648   DCHECK(display::Screen::GetScreen());
1649   Evas_Coord tmpX, tmpY;
1650   evas_object_geometry_get(evas_object_, &tmpX, &tmpY, NULL, NULL);
1651
1652   if (view_x) {
1653     *view_x = x - tmpX;
1654     *view_x /=
1655         display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1656   }
1657
1658   if (view_y) {
1659     *view_y = y - tmpY;
1660     *view_y /=
1661         display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1662   }
1663 }
1664
1665 void EWebView::UpdateHitTestData(const Hit_Test_Params& params) {
1666   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1667   hit_test_params_ = params;
1668   hit_test_completion_.Signal();
1669 }
1670
1671 void EWebView::OnCopyFromBackingStore(bool success, const SkBitmap& bitmap) {}
1672
1673 void EWebView::OnFocusIn() {
1674   SmartCallback<EWebViewCallbacks::FocusIn>().call();
1675 #if defined(USE_WAYLAND) && !BUILDFLAG(IS_TIZEN_TV)
1676   if (!rwhva() || !rwhva()->offscreen_helper())
1677     return;
1678   ClipboardHelperEfl::GetInstance()->OnWebviewFocusIn(
1679       this, rwhva()->offscreen_helper()->content_image_elm_host(),
1680       rwhva()->offscreen_helper()->IsFocusedNodeContentEditable(),
1681       base::BindRepeating(&EWebView::ExecuteEditCommand,
1682                           base::Unretained(this)));
1683 #endif
1684 }
1685
1686 void EWebView::OnFocusOut() {
1687   SmartCallback<EWebViewCallbacks::FocusOut>().call();
1688 #if defined(USE_WAYLAND) && !BUILDFLAG(IS_TIZEN_TV)
1689   ClipboardHelperEfl::GetInstance()->MaybeInvalidateActiveWebview(this);
1690 #endif
1691 }
1692
1693 void EWebView::RenderViewReady() {
1694   if (rwhva()) {
1695     rwhva()->offscreen_helper()->SetFocusInOutCallbacks(
1696         base::BindRepeating(&EWebView::OnFocusIn, base::Unretained(this)),
1697         base::BindRepeating(&EWebView::OnFocusOut, base::Unretained(this)));
1698   }
1699
1700 #if defined(TIZEN_VIDEO_HOLE)
1701   if (rwhva() && pending_video_hole_setting_) {
1702     rwhva()->host()->SetVideoHoleForRender(pending_video_hole_setting_);
1703     pending_video_hole_setting_ = false;
1704   }
1705 #endif
1706
1707   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1708
1709   SendDelayedMessages(render_view_host);
1710   UpdateWebkitPreferencesEfl(render_view_host);
1711
1712   if (render_view_host) {
1713     WebContents* content = WebContents::FromRenderViewHost(render_view_host);
1714     if (content) {
1715       RenderProcessHost* host = render_view_host->GetProcess();
1716       if (host)
1717         host->AddFilter(new WebViewBrowserMessageFilter(content));
1718     }
1719   }
1720 }
1721
1722 void EWebView::SetQuotaPermissionRequestCallback(
1723     Ewk_Quota_Permission_Request_Callback callback,
1724     void* user_data) {
1725   quota_request_callback_.Set(callback, user_data);
1726 }
1727
1728 void EWebView::InvokeQuotaPermissionRequest(
1729     _Ewk_Quota_Permission_Request* request,
1730     content::QuotaPermissionContext::PermissionCallback cb) {
1731   quota_permission_request_map_[request] = std::move(cb);
1732   request->setView(evas_object());
1733   if (quota_request_callback_.IsCallbackSet())
1734     quota_request_callback_.Run(evas_object(), request);
1735   else
1736     QuotaRequestCancel(request);
1737 }
1738
1739 void EWebView::QuotaRequestReply(const _Ewk_Quota_Permission_Request* request,
1740                                  bool allow) {
1741   DCHECK(quota_permission_request_map_.find(request) !=
1742          quota_permission_request_map_.end());
1743
1744   QuotaPermissionContextEfl::DispatchCallback(
1745       std::move(quota_permission_request_map_[request]),
1746       (allow ? QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
1747              : QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW));
1748
1749   quota_permission_request_map_.erase(request);
1750   delete request;
1751 }
1752
1753 void EWebView::QuotaRequestCancel(
1754     const _Ewk_Quota_Permission_Request* request) {
1755   DCHECK(quota_permission_request_map_.find(request) !=
1756          quota_permission_request_map_.end());
1757
1758   QuotaPermissionContextEfl::DispatchCallback(
1759       std::move(quota_permission_request_map_[request]),
1760       QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
1761   quota_permission_request_map_.erase(request);
1762   delete request;
1763 }
1764
1765 bool EWebView::GetLinkMagnifierEnabled() const {
1766 #if !defined(EWK_BRINGUP)  // FIXME: m71 bringup
1767   return web_contents_->GetMutableRendererPrefs()
1768              ->tap_multiple_targets_strategy ==
1769          TAP_MULTIPLE_TARGETS_STRATEGY_POPUP;
1770 #else
1771   return false;
1772 #endif
1773 }
1774
1775 void EWebView::SetLinkMagnifierEnabled(bool enabled) {
1776 #if !defined(EWK_BRINGUP)  // FIXME: m71 bringup
1777   web_contents_->GetMutableRendererPrefs()->tap_multiple_targets_strategy =
1778       enabled ? TAP_MULTIPLE_TARGETS_STRATEGY_POPUP
1779               : TAP_MULTIPLE_TARGETS_STRATEGY_NONE;
1780 #endif
1781   web_contents_->SyncRendererPrefs();
1782 }
1783
1784 bool EWebView::GetSnapshotAsync(
1785     Eina_Rectangle rect,
1786     Ewk_Web_App_Screenshot_Captured_Callback callback,
1787     void* user_data,
1788     float scale_factor) {
1789   if (!rwhva() || !rwhva()->offscreen_helper())
1790     return false;
1791
1792   rwhva()->offscreen_helper()->RequestSnapshotAsync(
1793       gfx::Rect(rect.x, rect.y, rect.w, rect.h), callback, user_data,
1794       scale_factor);
1795   return true;
1796 }
1797
1798 Evas_Object* EWebView::GetSnapshot(Eina_Rectangle rect, float scale_factor) {
1799   if (!rwhva() || !rwhva()->offscreen_helper())
1800     return nullptr;
1801
1802   return rwhva()->offscreen_helper()->GetSnapshot(
1803       gfx::Rect(rect.x, rect.y, rect.w, rect.h), scale_factor);
1804 }
1805
1806 void EWebView::BackForwardListClear() {
1807   content::NavigationController& controller = web_contents_->GetController();
1808
1809   int entry_count = controller.GetEntryCount();
1810   bool entry_removed = false;
1811
1812   for (int i = 0; i < entry_count; i++) {
1813     if (controller.RemoveEntryAtIndex(i)) {
1814       entry_removed = true;
1815       entry_count = controller.GetEntryCount();
1816       i--;
1817     }
1818   }
1819
1820   if (entry_removed) {
1821     back_forward_list_->ClearCache();
1822     InvokeBackForwardListChangedCallback();
1823   }
1824 }
1825
1826 _Ewk_Back_Forward_List* EWebView::GetBackForwardList() const {
1827   return back_forward_list_.get();
1828 }
1829
1830 void EWebView::InvokeBackForwardListChangedCallback() {
1831   SmartCallback<EWebViewCallbacks::BackForwardListChange>().call();
1832 }
1833
1834 _Ewk_History* EWebView::GetBackForwardHistory() const {
1835   return new _Ewk_History(web_contents_->GetController());
1836 }
1837
1838 bool EWebView::WebAppCapableGet(Ewk_Web_App_Capable_Get_Callback callback,
1839                                 void* userData) {
1840   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
1841   if (!renderViewHost) {
1842     return false;
1843   }
1844 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1845   WebApplicationCapableGetCallback* cb =
1846       new WebApplicationCapableGetCallback(callback, userData);
1847   int callbackId = web_app_capable_get_callback_map_.Add(cb);
1848   return renderViewHost->Send(new EwkViewMsg_WebAppCapableGet(
1849       renderViewHost->GetRoutingID(), callbackId));
1850 #else
1851   return false;
1852 #endif
1853 }
1854
1855 bool EWebView::WebAppIconUrlGet(Ewk_Web_App_Icon_URL_Get_Callback callback,
1856                                 void* userData) {
1857   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
1858   if (!renderViewHost) {
1859     return false;
1860   }
1861 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1862   WebApplicationIconUrlGetCallback* cb =
1863       new WebApplicationIconUrlGetCallback(callback, userData);
1864   int callbackId = web_app_icon_url_get_callback_map_.Add(cb);
1865   return renderViewHost->Send(new EwkViewMsg_WebAppIconUrlGet(
1866       renderViewHost->GetRoutingID(), callbackId));
1867 #else
1868   return false;
1869 #endif
1870 }
1871
1872 bool EWebView::WebAppIconUrlsGet(Ewk_Web_App_Icon_URLs_Get_Callback callback,
1873                                  void* userData) {
1874   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
1875   if (!renderViewHost) {
1876     return false;
1877   }
1878 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1879   WebApplicationIconUrlsGetCallback* cb =
1880       new WebApplicationIconUrlsGetCallback(callback, userData);
1881   int callbackId = web_app_icon_urls_get_callback_map_.Add(cb);
1882   return renderViewHost->Send(new EwkViewMsg_WebAppIconUrlsGet(
1883       renderViewHost->GetRoutingID(), callbackId));
1884 #else
1885   return false;
1886 #endif
1887 }
1888
1889 void EWebView::InvokeWebAppCapableGetCallback(bool capable, int callbackId) {
1890   WebApplicationCapableGetCallback* callback =
1891       web_app_capable_get_callback_map_.Lookup(callbackId);
1892   if (!callback)
1893     return;
1894   callback->Run(capable);
1895   web_app_capable_get_callback_map_.Remove(callbackId);
1896 }
1897
1898 void EWebView::InvokeWebAppIconUrlGetCallback(const std::string& iconUrl,
1899                                               int callbackId) {
1900   WebApplicationIconUrlGetCallback* callback =
1901       web_app_icon_url_get_callback_map_.Lookup(callbackId);
1902   if (!callback)
1903     return;
1904   callback->Run(iconUrl);
1905   web_app_icon_url_get_callback_map_.Remove(callbackId);
1906 }
1907
1908 void EWebView::InvokeWebAppIconUrlsGetCallback(const StringMap& iconUrls,
1909                                                int callbackId) {
1910   WebApplicationIconUrlsGetCallback* callback =
1911       web_app_icon_urls_get_callback_map_.Lookup(callbackId);
1912   if (!callback) {
1913     return;
1914   }
1915   callback->Run(iconUrls);
1916   web_app_icon_urls_get_callback_map_.Remove(callbackId);
1917 }
1918
1919 void EWebView::SetNotificationPermissionCallback(
1920     Ewk_View_Notification_Permission_Callback callback,
1921     void* user_data) {
1922   notification_permission_callback_.Set(callback, user_data);
1923 }
1924
1925 bool EWebView::IsNotificationPermissionCallbackSet() const {
1926   return notification_permission_callback_.IsCallbackSet();
1927 }
1928
1929 bool EWebView::InvokeNotificationPermissionCallback(
1930     Ewk_Notification_Permission_Request* request) {
1931   Eina_Bool ret = EINA_FALSE;
1932   notification_permission_callback_.Run(evas_object_, request, &ret);
1933   return ret;
1934 }
1935
1936 int EWebView::SetEwkViewPlainTextGetCallback(
1937     Ewk_View_Plain_Text_Get_Callback callback,
1938     void* user_data) {
1939   EwkViewPlainTextGetCallback* view_plain_text_callback_ptr =
1940       new EwkViewPlainTextGetCallback;
1941   view_plain_text_callback_ptr->Set(callback, user_data);
1942   return plain_text_get_callback_map_.Add(view_plain_text_callback_ptr);
1943 }
1944
1945 bool EWebView::PlainTextGet(Ewk_View_Plain_Text_Get_Callback callback,
1946                             void* user_data) {
1947   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1948   if (!render_view_host)
1949     return false;
1950 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1951   int plain_text_get_callback_id =
1952       SetEwkViewPlainTextGetCallback(callback, user_data);
1953   return render_view_host->Send(new EwkViewMsg_PlainTextGet(
1954       render_view_host->GetRoutingID(), plain_text_get_callback_id));
1955 #else
1956   return false;
1957 #endif
1958 }
1959
1960 void EWebView::InvokePlainTextGetCallback(const std::string& content_text,
1961                                           int plain_text_get_callback_id) {
1962   EwkViewPlainTextGetCallback* view_plain_text_callback_invoke_ptr =
1963       plain_text_get_callback_map_.Lookup(plain_text_get_callback_id);
1964   view_plain_text_callback_invoke_ptr->Run(evas_object(), content_text.c_str());
1965   plain_text_get_callback_map_.Remove(plain_text_get_callback_id);
1966 }
1967
1968 void EWebView::SetViewGeolocationPermissionCallback(
1969     Ewk_View_Geolocation_Permission_Callback callback,
1970     void* user_data) {
1971   geolocation_permission_cb_.Set(callback, user_data);
1972 }
1973
1974 bool EWebView::InvokeViewGeolocationPermissionCallback(
1975     _Ewk_Geolocation_Permission_Request* permission_context,
1976     Eina_Bool* callback_result) {
1977   return geolocation_permission_cb_.Run(evas_object_, permission_context,
1978                                         callback_result);
1979 }
1980
1981 void EWebView::SetViewUserMediaPermissionCallback(
1982     Ewk_View_User_Media_Permission_Callback callback,
1983     void* user_data) {
1984   user_media_permission_cb_.Set(callback, user_data);
1985 }
1986
1987 bool EWebView::InvokeViewUserMediaPermissionCallback(
1988     _Ewk_User_Media_Permission_Request* permission_context,
1989     Eina_Bool* callback_result) {
1990   return user_media_permission_cb_.Run(evas_object_, permission_context,
1991                                        callback_result);
1992 }
1993
1994 void EWebView::SetViewUserMediaPermissionQueryCallback(
1995     Ewk_View_User_Media_Permission_Query_Callback callback,
1996     void* user_data) {
1997   user_media_permission_query_cb_.Set(callback, user_data);
1998 }
1999
2000 Ewk_User_Media_Permission_Query_Result
2001 EWebView::InvokeViewUserMediaPermissionQueryCallback(
2002     _Ewk_User_Media_Permission_Query* permission_context) {
2003   return user_media_permission_query_cb_.Run(evas_object_, permission_context);
2004 }
2005
2006 void EWebView::SetViewUnfocusAllowCallback(
2007     Ewk_View_Unfocus_Allow_Callback callback,
2008     void* user_data) {
2009   unfocus_allow_cb_.Set(callback, user_data);
2010 }
2011
2012 bool EWebView::InvokeViewUnfocusAllowCallback(Ewk_Unfocus_Direction direction,
2013                                               Eina_Bool* callback_result) {
2014   return unfocus_allow_cb_.Run(evas_object_, direction, callback_result);
2015 }
2016
2017 void EWebView::StopFinding() {
2018   web_contents_->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION);
2019 }
2020
2021 void EWebView::SetProgressValue(double progress) {
2022   progress_ = progress;
2023 }
2024
2025 double EWebView::GetProgressValue() {
2026   return progress_;
2027 }
2028
2029 const char* EWebView::GetTitle() {
2030   title_ = base::UTF16ToUTF8(web_contents_->GetTitle());
2031   return title_.c_str();
2032 }
2033
2034 bool EWebView::SaveAsPdf(int width, int height, const std::string& filename) {
2035   if (!rwhva())
2036     return false;
2037   rwhva()->host()->PrintToPdf(width, height, base::FilePath(filename));
2038   return true;
2039 }
2040
2041 bool EWebView::GetMHTMLData(Ewk_View_MHTML_Data_Get_Callback callback,
2042                             void* user_data) {
2043   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2044   if (!render_view_host)
2045     return false;
2046
2047   MHTMLCallbackDetails* callback_details = new MHTMLCallbackDetails;
2048   callback_details->Set(callback, user_data);
2049 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2050   int mhtml_callback_id = mhtml_callback_map_.Add(callback_details);
2051   return render_view_host->Send(new EwkViewMsg_GetMHTMLData(
2052       render_view_host->GetRoutingID(), mhtml_callback_id));
2053 #else
2054   return false;
2055 #endif
2056 }
2057
2058 void EWebView::OnMHTMLContentGet(const std::string& mhtml_content,
2059                                  int callback_id) {
2060   MHTMLCallbackDetails* callback_details =
2061       mhtml_callback_map_.Lookup(callback_id);
2062   callback_details->Run(evas_object(), mhtml_content.c_str());
2063   mhtml_callback_map_.Remove(callback_id);
2064 }
2065
2066 bool EWebView::SavePageAsMHTML(const std::string& path,
2067                                Ewk_View_Save_Page_Callback callback,
2068                                void* user_data) {
2069   if (!web_contents_)
2070     return false;
2071
2072   GURL url(web_contents_->GetLastCommittedURL());
2073   std::u16string title(web_contents_->GetTitle());
2074
2075   // Post function that has file access to blocking task runner.
2076   return base::PostTaskAndReplyWithResult(
2077       base::ThreadPool::CreateSequencedTaskRunner(
2078           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
2079            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})
2080           .get(),
2081       FROM_HERE,
2082       base::BindOnce(&GenerateMHTMLFilePath, url, base::UTF16ToUTF8(title),
2083                      path),
2084       base::BindOnce(&EWebView::GenerateMHTML, base::Unretained(this), callback,
2085                      user_data));
2086 }
2087
2088 void EWebView::GenerateMHTML(Ewk_View_Save_Page_Callback callback,
2089                              void* user_data,
2090                              const base::FilePath& file_path) {
2091   if (file_path.empty()) {
2092     LOG(ERROR) << "Generating file path was failed";
2093     callback(evas_object_, nullptr, user_data);
2094     return;
2095   }
2096
2097   MHTMLGenerationParams params(file_path);
2098   web_contents_->GenerateMHTML(
2099       params, base::BindOnce(&EWebView::MHTMLGenerated, base::Unretained(this),
2100                              callback, user_data, file_path));
2101 }
2102
2103 void EWebView::MHTMLGenerated(Ewk_View_Save_Page_Callback callback,
2104                               void* user_data,
2105                               const base::FilePath& file_path,
2106                               int64_t file_size) {
2107   callback(evas_object_, file_size > 0 ? file_path.value().c_str() : nullptr,
2108            user_data);
2109 }
2110
2111 bool EWebView::GetBackgroundColor(
2112     Ewk_View_Background_Color_Get_Callback callback,
2113     void* user_data) {
2114   if (!rwhva())
2115     return false;
2116   BackgroundColorGetCallback* cb =
2117       new BackgroundColorGetCallback(callback, user_data);
2118   int callback_id = background_color_get_callback_map_.Add(cb);
2119
2120   rwhva()->host()->RequestBackgroundColor(callback_id);
2121   return true;
2122 }
2123
2124 void EWebView::OnGetBackgroundColor(int callback_id, SkColor bg_color) {
2125   BackgroundColorGetCallback* cb =
2126       background_color_get_callback_map_.Lookup(callback_id);
2127
2128   if (!cb)
2129     return;
2130
2131   cb->Run(evas_object(), SkColorGetR(bg_color), SkColorGetG(bg_color),
2132           SkColorGetB(bg_color), SkColorGetA(bg_color));
2133   background_color_get_callback_map_.Remove(callback_id);
2134 }
2135
2136 bool EWebView::IsFullscreen() {
2137   return web_contents_delegate_->IsFullscreenForTabOrPending(
2138       web_contents_.get());
2139 }
2140
2141 void EWebView::ExitFullscreen() {
2142   WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents_.get());
2143   wci->ExitFullscreen(false);
2144 }
2145
2146 double EWebView::GetScale() {
2147   return page_scale_factor_;
2148 }
2149
2150 void EWebView::DidChangePageScaleFactor(double scale_factor) {
2151   page_scale_factor_ = scale_factor;
2152   wcva()->wcva_helper()->SetPageScaleFactor(scale_factor);
2153   SetScaledContentsSize();
2154
2155   // Notify app about the scale change.
2156   scale_changed_cb_.Run(evas_object_, scale_factor);
2157 }
2158
2159 inline JavaScriptDialogManagerEfl* EWebView::GetJavaScriptDialogManagerEfl() {
2160   return static_cast<JavaScriptDialogManagerEfl*>(
2161       web_contents_delegate_->GetJavaScriptDialogManager(web_contents_.get()));
2162 }
2163
2164 void EWebView::SetJavaScriptAlertCallback(
2165     Ewk_View_JavaScript_Alert_Callback callback,
2166     void* user_data) {
2167   GetJavaScriptDialogManagerEfl()->SetAlertCallback(callback, user_data);
2168 }
2169
2170 void EWebView::JavaScriptAlertReply() {
2171   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(true,
2172                                                                std::string());
2173   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
2174 }
2175
2176 void EWebView::SetJavaScriptConfirmCallback(
2177     Ewk_View_JavaScript_Confirm_Callback callback,
2178     void* user_data) {
2179   GetJavaScriptDialogManagerEfl()->SetConfirmCallback(callback, user_data);
2180 }
2181
2182 void EWebView::JavaScriptConfirmReply(bool result) {
2183   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(result,
2184                                                                std::string());
2185   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
2186 }
2187
2188 void EWebView::SetJavaScriptPromptCallback(
2189     Ewk_View_JavaScript_Prompt_Callback callback,
2190     void* user_data) {
2191   GetJavaScriptDialogManagerEfl()->SetPromptCallback(callback, user_data);
2192 }
2193
2194 void EWebView::JavaScriptPromptReply(const char* result) {
2195   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(
2196       true, (std::string(result)));
2197   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
2198 }
2199
2200 void EWebView::GetPageScaleRange(double* min_scale, double* max_scale) {
2201   auto prefs = web_contents_->GetOrCreateWebPreferences();
2202   if (min_scale)
2203     *min_scale = prefs.default_minimum_page_scale_factor;
2204   if (max_scale)
2205     *max_scale = prefs.default_maximum_page_scale_factor;
2206 }
2207
2208 void EWebView::SetDrawsTransparentBackground(bool enabled) {
2209   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2210   if (!render_view_host)
2211     return;
2212 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2213   render_view_host->Send(new EwkViewMsg_SetDrawsTransparentBackground(
2214       render_view_host->GetRoutingID(), enabled));
2215 #endif
2216 }
2217
2218 void EWebView::GetSessionData(const char** data, unsigned* length) const {
2219   static const int MAX_SESSION_ENTRY_SIZE = std::numeric_limits<int>::max();
2220
2221   NavigationController& navigationController = web_contents_->GetController();
2222   base::Pickle sessionPickle;
2223   const int itemCount = navigationController.GetEntryCount();
2224
2225   sessionPickle.WriteInt(itemCount);
2226   sessionPickle.WriteInt(navigationController.GetCurrentEntryIndex());
2227
2228   for (int i = 0; i < itemCount; i++) {
2229     NavigationEntry* navigationEntry = navigationController.GetEntryAtIndex(i);
2230     sessions::SerializedNavigationEntry serializedEntry =
2231         sessions::ContentSerializedNavigationBuilder::FromNavigationEntry(
2232             i, navigationEntry);
2233     serializedEntry.WriteToPickle(MAX_SESSION_ENTRY_SIZE, &sessionPickle);
2234   }
2235
2236   *data = static_cast<char*>(malloc(sizeof(char) * sessionPickle.size()));
2237   memcpy(const_cast<char*>(*data), sessionPickle.data(), sessionPickle.size());
2238   *length = sessionPickle.size();
2239 }
2240
2241 bool EWebView::RestoreFromSessionData(const char* data, unsigned length) {
2242   base::Pickle sessionPickle(data, length);
2243   base::PickleIterator pickleIterator(sessionPickle);
2244   int entryCount;
2245   int currentEntry;
2246
2247   if (!pickleIterator.ReadInt(&entryCount))
2248     return false;
2249   if (!pickleIterator.ReadInt(&currentEntry))
2250     return false;
2251
2252   std::vector<sessions::SerializedNavigationEntry> serializedEntries;
2253   serializedEntries.resize(entryCount);
2254   for (int i = 0; i < entryCount; ++i) {
2255     if (!serializedEntries.at(i).ReadFromPickle(&pickleIterator))
2256       return false;
2257   }
2258
2259   if (!entryCount)
2260     return true;
2261
2262   if (!context())
2263     return false;
2264
2265   std::vector<std::unique_ptr<content::NavigationEntry>> scopedEntries =
2266       sessions::ContentSerializedNavigationBuilder::ToNavigationEntries(
2267           serializedEntries, context()->browser_context());
2268
2269   NavigationController& navigationController = web_contents_->GetController();
2270
2271   if (currentEntry < 0)
2272     currentEntry = 0;
2273
2274   if (currentEntry >= static_cast<int>(scopedEntries.size()))
2275     currentEntry = scopedEntries.size() - 1;
2276
2277   navigationController.Restore(currentEntry, RestoreType::kRestored,
2278                                &scopedEntries);
2279   return true;
2280 }
2281
2282 void EWebView::SetBrowserFont() {
2283 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2284   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2285   if (render_view_host) {
2286     IPC::Message* message =
2287         new EwkViewMsg_SetBrowserFont(render_view_host->GetRoutingID());
2288
2289     if (render_view_host->IsRenderViewLive())
2290       render_view_host->Send(message);
2291     else
2292       delayed_messages_.push_back(message);
2293   }
2294 #endif
2295 }
2296
2297 bool EWebView::IsDragging() const {
2298   return wcva()->wcva_helper()->IsDragging();
2299 }
2300
2301 void EWebView::ShowFileChooser(content::RenderFrameHost* render_frame_host,
2302                                const blink::mojom::FileChooserParams& params) {
2303   if (!IsMobileProfile() && !IsWearableProfile())
2304     return;
2305
2306 #if !defined(EWK_BRINGUP)  // FIXME: m71 bringup
2307   if (params.capture) {
2308     const std::string capture_types[] = {"video/*", "audio/*", "image/*"};
2309     unsigned int capture_types_num =
2310         sizeof(capture_types) / sizeof(*capture_types);
2311     for (unsigned int i = 0; i < capture_types_num; ++i) {
2312       for (unsigned int j = 0; j < params.accept_types.size(); ++j) {
2313         if (UTF16ToUTF8(params.accept_types[j]) == capture_types[i]) {
2314           filechooser_mode_ = params.mode;
2315           LaunchCamera(params.accept_types[j]);
2316           return;
2317         }
2318       }
2319     }
2320   }
2321   file_chooser_.reset(
2322       new content::FileChooserControllerEfl(render_frame_host, &params));
2323   file_chooser_->Open();
2324 #endif
2325 }
2326
2327 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
2328 void EWebView::SetViewMode(blink::WebViewMode view_mode) {
2329   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2330   if (!render_view_host)
2331     return;
2332
2333   IPC::Message* message =
2334       new ViewMsg_SetViewMode(render_view_host->GetRoutingID(), view_mode);
2335   if (render_view_host->IsRenderViewLive()) {
2336     render_view_host->Send(message);
2337   } else {
2338     delayed_messages_.push_back(message);
2339   }
2340 }
2341 #endif
2342
2343 gfx::Point EWebView::GetContextMenuPosition() const {
2344   return context_menu_position_;
2345 }
2346
2347 void EWebView::ShowContentsDetectedPopup(const char* message) {
2348   popup_controller_.reset(new PopupControllerEfl(this));
2349   popup_controller_->openPopup(message);
2350 }
2351
2352 void EWebView::RequestColorPicker(int r, int g, int b, int a) {
2353   input_picker_.reset(new InputPicker(this));
2354   input_picker_->ShowColorPicker(r, g, b, a);
2355 }
2356
2357 bool EWebView::SetColorPickerColor(int r, int g, int b, int a) {
2358 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2359   web_contents_->DidChooseColorInColorChooser(SkColorSetARGB(a, r, g, b));
2360 #endif
2361   return true;
2362 }
2363
2364 void EWebView::InputPickerShow(ui::TextInputType input_type,
2365                                double input_value,
2366                                content::DateTimeChooserEfl* date_time_chooser) {
2367   input_picker_.reset(new InputPicker(this));
2368   date_time_chooser_ = date_time_chooser;
2369   input_picker_->ShowDatePicker(input_type, input_value);
2370 }
2371
2372 void EWebView::LoadNotFoundErrorPage(const std::string& invalidUrl) {
2373 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2374   RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
2375   if (render_frame_host)
2376     render_frame_host->Send(new EwkFrameMsg_LoadNotFoundErrorPage(
2377         render_frame_host->GetRoutingID(), invalidUrl));
2378 #endif
2379 }
2380
2381 std::string EWebView::GetPlatformLocale() {
2382   char* local_default = setlocale(LC_CTYPE, 0);
2383   if (!local_default)
2384     return std::string("en-US");
2385   std::string locale = std::string(local_default);
2386   size_t position = locale.find('_');
2387   if (position != std::string::npos)
2388     locale.replace(position, 1, "-");
2389   position = locale.find('.');
2390   if (position != std::string::npos)
2391     locale = locale.substr(0, position);
2392   return locale;
2393 }
2394
2395 int EWebView::StartInspectorServer(int port) {
2396   return context_->InspectorServerStart(port);
2397 }
2398
2399 bool EWebView::StopInspectorServer() {
2400   return context_->InspectorServerStop();
2401 }
2402
2403 void EWebView::InvokeWebProcessCrashedCallback() {
2404   DCHECK_CURRENTLY_ON(BrowserThread::UI);
2405   const GURL last_url = GetURL();
2406   bool callback_handled = false;
2407   SmartCallback<EWebViewCallbacks::WebProcessCrashed>().call(&callback_handled);
2408   if (!callback_handled)
2409     LoadHTMLString(kRendererCrashedHTMLMessage, NULL,
2410                    last_url.possibly_invalid_spec().c_str());
2411 }
2412
2413 void EWebView::SyncAcceptLanguages(const std::string& accept_languages) {
2414   web_contents_->GetMutableRendererPrefs()->accept_languages = accept_languages;
2415   web_contents_->SyncRendererPrefs();
2416   BrowserContext* browser_context = web_contents_->GetBrowserContext();
2417   if (!browser_context)
2418     return;
2419
2420   auto* storage_partition = browser_context->GetDefaultStoragePartition();
2421   if (!storage_partition)
2422     return;
2423
2424   if (auto* network_context = storage_partition->GetNetworkContext())
2425     network_context->SetAcceptLanguage(accept_languages);
2426 }
2427
2428 void EWebView::HandleRendererProcessCrash() {
2429   base::ThreadPool::PostTask(
2430       FROM_HERE, {BrowserThread::UI},
2431       base::BindOnce(&EWebView::InvokeWebProcessCrashedCallback,
2432                      base::Unretained(this)));
2433 }
2434
2435 void EWebView::InitializeContent() {
2436   WebContents* new_contents = create_new_window_web_contents_cb_.Run(this);
2437   if (!new_contents) {
2438     WebContents::CreateParams params(context_->browser_context());
2439     web_contents_.reset(
2440         new WebContentsImplEfl(context_->browser_context(), this));
2441     static_cast<WebContentsImpl*>(web_contents_.get())
2442         ->Init(params, blink::FramePolicy());
2443   } else {
2444     web_contents_.reset(new_contents);
2445
2446     // When a new webview is created in response to a request from the
2447     // engine, the BrowserContext instance of the originator WebContents
2448     // is used by the newly created WebContents object.
2449     // See more in WebContentsImplEfl::HandleNewWebContentsCreate.
2450     //
2451     // Hence, if as part of the WebView creation, the embedding APP
2452     // passes in a Ewk_Context instance that wraps a different instance of
2453     // BrowserContext than the one the originator WebContents holds,
2454     // undefined behavior can be seen.
2455     //
2456     // This is a snippet code that illustrate the scenario:
2457     //
2458     // (..)
2459     // evas_object_smart_callback_add(web_view_, "create,window",
2460     //                                &OnNewWindowRequest, this);
2461     // (..)
2462     //
2463     // void OnNewWindowRequest(void *data, Evas_Object*, void* out_view) {
2464     //   (..)
2465     //   EvasObject* new_web_view = ewk_view_add_with_context(GetEvas(),
2466     //   ewk_context_new());
2467     //   *static_cast<Evas_Object**>(out_view) = new_web_view;
2468     //   (..)
2469     // }
2470     //
2471     // The new Ewk_Context object created and passed in as parameter to
2472     // ewk_view_add_with_context wraps a different instance of BrowserContext
2473     // than the one the new WebContents object will hold.
2474     //
2475     // CHECK below aims at catching misuse of this API.
2476     bool should_crash = context_->GetImpl()->browser_context() !=
2477                         web_contents_->GetBrowserContext();
2478     if (should_crash) {
2479       CHECK(false)
2480           << "BrowserContext of new WebContents does not match EWebView's. "
2481           << "Please see 'ewk_view_add*' documentation. "
2482           << "Aborting execution ...";
2483     }
2484   }
2485   web_contents_delegate_.reset(new WebContentsDelegateEfl(this));
2486   web_contents_->SetDelegate(web_contents_delegate_.get());
2487   WebContentsImplEfl* wc_efl =
2488       static_cast<WebContentsImplEfl*>(web_contents_.get());
2489   wc_efl->SetEflDelegate(new WebContentsEflDelegateEwk(this));
2490   wcva()->wcva_helper()->SetEflDelegate(wc_efl->GetEflDelegate());
2491
2492   back_forward_list_.reset(new _Ewk_Back_Forward_List(web_contents_.get()));
2493
2494   permission_popup_manager_.reset(new PermissionPopupManager(evas_object_));
2495   gin_native_bridge_dispatcher_host_.reset(
2496       new content::GinNativeBridgeDispatcherHost(web_contents_.get()));
2497
2498   native_view_ =
2499       static_cast<WebContentsImplEfl*>(web_contents_.get())->GetEflNativeView();
2500   evas_object_smart_member_add(native_view_, evas_object_);
2501   static_cast<WebContentsImpl*>(web_contents_.get())
2502       ->set_ewk_view(evas_object_);
2503   InitializeWindowTreeHost();
2504 }
2505
2506 void EWebView::InitializeWindowTreeHost() {
2507   CHECK(aura::Env::GetInstance());
2508
2509   int x, y, width, height;
2510   Ecore_Evas* ee =
2511       ecore_evas_ecore_evas_get(evas_object_evas_get(native_view_));
2512   ecore_evas_geometry_get(ee, &x, &y, &width, &height);
2513
2514   gfx::Rect bounds(x, y, width, height);
2515   ui::PlatformWindowInitProperties properties;
2516   properties.bounds = bounds;
2517
2518   host_ = aura::WindowTreeHost::Create(std::move(properties));
2519   host_->InitHost();
2520   host_->window()->Show();
2521
2522   focus_client_ =
2523       std::make_unique<aura::test::TestFocusClient>(host_->window());
2524   window_parenting_client_ =
2525       std::make_unique<aura::test::TestWindowParentingClient>(host_->window());
2526
2527   aura::Window* content = web_contents_->GetNativeView();
2528   aura::Window* parent = host_->window();
2529   if (!parent->Contains(content)) {
2530     parent->AddChild(content);
2531     content->Show();
2532   }
2533   content->SetBounds(bounds);
2534   RenderWidgetHostView* host_view = web_contents_->GetRenderWidgetHostView();
2535   if (host_view)
2536     host_view->SetSize(bounds.size());
2537 }
2538
2539 #if BUILDFLAG(IS_TIZEN) && !defined(EWK_BRINGUP)
2540 void EWebView::cameraResultCb(service_h request,
2541                               service_h reply,
2542                               service_result_e result,
2543                               void* data) {
2544   if (!IsMobileProfile() && !IsWearableProfile())
2545     return;
2546
2547   EWebView* webview = static_cast<EWebView*>(data);
2548   RenderViewHost* render_view_host =
2549       webview->web_contents_->GetRenderViewHost();
2550   if (result == SERVICE_RESULT_SUCCEEDED) {
2551     int ret = -1;
2552     char** filesarray;
2553     int number;
2554     ret = service_get_extra_data_array(reply, SERVICE_DATA_SELECTED,
2555                                        &filesarray, &number);
2556     if (filesarray) {
2557       for (int i = 0; i < number; i++) {
2558         std::vector<ui::SelectedFileInfo> files;
2559         if (!render_view_host) {
2560           return;
2561         }
2562         if (filesarray[i]) {
2563           GURL url(filesarray[i]);
2564           if (!url.is_valid()) {
2565             base::FilePath path(url.SchemeIsFile() ? url.path()
2566                                                    : filesarray[i]);
2567             files.push_back(ui::SelectedFileInfo(path, base::FilePath()));
2568           }
2569         }
2570         render_view_host->FilesSelectedInChooser(files,
2571                                                  webview->filechooser_mode_);
2572       }
2573     }
2574   } else {
2575     std::vector<ui::SelectedFileInfo> files;
2576     if (render_view_host) {
2577       render_view_host->FilesSelectedInChooser(files,
2578                                                webview->filechooser_mode_);
2579     }
2580   }
2581 }
2582
2583 bool EWebView::LaunchCamera(std::u16string mimetype) {
2584   service_h svcHandle = 0;
2585   if (service_create(&svcHandle) < 0 || !svcHandle) {
2586     LOG(ERROR) << __FUNCTION__ << " Service Creation Failed ";
2587     return false;
2588   }
2589   service_set_operation(svcHandle, SERVICE_OPERATION_CREATE_CONTENT);
2590   service_set_mime(svcHandle, UTF16ToUTF8(mimetype).c_str());
2591   service_add_extra_data(svcHandle, "CALLER", "Browser");
2592
2593   int ret = service_send_launch_request(svcHandle, cameraResultCb, this);
2594   if (ret != SERVICE_ERROR_NONE) {
2595     LOG(ERROR) << __FUNCTION__ << " Service Launch Failed ";
2596     service_destroy(svcHandle);
2597     return false;
2598   }
2599   service_destroy(svcHandle);
2600   return true;
2601 }
2602 #endif
2603
2604 void EWebView::UrlRequestSet(
2605     const char* url,
2606     content::NavigationController::LoadURLType loadtype,
2607     Eina_Hash* headers,
2608     const char* body) {
2609   GURL gurl(url);
2610   content::NavigationController::LoadURLParams params(gurl);
2611   params.load_type = loadtype;
2612   params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
2613
2614   if (body) {
2615     std::string s(body);
2616     params.post_data =
2617         network::ResourceRequestBody::CreateFromBytes(s.data(), s.size());
2618   }
2619
2620   net::HttpRequestHeaders header;
2621   if (headers) {
2622     Eina_Iterator* it = eina_hash_iterator_tuple_new(headers);
2623     Eina_Hash_Tuple* t;
2624     while (eina_iterator_next(it, reinterpret_cast<void**>(&t))) {
2625       if (t->key) {
2626         const char* value_str =
2627             t->data ? static_cast<const char*>(t->data) : "";
2628         base::StringPiece name = static_cast<const char*>(t->key);
2629         base::StringPiece value = value_str;
2630         header.SetHeader(name, value);
2631         // net::HttpRequestHeaders.ToString() returns string with newline
2632         params.extra_headers += header.ToString();
2633       }
2634     }
2635     eina_iterator_free(it);
2636   }
2637
2638   web_contents_->GetController().LoadURLWithParams(params);
2639 }
2640
2641 #if defined(TIZEN_VIDEO_HOLE)
2642 void EWebView::SetVideoHoleSupport(bool enable) {
2643   if (!web_contents_->GetPrimaryMainFrame() ||
2644       !web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive() || !rwhva()) {
2645     pending_video_hole_setting_ = enable;
2646     return;
2647   }
2648
2649   rwhva()->host()->SetVideoHoleForRender(enable);
2650 }
2651 #endif
2652
2653 bool EWebView::HandleShow() {
2654   if (!native_view_)
2655     return false;
2656
2657   Show();
2658   return true;
2659 }
2660
2661 bool EWebView::HandleHide() {
2662   if (!native_view_)
2663     return false;
2664
2665   Hide();
2666   return true;
2667 }
2668
2669 bool EWebView::HandleMove(int x, int y) {
2670   if (!native_view_)
2671     return false;
2672   evas_object_move(native_view_, x, y);
2673
2674 #if defined(TIZEN_VIDEO_HOLE) && !defined(EWK_BRINGUP)
2675   if (rwhva())
2676     rwhva()->offscreen_helper()->DidMoveWebView();
2677 #endif
2678
2679   return true;
2680 }
2681
2682 bool EWebView::HandleResize(int width, int height) {
2683   if (!native_view_)
2684     return false;
2685   evas_object_resize(native_view_, width, height);
2686   return true;
2687 }
2688
2689 bool EWebView::HandleTextSelectionDown(int x, int y) {
2690   if (!GetSelectionController())
2691     return false;
2692   return GetSelectionController()->TextSelectionDown(x, y);
2693 }
2694
2695 bool EWebView::HandleTextSelectionUp(int x, int y) {
2696   if (!GetSelectionController())
2697     return false;
2698   return GetSelectionController()->TextSelectionUp(x, y);
2699 }
2700
2701 void EWebView::HandleTapGestureForSelection(bool is_content_editable) {
2702   if (!GetSelectionController())
2703     return;
2704
2705   GetSelectionController()->PostHandleTapGesture(is_content_editable);
2706 }
2707
2708 void EWebView::HandleZoomGesture(blink::WebGestureEvent& event) {
2709   blink::WebInputEvent::Type event_type = event.GetType();
2710   if (event_type == blink::WebInputEvent::Type::kGestureDoubleTap ||
2711       event_type == blink::WebInputEvent::Type::kGesturePinchBegin) {
2712     SmartCallback<EWebViewCallbacks::ZoomStarted>().call();
2713   }
2714   if (event_type == blink::WebInputEvent::Type::kGestureDoubleTap ||
2715       event_type == blink::WebInputEvent::Type::kGesturePinchEnd) {
2716     SmartCallback<EWebViewCallbacks::ZoomFinished>().call();
2717   }
2718 }
2719
2720 bool EWebView::GetHorizontalPanningHold() const {
2721   if (!rwhva())
2722     return false;
2723   return rwhva()->offscreen_helper()->GetHorizontalPanningHold();
2724 }
2725
2726 void EWebView::SetHorizontalPanningHold(bool hold) {
2727   if (rwhva())
2728     rwhva()->offscreen_helper()->SetHorizontalPanningHold(hold);
2729 }
2730
2731 bool EWebView::GetVerticalPanningHold() const {
2732   if (!rwhva())
2733     return false;
2734   return rwhva()->offscreen_helper()->GetVerticalPanningHold();
2735 }
2736
2737 void EWebView::SetVerticalPanningHold(bool hold) {
2738   if (rwhva())
2739     rwhva()->offscreen_helper()->SetVerticalPanningHold(hold);
2740 }
2741
2742 void EWebView::SendDelayedMessages(RenderViewHost* render_view_host) {
2743   DCHECK(render_view_host);
2744
2745   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
2746     base::ThreadPool::PostTask(
2747         FROM_HERE, {BrowserThread::UI},
2748         base::BindOnce(&EWebView::SendDelayedMessages, base::Unretained(this),
2749                        render_view_host));
2750     return;
2751   }
2752
2753   for (auto iter = delayed_messages_.begin(); iter != delayed_messages_.end();
2754        ++iter) {
2755     IPC::Message* message = *iter;
2756     message->set_routing_id(render_view_host->GetRoutingID());
2757 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2758     render_view_host->Send(message);
2759 #endif
2760   }
2761
2762   delayed_messages_.clear();
2763 }
2764
2765 void EWebView::ClosePage() {
2766   web_contents_->ClosePage();
2767 }
2768
2769 void EWebView::OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll,
2770                               const gfx::Vector2dF& latest_overscroll_delta) {
2771   const gfx::Vector2dF old_overscroll =
2772       accumulated_overscroll - latest_overscroll_delta;
2773
2774   if (latest_overscroll_delta.x() && !old_overscroll.x()) {
2775     latest_overscroll_delta.x() < 0
2776         ? SmartCallback<EWebViewCallbacks::OverscrolledLeft>().call()
2777         : SmartCallback<EWebViewCallbacks::OverscrolledRight>().call();
2778   }
2779   if (latest_overscroll_delta.y() && !old_overscroll.y()) {
2780     latest_overscroll_delta.y() < 0
2781         ? SmartCallback<EWebViewCallbacks::OverscrolledTop>().call()
2782         : SmartCallback<EWebViewCallbacks::OverscrolledBottom>().call();
2783   }
2784 }
2785
2786 void EWebView::SetDidChangeThemeColorCallback(
2787     Ewk_View_Did_Change_Theme_Color_Callback callback,
2788     void* user_data) {
2789   did_change_theme_color_callback_.Set(callback, user_data);
2790 }
2791
2792 void EWebView::DidChangeThemeColor(const SkColor& color) {
2793   did_change_theme_color_callback_.Run(evas_object_, color);
2794 }
2795
2796 #if BUILDFLAG(IS_TIZEN_TV)
2797 void EWebView::DrawLabel(Evas_Object* image, Eina_Rectangle rect) {
2798   if (rwhva())
2799     rwhva()->offscreen_helper()->DrawLabel(image, rect);
2800 }
2801
2802 void EWebView::ClearLabels() {
2803   if (rwhva())
2804     rwhva()->offscreen_helper()->ClearLabels();
2805 }
2806 #endif
2807
2808 void EWebView::RequestManifest(Ewk_View_Request_Manifest_Callback callback,
2809                                void* user_data) {
2810   web_contents_delegate_->RequestManifestInfo(callback, user_data);
2811 }
2812
2813 void EWebView::DidRespondRequestManifest(
2814     _Ewk_View_Request_Manifest* manifest,
2815     Ewk_View_Request_Manifest_Callback callback,
2816     void* user_data) {
2817   callback(evas_object_, manifest, user_data);
2818 }
2819
2820 void EWebView::SetSessionTimeout(uint64_t timeout) {
2821   if (web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive() && rwhva())
2822     rwhva()->host()->SetLongPollingGlobalTimeout(timeout);
2823 }
2824
2825 void EWebView::SetExceededIndexedDatabaseQuotaCallback(
2826     Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback,
2827     void* user_data) {
2828   exceeded_indexed_db_quota_callback_.Set(callback, user_data);
2829   content::BrowserContextEfl* browser_context =
2830       static_cast<content::BrowserContextEfl*>(
2831           web_contents_->GetBrowserContext());
2832   if (browser_context) {
2833     browser_context->GetSpecialStoragePolicyEfl()->SetQuotaExceededCallback(
2834         base::BindOnce(&EWebView::InvokeExceededIndexedDatabaseQuotaCallback,
2835                        base::Unretained(this)));
2836   }
2837 }
2838
2839 void EWebView::InvokeExceededIndexedDatabaseQuotaCallback(
2840     const GURL& origin,
2841     int64_t current_quota) {
2842   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
2843     base::ThreadPool::PostTask(
2844         FROM_HERE, {BrowserThread::UI},
2845         base::BindOnce(&EWebView::InvokeExceededIndexedDatabaseQuotaCallback,
2846                        base::Unretained(this), origin, current_quota));
2847     return;
2848   }
2849   LOG(INFO) << __func__ << "()" << origin << ", " << current_quota;
2850   CHECK(!exceeded_indexed_db_quota_origin_.get());
2851   exceeded_indexed_db_quota_origin_.reset(new Ewk_Security_Origin(origin));
2852   exceeded_indexed_db_quota_callback_.Run(
2853       evas_object_, exceeded_indexed_db_quota_origin_.get(), current_quota);
2854 }
2855
2856 void EWebView::ExceededIndexedDatabaseQuotaReply(bool allow) {
2857   if (!exceeded_indexed_db_quota_origin_.get()) {
2858     LOG(WARNING) << __func__ << "() : callback is not invoked!";
2859     return;
2860   }
2861   LOG(INFO) << __func__ << "()" << exceeded_indexed_db_quota_origin_->GetURL()
2862             << ", " << allow;
2863   content::BrowserContextEfl* browser_context =
2864       static_cast<content::BrowserContextEfl*>(
2865           web_contents_->GetBrowserContext());
2866   if (browser_context) {
2867     browser_context->GetSpecialStoragePolicyEfl()->SetUnlimitedStoragePolicy(
2868         exceeded_indexed_db_quota_origin_->GetURL(), allow);
2869   }
2870   exceeded_indexed_db_quota_origin_.reset();
2871 }
2872
2873 bool EWebView::ShouldIgnoreNavigation(
2874     content::NavigationHandle* navigation_handle) {
2875   if (!navigation_handle->GetURL().is_valid() ||
2876       !navigation_handle->GetURL().SchemeIs("appcontrol") ||
2877       (!navigation_handle->HasUserGesture() &&
2878        !navigation_handle->WasServerRedirect())) {
2879     return false;
2880   }
2881
2882   _Ewk_App_Control app_control(
2883       this, navigation_handle->GetURL().possibly_invalid_spec());
2884   return app_control.Proceed();
2885 }
2886
2887 bool EWebView::SetVisibility(bool enable) {
2888   if (!web_contents_)
2889     return false;
2890
2891   if (enable)
2892     web_contents_->WasShown();
2893   else
2894     web_contents_->WasHidden();
2895
2896   return true;
2897 }
2898
2899 #if defined(TIZEN_ATK_SUPPORT)
2900 void EWebView::UpdateSpatialNavigationStatus(Eina_Bool enable) {
2901   if (settings_->getPreferences().spatial_navigation_enabled == enable)
2902     return;
2903
2904   settings_->getPreferences().spatial_navigation_enabled = enable;
2905   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
2906   if (wc)
2907     wc->SetSpatialNavigationEnabled(enable);
2908 }
2909
2910 void EWebView::UpdateAccessibilityStatus(Eina_Bool enable) {
2911   if (settings_->getPreferences().atk_enabled == enable)
2912     return;
2913
2914   settings_->getPreferences().atk_enabled = enable;
2915   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
2916   if (wc)
2917     wc->SetAtkEnabled(enable);
2918 }
2919
2920 void EWebView::InitAtk() {
2921   EWebAccessibilityUtil::GetInstance()->ToggleAtk(lazy_initialize_atk_);
2922 }
2923
2924 /* LCOV_EXCL_START */
2925 bool EWebView::GetAtkStatus() {
2926   auto state = content::BrowserAccessibilityStateImpl::GetInstance();
2927   if (!state)
2928     return false;
2929   return state->IsAccessibleBrowser();
2930 }
2931 /* LCOV_EXCL_STOP */
2932 #endif