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