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