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