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