[M120 Migration] Support Downloadable font info feature
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / eweb_view.cc
1 // Copyright 2014-2020 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "eweb_view.h"
6
7 #include <Ecore_Evas.h>
8 #include <Eina.h>
9 #include <Elementary.h>
10
11 #include "base/command_line.h"
12 #include "base/files/file_util.h"
13 #include "base/functional/bind.h"
14 #include "base/json/json_string_value_serializer.h"
15 #include "base/logging.h"
16 #include "base/pickle.h"
17 #include "base/strings/escape.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/task/thread_pool.h"
20 #include "browser/javascript_dialog_manager_efl.h"
21 #include "browser/javascript_interface/gin_native_bridge_dispatcher_host.h"
22 #include "browser/navigation_policy_handler_efl.h"
23 #include "browser/scoped_allow_wait_for_legacy_web_view_api.h"
24 #include "browser/select_picker/select_picker_mobile.h"
25 #include "browser/select_picker/select_picker_tv.h"
26 #include "browser/web_view_browser_message_filter.h"
27 #include "browser_context_efl.h"
28 #include "common/content_client_efl.h"
29 #include "common/render_messages_ewk.h"
30 #include "common/version_info.h"
31 #include "common/web_contents_utils.h"
32 #include "components/sessions/content/content_serialized_navigation_builder.h"
33 #include "components/sessions/core/serialized_navigation_entry.h"
34 #include "content/browser/renderer_host/render_view_host_impl.h"
35 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
36 #include "content/browser/renderer_host/ui_events_helper.h"
37 #include "content/browser/web_contents/web_contents_impl_efl.h"
38 #include "content/browser/web_contents/web_contents_view.h"
39 #include "content/browser/web_contents/web_contents_view_aura.h"
40 #include "content/browser/web_contents/web_contents_view_aura_helper_efl.h"
41 #include "content/common/content_client_export.h"
42 #include "content/public/browser/browser_message_filter.h"
43 #include "content/public/browser/browser_task_traits.h"
44 #include "content/public/browser/browser_thread.h"
45 #include "content/public/browser/host_zoom_map.h"
46 #include "content/public/browser/navigation_controller.h"
47 #include "content/public/browser/navigation_entry.h"
48 #include "content/public/browser/navigation_handle.h"
49 #include "content/public/common/content_client.h"
50 #include "content/public/common/content_switches.h"
51 #include "content/public/common/mhtml_generation_params.h"
52 #include "content/public/common/user_agent.h"
53 #include "net/base/filename_util.h"
54 #include "permission_popup_manager.cc"
55 #include "private/ewk_app_control_private.h"
56 #include "private/ewk_back_forward_list_private.h"
57 #include "private/ewk_context_private.h"
58 #include "private/ewk_frame_private.h"
59 #include "private/ewk_policy_decision_private.h"
60 #include "private/ewk_quota_permission_request_private.h"
61 #include "private/ewk_settings_private.h"
62 #include "private/webview_delegate_ewk.h"
63 #include "public/ewk_hit_test_internal.h"
64 #include "services/network/public/cpp/features.h"
65 #include "services/network/public/cpp/resource_request_body.h"
66 #include "services/network/public/mojom/network_context.mojom.h"
67 #include "skia/ext/platform_canvas.h"
68 #include "third_party/blink/public/common/page/page_zoom.h"
69 #include "third_party/blink/public/platform/web_string.h"
70 #include "tizen/system_info.h"
71 #include "ui/aura/env.h"
72 #include "ui/aura/test/test_focus_client.h"
73 #include "ui/aura/test/test_window_parenting_client.h"
74 #include "ui/aura/window.h"
75 #include "ui/base/clipboard/clipboard_helper_efl.h"
76 #include "ui/base/l10n/l10n_util.h"
77 #include "ui/compositor/compositor_observer_efl.h"
78 #include "ui/display/screen.h"
79 #include "ui/events/event_switches.h"
80 #include "ui/gfx/geometry/dip_util.h"
81 #include "ui/gfx/geometry/vector2d_f.h"
82 #include "ui/ozone/platform/efl/efl_event_handler.h"
83 #include "ui/platform_window/platform_window_init_properties.h"
84 #include "web_contents_delegate_efl.h"
85 #include "webview_delegate_efl.h"
86
87 #include <iostream>
88
89 #if defined(TIZEN_ATK_SUPPORT)
90 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
91 #include "eweb_accessibility.h"
92 #include "eweb_accessibility_util.h"
93 #endif
94
95 #if defined(TIZEN_AUTOFILL_FW)
96 #include "browser/autofill/autofill_request_manager.h"
97 #include "components/autofill/core/common/autofill_switches.h"
98 #endif
99
100 #if BUILDFLAG(IS_TIZEN_TV)
101 #include "browser/mixed_content_observer.h"
102 #include "common/application_type.h"
103 #include "devtools_port_manager.h"
104 #include "private/ewk_file_chooser_request_private.h"
105 #include "public/ewk_media_downloadable_font_info.h"
106 #include "public/ewk_user_media_internal.h"
107 #endif
108
109 #if defined(TIZEN_PEPPER_EXTENSIONS)
110 #include "efl/window_factory.h"
111 #include "ewk/efl_integration/ewk_privilege_checker.h"
112 #endif  // defined(TIZEN_PEPPER_EXTENSIONS)
113
114 #if defined(USE_WAYLAND) && defined(TIZEN_PEPPER_EXTENSIONS)
115 #include <Ecore_Wayland.h>
116 #endif  // defined(USE_WAYLAND)
117
118 #if defined(TIZEN_TBM_SUPPORT)
119 #include "ui/compositor/compositor.h"
120 #endif
121
122 using namespace content;
123 using web_contents_utils::WebViewFromWebContents;
124
125 namespace {
126
127 const int kTitleLengthMax = 80;
128 const base::FilePath::CharType kMHTMLFileNameExtension[] =
129     FILE_PATH_LITERAL(".mhtml");
130 const base::FilePath::CharType kMHTMLExtension[] = FILE_PATH_LITERAL("mhtml");
131 const base::FilePath::CharType kDefaultFileName[] =
132     FILE_PATH_LITERAL("saved_page");
133 const char kReplaceChars[] = " ";
134 const char kReplaceWith[] = "_";
135
136 static const char* kRendererCrashedHTMLMessage =
137     "<html><body><h1>Renderer process has crashed!</h1></body></html>";
138
139 // "visible,content,changed" is an email-app specific signal which informs
140 // that the web view is only partially visible.
141 static const char* kVisibleContentChangedSignalName = "visible,content,changed";
142
143 // email-app specific signal which informs that custom scrolling is started.
144 const char* kCustomScrollBeginSignalName = "custom,scroll,begin";
145
146 // email-app specific signal which informs that custom scrolling is finished.
147 const char* kCustomScrollEndSignalName = "custom,scroll,end";
148
149 const float kDelayShowContextMenuTime = 0.2f;
150
151 inline void SetDefaultStringIfNull(const char*& variable,
152                                    const char* default_string) {
153   if (!variable) {
154     variable = default_string;
155   }
156 }
157
158 void GetEinaRectFromGfxRect(const gfx::Rect& gfx_rect,
159                             Eina_Rectangle* eina_rect) {
160   eina_rect->x = gfx_rect.x();
161   eina_rect->y = gfx_rect.y();
162   eina_rect->w = gfx_rect.width();
163   eina_rect->h = gfx_rect.height();
164 }
165
166 #if BUILDFLAG(IS_TIZEN)
167 static Eina_Bool RotateWindowCb(void* data, int type, void* event) {
168   auto wv = static_cast<EWebView*>(data);
169 #if defined(TIZEN_TBM_SUPPORT)
170   if (wv->rwhva() && wv->rwhva()->GetCompositor() &&
171       wv->rwhva()->GetCompositor()->use_tbm_surface_for_offscreen_rendering()) {
172     Ecore_Wl2_Event_Window_Rotation* rotateEvent =
173         static_cast<Ecore_Wl2_Event_Window_Rotation*>(event);
174     if (rotateEvent != nullptr) {
175       LOG(INFO) << "For NUI app, new ori " << rotateEvent->angle;
176       wv->SetOrientation(rotateEvent->angle);
177     }
178     return ECORE_CALLBACK_PASS_ON;
179   }
180 #endif
181   LOG(INFO) << "New ori "
182             << ecore_evas_rotation_get(
183                    ecore_evas_ecore_evas_get(wv->GetEvas()));
184   wv->SetOrientation(
185       ecore_evas_rotation_get(ecore_evas_ecore_evas_get(wv->GetEvas())));
186   return ECORE_CALLBACK_PASS_ON;
187 }
188 #endif
189
190 static content::WebContents* NullCreateWebContents(void*) {
191   return NULL;
192 }
193
194 base::FilePath GenerateMHTMLFilePath(const GURL& url,
195                                      const std::string& title,
196                                      const std::string& base_path) {
197   base::FilePath file_path(base_path);
198
199   if (base::DirectoryExists(file_path)) {
200     std::string title_part(title.substr(0, kTitleLengthMax));
201     base::ReplaceChars(title_part, kReplaceChars, kReplaceWith, &title_part);
202     base::FilePath file_name =
203         net::GenerateFileName(url, std::string(), std::string(), title_part,
204                               std::string(), kDefaultFileName);
205     DCHECK(!file_name.empty());
206     file_path = file_path.Append(file_name);
207   }
208
209   if (file_path.Extension().empty())
210     file_path = file_path.AddExtension(kMHTMLExtension);
211   else if (!file_path.MatchesExtension(kMHTMLFileNameExtension))
212     file_path = file_path.ReplaceExtension(kMHTMLExtension);
213
214   if (!base::PathExists(file_path))
215     return file_path;
216
217   int uniquifier = base::GetUniquePathNumber(file_path);
218   if (uniquifier > 0) {
219     return file_path.InsertBeforeExtensionASCII(
220         base::StringPrintf(" (%d)", uniquifier));
221   }
222
223   return base::FilePath();
224 }
225
226 SelectPickerBase* CreateSelectPicker(
227     EWebView* web_view,
228     int selected_index,
229     std::vector<blink::mojom::MenuItemPtr> items,
230     bool is_multiple_selection,
231     const gfx::Rect& bounds) {
232   SelectPickerBase* picker;
233   if (IsTvProfile()) {
234     picker =
235         new SelectPickerTv(web_view, selected_index, is_multiple_selection);
236   } else {
237     picker =
238         new SelectPickerMobile(web_view, selected_index, is_multiple_selection);
239   }
240   // Create two separate Elm_Genlist_Item_Class classes, because EFL cannot swap
241   // item_style at runtime.
242   picker->InitializeItemClass();
243   picker->InitializeGroupClass();
244   picker->Init(std::move(items), bounds);
245   return picker;
246 }
247
248 }  // namespace
249
250 class WebViewAsyncRequestHitTestDataCallback {
251  public:
252   WebViewAsyncRequestHitTestDataCallback(int x, int y, Ewk_Hit_Test_Mode mode)
253       : x_(x), y_(y), mode_(mode) {}
254   virtual ~WebViewAsyncRequestHitTestDataCallback(){};
255
256   virtual void Run(_Ewk_Hit_Test* hit_test, EWebView* web_view) = 0;
257
258  protected:
259   int GetX() const { return x_; }
260   int GetY() const { return y_; }
261   Ewk_Hit_Test_Mode GetMode() const { return mode_; }
262
263  private:
264   int x_;
265   int y_;
266   Ewk_Hit_Test_Mode mode_;
267 };
268
269 class WebViewAsyncRequestHitTestDataUserCallback
270     : public WebViewAsyncRequestHitTestDataCallback {
271  public:
272   WebViewAsyncRequestHitTestDataUserCallback(
273       int x,
274       int y,
275       Ewk_Hit_Test_Mode mode,
276       Ewk_View_Hit_Test_Request_Callback callback,
277       void* user_data)
278       : WebViewAsyncRequestHitTestDataCallback(x, y, mode),
279         callback_(callback),
280         user_data_(user_data) {}
281
282   void Run(_Ewk_Hit_Test* hit_test, EWebView* web_view) override {
283     DCHECK(callback_);
284     callback_(web_view->ewk_view(), GetX(), GetY(), GetMode(), hit_test,
285               user_data_);
286   }
287
288  private:
289   Ewk_View_Hit_Test_Request_Callback callback_;
290   void* user_data_;
291 };
292
293 #if defined(TIZEN_ATK_SUPPORT)
294 class EWebAccessibilityObserver : public EWebAccessibility::Observer {
295  public:
296   explicit EWebAccessibilityObserver(EWebView* webview) : webview_(webview) {}
297   virtual ~EWebAccessibilityObserver() {}
298
299   // EWebAccessibility::Observer implementation
300   void OnSpatialNavigationStatusChanged(Eina_Bool enable) override {
301     webview_->UpdateSpatialNavigationStatus(enable);
302   }
303
304   void OnAccessibilityStatusChanged(Eina_Bool enable) override {
305     webview_->UpdateAccessibilityStatus(enable);
306   }
307
308  private:
309   EWebView* webview_;
310 };
311 #endif
312
313 int EWebView::find_request_id_counter_ = 0;
314 content::WebViewDelegate::WebContentsCreateCallback
315     EWebView::create_new_window_web_contents_cb_ =
316         base::BindRepeating(&NullCreateWebContents);
317
318 EWebView* EWebView::FromEwkView(Evas_Object* ewk_view) {
319   return WebViewDelegateEwk::GetInstance().GetEWebViewFromEwkView(ewk_view);
320 }
321
322 void EWebView::VisibleContentChangedCallback(void* user_data,
323                                              Evas_Object* /*object*/,
324                                              void* event_info) {
325   auto view = static_cast<EWebView*>(user_data);
326   auto rect = static_cast<Eina_Rectangle*>(event_info);
327   view->GetSelectionController()->SetCustomVisibleViewRect(
328       gfx::Rect(rect->x, rect->y, rect->w, rect->h));
329 }
330
331 void EWebView::OnCustomScrollBeginCallback(void* user_data,
332                                            Evas_Object* /*object*/,
333                                            void* /*event_info*/) {
334   auto* view = static_cast<EWebView*>(user_data);
335   if (auto* selection_controller = view->GetSelectionController())
336     selection_controller->SetControlsTemporarilyHidden(true,true);
337 }
338
339 void EWebView::OnCustomScrollEndCallback(void* user_data,
340                                          Evas_Object* /*object*/,
341                                          void* /*event_info*/) {
342   auto* view = static_cast<EWebView*>(user_data);
343   if (auto* selection_controller = view->GetSelectionController())
344     selection_controller->SetControlsTemporarilyHidden(false,true);
345 }
346
347 EWebView::EWebView(Ewk_Context* context, Evas_Object* ewk_view)
348     : context_(context),
349       ewk_view_(ewk_view),
350       efl_main_layout_(ewk_view),
351       mouse_events_enabled_(false),
352       text_zoom_factor_(1.0),
353       current_find_request_id_(find_request_id_counter_++),
354       progress_(0.0),
355       hit_test_completion_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
356                            base::WaitableEvent::InitialState::NOT_SIGNALED),
357       page_scale_factor_(1.0),
358       x_delta_(0.0),
359       y_delta_(0.0),
360 #if BUILDFLAG(IS_TIZEN_TV)
361       is_processing_edge_scroll_(false),
362       use_early_rwi_(false),
363       rwi_info_showed_(false),
364 #endif
365 #if defined(TIZEN_PEPPER_EXTENSIONS)
366       render_frame_id_{0, 0},
367 #endif
368       is_initialized_(false) {
369   LOG(INFO) << "EWebView: " << this;
370   if (ewk_view_) {
371     evas_object_smart_callback_add(ewk_view_, kVisibleContentChangedSignalName,
372                                    VisibleContentChangedCallback, this);
373
374     evas_object_smart_callback_add(ewk_view_, kCustomScrollBeginSignalName,
375                                    OnCustomScrollBeginCallback, this);
376     evas_object_smart_callback_add(ewk_view_, kCustomScrollEndSignalName,
377                                    OnCustomScrollEndCallback, this);
378 #if BUILDFLAG(IS_TIZEN)
379     window_rotate_handler_ = ecore_event_handler_add(
380       ECORE_WL2_EVENT_WINDOW_ROTATE, RotateWindowCb, this);
381 #endif
382   }
383 }
384
385 void EWebView::Initialize() {
386   if (is_initialized_) {
387     return;
388   }
389
390   InitializeContent();
391
392   scroll_detector_.reset(new ScrollDetector(this));
393
394 #if defined(TIZEN_PEPPER_EXTENSIONS)
395   InitializePepperExtensionSystem();
396 #endif
397   DCHECK(web_contents_->GetRenderViewHost());
398   // Settings (content::WebPreferences) will be initalized by
399   // RenderViewHostImpl::ComputeWebkitPrefs() based on command line switches.
400   settings_.reset(
401       new Ewk_Settings(ewk_view_, web_contents_->GetOrCreateWebPreferences()));
402 #if defined(TIZEN_ATK_SUPPORT)
403   std::unique_ptr<EWebAccessibilityObserver> observer(
404       new EWebAccessibilityObserver(this));
405   eweb_accessibility_.reset(new EWebAccessibility(
406       ewk_view_, web_contents_.get(), std::move(observer)));
407   lazy_initialize_atk_ = true;
408 #endif
409
410   base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
411   if (cmdline->HasSwitch(switches::kTouchEventFeatureDetection)) {
412     SetTouchEventsEnabled(
413         cmdline->GetSwitchValueASCII(switches::kTouchEventFeatureDetection) ==
414         switches::kTouchEventFeatureDetectionEnabled);
415   } else {
416     SetMouseEventsEnabled(true);
417   }
418
419   std::string user_agent =
420       EflWebView::VersionInfo::GetInstance()->DefaultUserAgent();
421   web_contents_->SetUserAgentOverride(
422       blink::UserAgentOverride::UserAgentOnly(user_agent),
423       false /* override_in_new_tabs */);
424
425   elm_object_tree_focus_allow_set(efl_main_layout_, EINA_TRUE);
426   is_initialized_ = true;
427   evas_object_event_callback_add(efl_main_layout_, EVAS_CALLBACK_RESIZE,
428                                  EWebView::NativeViewResize, this);
429
430   auto cbce = static_cast<ContentBrowserClientEfl*>(
431       content::GetContentClientExport()->browser());
432   // Initialize accept languages
433   SyncAcceptLanguages(cbce->GetAcceptLangs(nullptr));
434   accept_langs_changed_callback_ = base::BindRepeating(
435       &EWebView::SyncAcceptLanguages, base::Unretained(this));
436   cbce->AddAcceptLangsChangedCallback(accept_langs_changed_callback_);
437
438   // If EWebView is created by window.open, RenderView is already created
439   // before initializing WebContents. So we should manually invoke
440   // EWebView::RenderViewReady here.
441   if (web_contents_->GetPrimaryMainFrame() &&
442       web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive()) {
443     RenderViewReady();
444   }
445 }
446
447 EWebView::~EWebView() {
448   LOG(INFO) << "EWebView: " << this;
449   weak_factory_.InvalidateWeakPtrs();
450   auto cbce = static_cast<ContentBrowserClientEfl*>(
451       content::GetContentClientExport()->browser());
452   cbce->RemoveAcceptLangsChangedCallback(accept_langs_changed_callback_);
453 #if defined(TIZEN_PEPPER_EXTENSIONS)
454   UnregisterPepperExtensionDelegate();
455 #endif
456
457   evas_object_event_callback_del(efl_main_layout_, EVAS_CALLBACK_RESIZE,
458                                  EWebView::NativeViewResize);
459 #if defined(USE_WAYLAND)
460   if (GetSettings()->getClipboardEnabled())
461     ClipboardHelperEfl::GetInstance()->MaybeInvalidateActiveWebview(this);
462 #endif
463
464   std::map<int64_t, WebViewAsyncRequestHitTestDataCallback*>::iterator
465       hit_test_callback_iterator;
466   for (hit_test_callback_iterator = hit_test_callback_.begin();
467        hit_test_callback_iterator != hit_test_callback_.end();
468        hit_test_callback_iterator++)
469     delete hit_test_callback_iterator->second;
470   hit_test_callback_.clear();
471
472   for (auto iter = delayed_messages_.begin(); iter != delayed_messages_.end();
473        ++iter)
474     delete *iter;
475
476   delayed_messages_.clear();
477
478   if (!is_initialized_) {
479     return;
480   }
481
482 #if defined(TIZEN_ATK_SUPPORT)
483   eweb_accessibility_.reset();
484 #endif
485
486 #if defined(TIZEN_AUTOFILL_FW)
487   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
488           autofill::switches::kDisableAutofill)) {
489     autofill::AutofillRequestManager::GetInstance()->RemoveRequest(ewk_view());
490   }
491 #endif
492
493   select_picker_.reset();
494   context_menu_.reset();
495   mhtml_callback_map_.Clear();
496
497   compositor_observer_.reset();
498
499   // Release manually those scoped pointers to
500   // make sure they are released in correct order
501   web_contents_.reset();
502   web_contents_delegate_.reset();
503
504   // This code must be executed after WebContents deletion
505   // because WebContents depends on BrowserContext which
506   // is deleted along with EwkContext.
507   CHECK(!web_contents_);
508
509   permission_popup_manager_.reset();
510
511   gin_native_bridge_dispatcher_host_.reset();
512
513   if (ewk_view_) {
514     evas_object_smart_callback_del(ewk_view_, kVisibleContentChangedSignalName,
515                                    VisibleContentChangedCallback);
516     evas_object_smart_callback_del(ewk_view_, kCustomScrollBeginSignalName,
517                                    OnCustomScrollBeginCallback);
518     evas_object_smart_callback_del(ewk_view_, kCustomScrollEndSignalName,
519                                    OnCustomScrollEndCallback);
520 #if BUILDFLAG(IS_TIZEN)
521     if (window_rotate_handler_)
522       ecore_event_handler_del(window_rotate_handler_);
523 #endif
524   }
525 }
526
527 content::RenderWidgetHostViewAura* EWebView::rwhva() const {
528   return static_cast<content::RenderWidgetHostViewAura*>(
529       web_contents_->GetRenderWidgetHostView());
530 }
531
532 content::WebContentsViewAura* EWebView::wcva() const {
533   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
534   return static_cast<WebContentsViewAura*>(wc->GetView());
535 }
536
537 void EWebView::NativeViewResize(void* data,
538                                 Evas* e,
539                                 Evas_Object* obj,
540                                 void* event_info) {
541   auto thiz = static_cast<EWebView*>(data);
542   if (!thiz->context_menu_)
543     return;
544   int x, y, width, height;
545   evas_object_geometry_get(obj, &x, &y, &width, &height);
546   thiz->context_menu_->Resize(gfx::Rect(x, y, width, height));
547 }
548
549 void EWebView::ResetContextMenuController() {
550   return context_menu_.reset();
551 }
552
553 #if BUILDFLAG(IS_TIZEN_TV)
554 void EWebView::RunPendingSetFocus(Eina_Bool focus) {
555   SetFocusInternal(focus);
556 }
557
558 void EWebView::SetFocusInternal(Eina_Bool focus) {
559   if (!rwhva() || !rwhva()->offscreen_helper() || (HasFocus() == focus))
560     return;
561   rwhva()->offscreen_helper()->Focus(focus);
562 }
563 #endif
564
565 void EWebView::SetFocus(Eina_Bool focus) {
566   if (!web_contents_)
567     return;
568
569 #if BUILDFLAG(IS_TIZEN_TV)
570   if (web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive()) {
571     SetFocusInternal(focus);
572
573     if (pending_setfocus_closure_)
574       pending_setfocus_closure_.Reset();
575   } else {
576     LOG(ERROR) << "SEND DELAY SET FOCUS BIND";
577     pending_setfocus_closure_ = base::BindOnce(&EWebView::RunPendingSetFocus,
578                                                base::Unretained(this), focus);
579   }
580 #else
581   rwhva()->offscreen_helper()->Focus(focus);
582 #endif
583 }
584
585 Eina_Bool EWebView::HasFocus() const {
586   if (!rwhva() || !rwhva()->offscreen_helper())
587     return EINA_FALSE;
588
589   return rwhva()->offscreen_helper()->HasFocus() ? EINA_TRUE : EINA_FALSE;
590 }
591
592 Eina_Bool EWebView::AddJavaScriptMessageHandler(
593     Evas_Object* view,
594     Ewk_View_Script_Message_Cb callback,
595     std::string name) {
596   if (!gin_native_bridge_dispatcher_host_)
597     return EINA_FALSE;
598
599   return gin_native_bridge_dispatcher_host_->AddNamedObject(view, callback,
600                                                             name);
601 }
602
603 bool EWebView::SetPageVisibility(
604     Ewk_Page_Visibility_State page_visibility_state) {
605   if (!rwhva())
606     return false;
607
608   // TODO: We should able to set 'prerender' or 'unloaded' as visibility state.
609   // http://www.w3.org/TR/page-visibility/#dom-document-visibilitystate
610   switch (page_visibility_state) {
611     case EWK_PAGE_VISIBILITY_STATE_VISIBLE:
612       rwhva()->offscreen_helper()->SetPageVisibility(true);
613       break;
614     case EWK_PAGE_VISIBILITY_STATE_HIDDEN:
615       rwhva()->offscreen_helper()->SetPageVisibility(false);
616       break;
617     case EWK_PAGE_VISIBILITY_STATE_PRERENDER:
618       NOTIMPLEMENTED();
619       break;
620     default:
621       return false;
622   }
623
624   return true;
625 }
626
627 bool EWebView::CreateNewWindow(
628     content::WebViewDelegate::WebContentsCreateCallback cb) {
629   create_new_window_web_contents_cb_ = cb;
630   Evas_Object* new_object = NULL;
631   SmartCallback<EWebViewCallbacks::CreateNewWindow>().call(&new_object);
632   create_new_window_web_contents_cb_ =
633       base::BindRepeating(&NullCreateWebContents);
634   return !!new_object;
635 }
636
637 // static
638 Evas_Object* EWebView::GetHostWindowDelegate(const content::WebContents* wc) {
639   EWebView* thiz = WebViewFromWebContents(wc);
640   DCHECK(thiz->ewk_view_);
641   Evas_Object* parent = evas_object_above_get(thiz->ewk_view_);
642   if (!parent) {
643     LOG(WARNING) << "Could not find and visual parents for EWK smart object!.";
644     return thiz->ewk_view_;
645   }
646
647   if (elm_object_widget_check(parent)) {
648     Evas_Object* elm_parent = elm_object_top_widget_get(parent);
649     if (elm_parent)
650       return elm_parent;
651     return parent;
652   }
653
654   LOG(WARNING) << "Could not find elementary parent for WebView object!";
655   return thiz->ewk_view_;
656 }
657
658 Evas_Object* EWebView::GetElmWindow() const {
659   Evas_Object* parent = elm_object_parent_widget_get(ewk_view_);
660   return parent ? elm_object_top_widget_get(parent) : nullptr;
661 }
662
663 void EWebView::SetURL(const GURL& url, bool from_api) {
664   NavigationController::LoadURLParams params(url);
665
666   if (from_api) {
667     params.transition_type = ui::PageTransitionFromInt(
668         ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_API);
669   }
670
671 #if BUILDFLAG(IS_TIZEN_TV)
672   if (use_early_rwi_) {
673     LOG(INFO) << "[FAST RWI] SetURL Replace [" << url.spec()
674               << "] to [about:blank]";
675     rwi_gurl_ = url;
676     params.url = GURL("about:blank");
677   }
678 #endif
679
680   params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
681   web_contents_->GetController().LoadURLWithParams(params);
682 }
683
684 const GURL& EWebView::GetURL() const {
685   return web_contents_->GetVisibleURL();
686 }
687
688 const GURL& EWebView::GetOriginalURL() const {
689   const auto entry = web_contents_->GetController().GetVisibleEntry();
690   if (entry)
691     return entry->GetOriginalRequestURL();
692
693   return web_contents_->GetVisibleURL();
694 }
695
696 void EWebView::Reload() {
697   web_contents_->GetController().Reload(content::ReloadType::NORMAL, true);
698 }
699
700 void EWebView::ReloadBypassingCache() {
701   web_contents_->GetController().Reload(content::ReloadType::BYPASSING_CACHE,
702                                         true);
703 }
704
705 Eina_Bool EWebView::CanGoBack() {
706   return web_contents_->GetController().CanGoBack();
707 }
708
709 Eina_Bool EWebView::CanGoForward() {
710   return web_contents_->GetController().CanGoForward();
711 }
712
713 Eina_Bool EWebView::GoBack() {
714   if (!web_contents_->GetController().CanGoBack())
715     return EINA_FALSE;
716
717 #if defined(TIZEN_AUTOFILL_FW)
718   if (web_contents_delegate_)
719     web_contents_delegate_->ResetLastInteractedElements();
720 #endif
721
722   web_contents_->GetController().GoBack();
723   return EINA_TRUE;
724 }
725
726 Eina_Bool EWebView::GoForward() {
727   if (!web_contents_->GetController().CanGoForward())
728     return EINA_FALSE;
729
730   web_contents_->GetController().GoForward();
731   return EINA_TRUE;
732 }
733
734 void EWebView::Stop() {
735   if (web_contents_->IsLoading())
736     web_contents_->Stop();
737 }
738
739 void EWebView::Suspend() {
740 #if BUILDFLAG(IS_TIZEN)
741   CHECK(web_contents_);
742   if (IsMobileProfile() && web_contents_->IsFullscreen())
743     web_contents_->ExitFullscreen(true);
744   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
745   RenderFrameHost* rfh = web_contents_->GetPrimaryMainFrame();
746   CHECK(rvh);
747   CHECK(rfh);
748   if (rvh->IsRenderViewLive()) {
749     RenderWidgetHostImpl* rwhi = static_cast<RenderWidgetHostImpl*>(rvh->GetWidget());
750     rwhi->PauseScheduledTasks();
751   }
752 #endif
753 }
754
755 void EWebView::Resume() {
756 #if BUILDFLAG(IS_TIZEN)
757   CHECK(web_contents_);
758   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
759   RenderFrameHost* rfh = web_contents_->GetPrimaryMainFrame();
760   CHECK(rvh);
761   CHECK(rfh);
762   if (rvh->IsRenderViewLive() && rwhva())
763     rwhva()->host()->UnPauseScheduledTasks();
764 #endif
765 }
766
767 #if BUILDFLAG(IS_TIZEN_TV)
768 void EWebView::SetFloatVideoWindowState(bool enabled) {
769   RenderWidgetHostImpl* rwhi = static_cast<RenderWidgetHostImpl*>(
770       web_contents_->GetRenderViewHost()->GetWidget());
771
772     rwhi->SetFloatVideoWindowState(enabled);
773 }
774 #endif // IS_TIZEN_TV
775
776 double EWebView::GetTextZoomFactor() const {
777   if (text_zoom_factor_ < 0.0)
778     return -1.0;
779
780   return text_zoom_factor_;
781 }
782
783 void EWebView::SetTextZoomFactor(double text_zoom_factor) {
784   if (text_zoom_factor_ == text_zoom_factor || text_zoom_factor < 0.0)
785     return;
786
787   text_zoom_factor_ = text_zoom_factor;
788   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
789   if (!render_view_host)
790     return;
791 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
792   render_view_host->Send(new ViewMsg_SetTextZoomFactor(
793       render_view_host->GetRoutingID(), text_zoom_factor));
794 #endif
795 }
796
797 double EWebView::GetPageZoomFactor() const {
798   return blink::PageZoomLevelToZoomFactor(
799       content::HostZoomMap::GetZoomLevel(web_contents_.get()));
800 }
801
802 void EWebView::SetPageZoomFactor(double page_zoom_factor) {
803   content::HostZoomMap::SetZoomLevel(
804       web_contents_.get(), blink::PageZoomFactorToZoomLevel(page_zoom_factor));
805 }
806
807 void EWebView::ExecuteEditCommand(const char* command, const char* value) {
808   EINA_SAFETY_ON_NULL_RETURN(command);
809
810   absl::optional<std::u16string> optional_value;
811   if (value)
812     optional_value = absl::make_optional(base::ASCIIToUTF16(value));
813
814   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
815   if (!wc || !wc->GetFocusedFrameWidgetInputHandler())
816     return;
817
818   wc->GetFocusedFrameWidgetInputHandler()->ExecuteEditCommand(
819       std::string(command), optional_value);
820 }
821
822 #if BUILDFLAG(IS_TIZEN)
823 void EWebView::EnterDragState() {
824   if (IsMobileProfile()) {
825     if (RenderViewHost* render_view_host = web_contents_->GetRenderViewHost())
826       web_contents_->EnterDragState(render_view_host);
827   }
828 }
829 #endif
830
831 void EWebView::SetOrientation(int orientation) {
832   if (GetOrientation() == orientation)
833     return;
834
835   if (orientation == 0 || orientation == 90 || orientation == 180 ||
836       orientation == 270) {
837 #if !defined(USE_AURA)
838     GetWebContentsViewEfl()->SetOrientation(orientation);
839 #endif
840     int width = 0;
841     int height = 0;
842     const Ecore_Evas* ee =
843         ecore_evas_ecore_evas_get(evas_object_evas_get(ewk_view_));
844     ecore_evas_screen_geometry_get(ee, nullptr, nullptr, &width, &height);
845     if (orientation == 90 || orientation == 270)
846       std::swap(width, height);
847
848     if (popup_controller_)
849       popup_controller_->SetPopupSize(width, height);
850     if (JavaScriptDialogManagerEfl* dialogMG = GetJavaScriptDialogManagerEfl())
851       dialogMG->SetPopupSize(width, height);
852   }
853 }
854
855 int EWebView::GetOrientation() {
856 #if !defined(USE_AURA)
857   return GetWebContentsViewEfl()->GetOrientation();
858 #else
859   return 0;
860 #endif
861 }
862
863 void EWebView::Show() {
864   evas_object_show(efl_main_layout_);
865   web_contents_->WasShown();
866 }
867
868 void EWebView::Hide() {
869   LOG(INFO) << "EWebView: " << this;
870   evas_object_hide(efl_main_layout_);
871   if (!web_contents_)
872     return;
873   web_contents_->WasHidden();
874 }
875
876 void EWebView::SetViewAuthCallback(Ewk_View_Authentication_Callback callback,
877                                    void* user_data) {
878   authentication_cb_.Set(callback, user_data);
879 }
880
881 void EWebView::InvokeAuthCallback(LoginDelegateEfl* login_delegate,
882                                   const GURL& url,
883                                   const std::string& realm) {
884   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
885
886   auth_challenge_.reset(new _Ewk_Auth_Challenge(login_delegate, url, realm));
887   authentication_cb_.Run(ewk_view_, auth_challenge_.get());
888
889   if (!auth_challenge_->is_decided && !auth_challenge_->is_suspended) {
890     auth_challenge_->is_decided = true;
891     auth_challenge_->login_delegate->Cancel();
892   }
893 }
894
895 void EWebView::InvokePolicyResponseCallback(
896     _Ewk_Policy_Decision* policy_decision,
897     bool* defer) {
898   SmartCallback<EWebViewCallbacks::PolicyResponseDecide>().call(
899       policy_decision);
900
901   if (policy_decision->isSuspended()) {
902     *defer = true;
903     return;
904   }
905
906   if (!policy_decision->isDecided())
907     policy_decision->Use();
908
909   policy_decision->SelfDeleteIfNecessary();
910 }
911
912 void EWebView::InvokePolicyNavigationCallback(
913     const NavigationPolicyParams& params,
914     bool* handled) {
915   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
916
917   SmartCallback<EWebViewCallbacks::SaveSessionData>().call();
918
919   std::unique_ptr<_Ewk_Policy_Decision> policy_decision(
920       new _Ewk_Policy_Decision(params));
921
922   SmartCallback<EWebViewCallbacks::NavigationPolicyDecision>().call(
923       policy_decision.get());
924
925   CHECK(!policy_decision->isSuspended());
926
927   // TODO: Navigation can't be suspended
928   // this aproach is synchronous and requires immediate response
929   // Maybe there is different approach (like resource throttle response
930   // mechanism) that allows us to
931   // suspend navigation
932   if (!policy_decision->isDecided())
933     policy_decision->Use();
934
935   *handled = policy_decision->GetNavigationPolicyHandler()->GetDecision() ==
936              NavigationPolicyHandlerEfl::Handled;
937 }
938
939 void EWebView::HandleTouchEvents(Ewk_Touch_Event_Type type,
940                                  const Eina_List* points,
941                                  const Evas_Modifier* modifiers) {
942   const Eina_List* l;
943   void* data;
944
945   if (GetSettings()->touchFocusEnabled() &&
946       (type == EWK_TOUCH_START && eina_list_count(points) == 1)) {
947     SetFocus(EINA_TRUE);
948   }
949
950   EINA_LIST_FOREACH(points, l, data) {
951     const Ewk_Touch_Point* point = static_cast<Ewk_Touch_Point*>(data);
952     if (point->state == EVAS_TOUCH_POINT_STILL) {
953       // Chromium doesn't expect (and doesn't like) these events.
954       continue;
955     }
956     if (rwhva()) {
957       Evas_Coord_Point pt;
958       pt.x = point->x;
959       pt.y = point->y;
960
961       int delta_y = 0;
962       evas_object_geometry_get(ewk_view(), nullptr, &delta_y, nullptr, nullptr);
963       ui::TouchEvent touch_event =
964           ui::MakeTouchEvent(pt, point->state, point->id, 0, delta_y);
965       rwhva()->OnTouchEvent(&touch_event);
966     }
967   }
968 }
969
970 bool EWebView::TouchEventsEnabled() const {
971   return rwhva()->offscreen_helper()->TouchEventsEnabled();
972 }
973
974 // TODO: Touch events use the same mouse events in EFL API.
975 // Figure out how to distinguish touch and mouse events on touch&mice devices.
976 // Currently mouse and touch support is mutually exclusive.
977 void EWebView::SetTouchEventsEnabled(bool enabled) {
978   if (!rwhva() || !rwhva()->offscreen_helper()) {
979     LOG(WARNING) << "RWHV is not created yet!";
980     return;
981   }
982
983   if (rwhva()->offscreen_helper()->TouchEventsEnabled() == enabled)
984     return;
985
986   rwhva()->offscreen_helper()->SetTouchEventsEnabled(enabled);
987
988   GetSettings()->getPreferences().touch_event_feature_detection_enabled =
989       enabled;
990   GetSettings()->getPreferences().double_tap_to_zoom_enabled = enabled;
991   GetSettings()->getPreferences().editing_behavior =
992       enabled ? blink::mojom::EditingBehavior::kEditingAndroidBehavior
993               : blink::mojom::EditingBehavior::kEditingUnixBehavior,
994   UpdateWebKitPreferences();
995 }
996
997 bool EWebView::MouseEventsEnabled() const {
998   return mouse_events_enabled_;
999 }
1000
1001 void EWebView::SetMouseEventsEnabled(bool enabled) {
1002   if (!rwhva() || !rwhva()->offscreen_helper()) {
1003     LOG(WARNING) << "RWHV is not created yet!";
1004     return;
1005   }
1006
1007   if (mouse_events_enabled_ == enabled)
1008     return;
1009
1010   mouse_events_enabled_ = enabled;
1011   rwhva()->offscreen_helper()->SetTouchEventsEnabled(!enabled);
1012 }
1013
1014 bool EWebView::SetKeyEventsEnabled(bool enabled) {
1015   if (!rwhva() || !rwhva()->aura_efl_helper()) {
1016     LOG(WARNING) << "RWHV is not created yet!";
1017     return false;
1018   }
1019
1020   if (key_events_enabled_ == enabled)
1021     return true;
1022
1023   key_events_enabled_ = enabled;
1024   rwhva()->aura_efl_helper()->SetKeyEventsEnabled(enabled);
1025   return true;
1026 }
1027
1028 void EWebView::SendKeyEvent(Evas_Object* ewk_view,
1029                             void* key_event,
1030                             bool is_press) {
1031   if (!rwhva() || !rwhva()->aura_efl_helper()) {
1032     LOG(WARNING) << "RWHV is not created yet!";
1033     return;
1034   }
1035
1036   rwhva()->aura_efl_helper()->SendKeyEvent(ewk_view, key_event, is_press);
1037 }
1038
1039 namespace {
1040
1041 class JavaScriptCallbackDetails {
1042  public:
1043   JavaScriptCallbackDetails(Ewk_View_Script_Execute_Callback callback_func,
1044                             void* user_data,
1045                             Evas_Object* view)
1046       : callback_func_(callback_func), user_data_(user_data), view_(view) {}
1047
1048   Ewk_View_Script_Execute_Callback callback_func_;
1049   void* user_data_;
1050   Evas_Object* view_;
1051 };
1052
1053 void JavaScriptComplete(JavaScriptCallbackDetails* script_callback_data,
1054                         base::Value result) {
1055   if (!script_callback_data->callback_func_)
1056     return;
1057
1058   std::string return_string;
1059   if (result.is_string()) {
1060     // We don't want to serialize strings with JSONStringValueSerializer
1061     // to avoid quotation marks.
1062     return_string = result.GetString();
1063   } else if (result.is_none()) {
1064     // Value::TYPE_NULL is for lack of value, undefined, null
1065     return_string = "";
1066   } else {
1067     JSONStringValueSerializer serializer(&return_string);
1068     serializer.Serialize(result);
1069   }
1070
1071   script_callback_data->callback_func_(script_callback_data->view_,
1072                                        return_string.c_str(),
1073                                        script_callback_data->user_data_);
1074 }
1075
1076 }  // namespace
1077
1078 bool EWebView::ExecuteJavaScript(const char* script,
1079                                  Ewk_View_Script_Execute_Callback callback,
1080                                  void* userdata) {
1081   LOG(INFO) << __FUNCTION__;
1082   if (!web_contents_) {
1083     LOG(ERROR) << __FUNCTION__ << "web_contents_ is null";
1084     return false;
1085   }
1086
1087   RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
1088   if (!render_frame_host) {
1089     LOG(ERROR) << __FUNCTION__ << " render_frame_host is null";
1090     return false;
1091   }
1092
1093   // Note: M37. Execute JavaScript, |script| with
1094   // |RenderFrameHost::ExecuteJavaScript|.
1095   // @see also https://codereview.chromium.org/188893005 for more details.
1096   std::u16string js_script;
1097   base::UTF8ToUTF16(script, strlen(script), &js_script);
1098   if (callback) {
1099     JavaScriptCallbackDetails* script_callback_data =
1100         new JavaScriptCallbackDetails(callback, userdata, ewk_view_);
1101     RenderFrameHost::JavaScriptResultCallback js_callback =
1102         base::BindOnce(&JavaScriptComplete, base::Owned(script_callback_data));
1103     // In M47, it isn't possible anymore to execute javascript in the generic
1104     // case. We need to call ExecuteJavaScriptForTests to keep the behaviour
1105     // unchanged @see https://codereview.chromium.org/1123783002
1106     render_frame_host->ExecuteJavaScriptWithUserGestureForTests(
1107         js_script, std::move(js_callback));
1108   } else {
1109     // We use ExecuteJavaScriptWithUserGestureForTests instead of
1110     // ExecuteJavaScript because
1111     // ExecuteJavaScriptWithUserGestureForTests sets user_gesture to true. This
1112     // was the
1113     // behaviour is m34, and we want to keep it that way.
1114     render_frame_host->ExecuteJavaScriptWithUserGestureForTests(
1115         js_script, base::NullCallback());
1116   }
1117
1118   return true;
1119 }
1120
1121 bool EWebView::SetUserAgent(const char* userAgent) {
1122   content::NavigationController& controller = web_contents_->GetController();
1123   bool override = userAgent && strlen(userAgent);
1124   for (int i = 0; i < controller.GetEntryCount(); ++i)
1125     controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(override);
1126   // TODO: Check if override_in_new_tabs has to be true.
1127   web_contents_->SetUserAgentOverride(
1128       blink::UserAgentOverride::UserAgentOnly(userAgent),
1129       false /* override_in_new_tabs */);
1130   return true;
1131 }
1132
1133 bool EWebView::SetUserAgentAppName(const char* application_name) {
1134   EflWebView::VersionInfo::GetInstance()->UpdateUserAgentWithAppName(
1135       application_name ? application_name : "");
1136   std::string user_agent =
1137       EflWebView::VersionInfo::GetInstance()->DefaultUserAgent();
1138   web_contents_->SetUserAgentOverride(
1139       blink::UserAgentOverride::UserAgentOnly(user_agent),
1140       false /* override_in_new_tabs */);
1141   return true;
1142 }
1143
1144 #if BUILDFLAG(IS_TIZEN)
1145 bool EWebView::SetPrivateBrowsing(bool incognito) {
1146   if (context_->GetImpl()->browser_context()->IsOffTheRecord() == incognito)
1147     return false;
1148   context_->GetImpl()->browser_context()->SetOffTheRecord(incognito);
1149   return true;
1150 }
1151
1152 bool EWebView::GetPrivateBrowsing() const {
1153   return context_->GetImpl()->browser_context()->IsOffTheRecord();
1154 }
1155 #endif
1156
1157 const char* EWebView::GetUserAgent() const {
1158   std::string user_agent =
1159       web_contents_->GetUserAgentOverride().ua_string_override;
1160   if (user_agent.empty())
1161     user_agent_ = content::GetContentClientExport()->browser()->GetUserAgent();
1162   else
1163     user_agent_ = user_agent;
1164
1165   return user_agent_.c_str();
1166 }
1167
1168 const char* EWebView::GetUserAgentAppName() const {
1169   user_agent_app_name_ = EflWebView::VersionInfo::GetInstance()->AppName();
1170   return user_agent_app_name_.c_str();
1171 }
1172
1173 const char* EWebView::CacheSelectedText() {
1174   if (!rwhva())
1175     return "";
1176
1177   selected_text_cached_ = base::UTF16ToUTF8(rwhva()->GetSelectedText());
1178   return selected_text_cached_.c_str();
1179 }
1180
1181 _Ewk_Frame* EWebView::GetMainFrame() {
1182   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1183
1184   if (!frame_.get())
1185     frame_.reset(new _Ewk_Frame(web_contents_->GetPrimaryMainFrame()));
1186
1187   return frame_.get();
1188 }
1189
1190 void EWebView::UpdateWebKitPreferences() {
1191   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1192
1193   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1194   if (!render_view_host)
1195     return;
1196
1197   web_contents_delegate_->OnUpdateSettings(settings_.get());
1198 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1199   render_view_host->UpdateWebkitPreferences(settings_->getPreferences());
1200 #endif
1201   UpdateWebkitPreferencesEfl(render_view_host);
1202 }
1203
1204 void EWebView::UpdateWebkitPreferencesEfl(RenderViewHost* render_view_host) {
1205   DCHECK(render_view_host);
1206 #if !defined(EWK_BRINGUP)  // FIXME: m108 bringup
1207   IPC::Message* message = new EwkSettingsMsg_UpdateWebKitPreferencesEfl(
1208       render_view_host->GetRoutingID(), settings_->getPreferencesEfl());
1209
1210   if (render_view_host->IsRenderViewLive()) {
1211 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1212     render_view_host->Send(message);
1213 #endif
1214   } else {
1215     delayed_messages_.push_back(message);
1216   }
1217 #endif
1218 }
1219
1220 void EWebView::SetContentSecurityPolicy(const char* policy,
1221                                         Ewk_CSP_Header_Type type) {
1222   web_contents_delegate_->SetContentSecurityPolicy(
1223       (policy ? policy : std::string()), type);
1224 }
1225
1226 void EWebView::LoadHTMLString(const char* html,
1227                               const char* base_uri,
1228                               const char* unreachable_uri) {
1229   LoadData(html, std::string::npos, NULL, NULL, base_uri, unreachable_uri);
1230 }
1231
1232 void EWebView::LoadPlainTextString(const char* plain_text) {
1233   LoadData(plain_text, std::string::npos, "text/plain", NULL, NULL, NULL);
1234 }
1235
1236 void EWebView::LoadHTMLStringOverridingCurrentEntry(
1237     const char* html,
1238     const char* base_uri,
1239     const char* unreachable_url) {
1240   LoadData(html, std::string::npos, NULL, NULL, base_uri, unreachable_url,
1241            true);
1242 }
1243
1244 void EWebView::LoadData(const char* data,
1245                         size_t size,
1246                         const char* mime_type,
1247                         const char* encoding,
1248                         const char* base_uri,
1249                         const char* unreachable_uri,
1250                         bool should_replace_current_entry) {
1251   SetDefaultStringIfNull(mime_type, "text/html");
1252   SetDefaultStringIfNull(encoding, "utf-8");
1253   SetDefaultStringIfNull(base_uri, "about:blank");  // Webkit2 compatible
1254   SetDefaultStringIfNull(unreachable_uri, "");
1255
1256   std::string str_data = data;
1257
1258   if (size < str_data.length())
1259     str_data = str_data.substr(0, size);
1260
1261   std::string url_str("data:");
1262   url_str.append(mime_type);
1263   url_str.append(";charset=");
1264   url_str.append(encoding);
1265   url_str.append(",");
1266
1267   // GURL constructor performs canonicalization of url string, but this is not
1268   // enough for correctly escaping contents of "data:" url.
1269   url_str.append(base::EscapeUrlEncodedData(str_data, false));
1270
1271   NavigationController::LoadURLParams data_params(GURL(url_str.c_str()));
1272
1273   data_params.base_url_for_data_url = GURL(base_uri);
1274   data_params.virtual_url_for_data_url = GURL(unreachable_uri);
1275
1276   data_params.load_type = NavigationController::LOAD_TYPE_DATA;
1277   data_params.should_replace_current_entry = should_replace_current_entry;
1278   data_params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
1279   web_contents_->GetController().LoadURLWithParams(data_params);
1280 }
1281
1282 void EWebView::InvokeLoadError(const GURL& url,
1283                                int error_code,
1284                                bool is_cancellation) {
1285   _Ewk_Error err(error_code, is_cancellation,
1286                  url.possibly_invalid_spec().c_str());
1287
1288   SmartCallback<EWebViewCallbacks::LoadError>().call(&err);
1289 }
1290
1291 void EWebView::SetViewLoadErrorPageCallback(
1292     Ewk_View_Error_Page_Load_Callback callback,
1293     void* user_data) {
1294   load_error_page_cb_.Set(callback, user_data);
1295 }
1296
1297 // Remove below code while ewk_error_cancellation_get has been implemented.
1298 const char* EWebView::InvokeViewLoadErrorPageCallback(
1299     const GURL& url,
1300     int error_code,
1301     const std::string& error_description) {
1302   std::unique_ptr<_Ewk_Error> err(
1303       new _Ewk_Error(error_code, url.possibly_invalid_spec().c_str(),
1304                      error_description.c_str()));
1305   _Ewk_Error_Page error_page;
1306
1307   LOG(INFO) << "EWebView::InvokeLoadErrorPageCallback url: "
1308             << url.spec().c_str() << ", error_code: " << error_code;
1309
1310   load_error_page_cb_.Run(ewk_view_, err.get(), &error_page);
1311   return error_page.content;
1312 }
1313
1314 bool EWebView::IsLoadErrorPageCallbackSet() const {
1315   return load_error_page_cb_.IsCallbackSet();
1316 }
1317 void EWebView::HandlePopupMenu(std::vector<blink::mojom::MenuItemPtr> items,
1318                                int selectedIndex,
1319                                bool multiple,
1320                                const gfx::Rect& bounds) {
1321   if (!select_picker_) {
1322     select_picker_.reset(CreateSelectPicker(
1323         this, selectedIndex, std::move(items), multiple, bounds));
1324
1325     // Picker has been shown on top of webview and the page content gets
1326     // partially overlapped. Decrease viewport while showing picker.
1327     AdjustViewPortHeightToPopupMenu(true /* is_popup_menu_visible */);
1328 #if BUILDFLAG(IS_TIZEN_TV)
1329     SmartCallback<EWebViewCallbacks::PopupMenuShow>().call();
1330 #endif
1331   } else {
1332     select_picker_->UpdatePickerData(selectedIndex, std::move(items), multiple);
1333   }
1334
1335   select_picker_->Show();
1336 }
1337
1338 void EWebView::HidePopupMenu() {
1339   if (!select_picker_)
1340     return;
1341
1342   AdjustViewPortHeightToPopupMenu(false /* is_popup_menu_visible */);
1343 #if BUILDFLAG(IS_TIZEN_TV)
1344   SmartCallback<EWebViewCallbacks::PopupMenuHide>().call();
1345 #endif
1346   select_picker_.reset();
1347 }
1348
1349 void EWebView::DidSelectPopupMenuItems(std::vector<int>& indices) {
1350   wcva()->wcva_helper()->DidSelectPopupMenuItems(indices);
1351 }
1352
1353 void EWebView::DidCancelPopupMenu() {
1354   wcva()->wcva_helper()->DidCancelPopupMenu();
1355 }
1356
1357 void EWebView::HandleLongPressGesture(
1358     const content::ContextMenuParams& params) {
1359   // This menu is created in renderer process and it does not now anything about
1360   // view scaling factor and it has another calling sequence, so coordinates is
1361   // not updated.
1362   if (settings_ && !settings_->getPreferences().long_press_enabled)
1363     return;
1364
1365   content::ContextMenuParams convertedParams = params;
1366   gfx::Point convertedPoint =
1367       rwhva()->offscreen_helper()->ConvertPointInViewPix(
1368           gfx::Point(params.x, params.y));
1369   convertedParams.x = convertedPoint.x();
1370   convertedParams.y = convertedPoint.y();
1371
1372   Evas_Coord x, y;
1373   evas_object_geometry_get(ewk_view(), &x, &y, 0, 0);
1374   convertedParams.x += x;
1375   convertedParams.y += y;
1376
1377   if (GetSelectionController() && GetSelectionController()->GetLongPressed()) {
1378     bool show_context_menu_now =
1379         !GetSelectionController()->HandleLongPressEvent(convertedPoint,
1380                                                         convertedParams);
1381     if (show_context_menu_now)
1382       ShowContextMenuInternal(convertedParams);
1383   }
1384 }
1385
1386 void EWebView::ShowContextMenu(const content::ContextMenuParams& params) {
1387   if (!rwhva())
1388     return;
1389
1390   // This menu is created in renderer process and it does not now anything about
1391   // view scaling factor and it has another calling sequence, so coordinates is
1392   // not updated.
1393   content::ContextMenuParams convertedParams = params;
1394   gfx::Point convertedPoint =
1395       rwhva()->offscreen_helper()->ConvertPointInViewPix(
1396           gfx::Point(params.x, params.y));
1397   convertedParams.x = convertedPoint.x();
1398   convertedParams.y = convertedPoint.y();
1399
1400   Evas_Coord x, y;
1401   evas_object_geometry_get(ewk_view(), &x, &y, 0, 0);
1402   convertedParams.x += x;
1403   convertedParams.y += y;
1404
1405   context_menu_position_ = gfx::Point(convertedParams.x, convertedParams.y);
1406
1407   ShowContextMenuInternal(convertedParams);
1408 }
1409
1410 void EWebView::ShowContextMenuInternal(
1411     const content::ContextMenuParams& params) {
1412   // We don't want to show 'cut' or 'copy' for inputs of type 'password' in
1413   // selection context menu, but params.input_field_type might not be set
1414   // correctly, because in some cases params is received from SelectionBoxEfl,
1415   // not from FrameHostMsg_ContextMenu message. In SelectionBoxEfl
1416   // ContextMenuParams is constructed on our side with limited information and
1417   // input_field_type is not set.
1418   //
1419   // To work around this, we query for input type and set it separately. In
1420   // response to EwkViewMsg_QueryInputType we run ::UpdateContextMenu with
1421   // information about input's type.
1422   //
1423   // FIXME: the way we get ContextMenuParams for context menu is flawed in some
1424   //        cases. This should be fixed by restructuring context menu code.
1425   //        Context menu creation should be unified to always have
1426   //        ContextMenuParams received from FrameHostMsg_ContextMenu.
1427   //        Tracked at: http://suprem.sec.samsung.net/jira/browse/TWF-1640
1428   if (params.is_editable) {
1429     saved_context_menu_params_ = params;
1430     if (rwhva())
1431       rwhva()->host()->QueryInputType();
1432   } else {
1433     UpdateContextMenuWithParams(params);
1434   }
1435 }
1436
1437 void EWebView::UpdateContextMenu(bool is_password_input) {
1438   if (is_password_input) {
1439     saved_context_menu_params_.form_control_type =
1440         blink::mojom::FormControlType::kInputPassword;
1441   }
1442   UpdateContextMenuWithParams(saved_context_menu_params_);
1443 }
1444
1445 void EWebView::UpdateContextMenuWithParams(
1446     const content::ContextMenuParams& params) {
1447   context_menu_.reset(
1448       new content::ContextMenuControllerEfl(this, *web_contents_.get()));
1449
1450   if (IsMobileProfile()) {
1451     if (delayed_show_context_menu_timer_) {
1452       ecore_timer_del(delayed_show_context_menu_timer_);
1453       delayed_show_context_menu_timer_ = nullptr;
1454     }
1455     saved_context_menu_params_ = params;
1456     delayed_show_context_menu_timer_ = ecore_timer_add(
1457         kDelayShowContextMenuTime, DelayedPopulateAndShowContextMenu, this);
1458   } else {
1459     if (!context_menu_->PopulateAndShowContextMenu(params)) {
1460       context_menu_.reset();
1461       if (GetSelectionController())
1462         GetSelectionController()->HideHandles();
1463     }
1464   }
1465 }
1466
1467 Eina_Bool EWebView::DelayedPopulateAndShowContextMenu(void* data) {
1468   if (IsMobileProfile()) {
1469     EWebView* view = static_cast<EWebView*>(data);
1470     if (view) {
1471       if (view->context_menu_ &&
1472           !(view->context_menu_->PopulateAndShowContextMenu(
1473               view->saved_context_menu_params_))) {
1474         view->context_menu_.reset();
1475       }
1476       view->delayed_show_context_menu_timer_ = nullptr;
1477     }
1478   }
1479   return ECORE_CALLBACK_CANCEL;
1480 }
1481
1482 void EWebView::CancelContextMenu(int request_id) {
1483   if (context_menu_)
1484     context_menu_->HideContextMenu();
1485 }
1486
1487 void EWebView::Find(const char* text, Ewk_Find_Options ewk_find_options) {
1488   std::u16string find_text = base::UTF8ToUTF16(text);
1489   bool find_next = (previous_text_ == find_text);
1490
1491   if (!find_next) {
1492     current_find_request_id_ = find_request_id_counter_++;
1493     previous_text_ = find_text;
1494   }
1495
1496   auto find_options = blink::mojom::FindOptions::New();
1497   find_options->forward = !(ewk_find_options & EWK_FIND_OPTIONS_BACKWARDS);
1498   find_options->match_case =
1499       !(ewk_find_options & EWK_FIND_OPTIONS_CASE_INSENSITIVE);
1500
1501   web_contents_->Find(current_find_request_id_, find_text,
1502                       std::move(find_options));
1503 }
1504
1505 void EWebView::SetScale(double scale_factor) {
1506   // Do not cache |scale_factor| here as it may be discarded by Blink's
1507   // minimumPageScaleFactor and maximumPageScaleFactor.
1508   // |scale_factor| is cached as responde to DidChangePageScaleFactor.
1509   WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents_.get());
1510   wci->GetPrimaryMainFrame()->GetAssociatedLocalMainFrame()->SetScaleFactor(
1511       scale_factor);
1512 }
1513
1514 void EWebView::ScrollFocusedNodeIntoView() {
1515   if (RenderViewHost* render_view_host = web_contents_->GetRenderViewHost()) {
1516     if (auto& broadcast = static_cast<RenderViewHostImpl*>(render_view_host)
1517                               ->GetAssociatedPageBroadcast())
1518       broadcast->ScrollFocusedNodeIntoView();
1519   }
1520 }
1521
1522 void EWebView::AdjustViewPortHeightToPopupMenu(bool is_popup_menu_visible) {
1523   if (!rwhva() || !IsMobileProfile() ||
1524       settings_->getPreferences().TizenCompatibilityModeEnabled()) {
1525     return;
1526   }
1527
1528   int picker_height = select_picker_->GetGeometryDIP().height();
1529   gfx::Rect screen_rect =
1530       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
1531   gfx::Rect view_rect = rwhva()->offscreen_helper()->GetViewBounds();
1532   int bottom_height =
1533       screen_rect.height() - (view_rect.y() + view_rect.height());
1534
1535   rwhva()->offscreen_helper()->SetCustomViewportSize(
1536       is_popup_menu_visible
1537           ? gfx::Size(view_rect.width(),
1538                       view_rect.height() - picker_height + bottom_height)
1539           : gfx::Size());
1540 }
1541
1542 void EWebView::SetScaleChangedCallback(Ewk_View_Scale_Changed_Callback callback,
1543                                        void* user_data) {
1544   scale_changed_cb_.Set(callback, user_data);
1545 }
1546
1547 bool EWebView::GetScrollPosition(int* x, int* y) const {
1548   if (!rwhva()) {
1549     LOG(ERROR) << "rwhva() returns nullptr";
1550     return false;
1551   }
1552   if (scroll_detector_->IsScrollOffsetChanged()) {
1553     if (x)
1554       *x = previous_scroll_position_.x();
1555     if (y)
1556       *y = previous_scroll_position_.y();
1557   } else {
1558     const gfx::Vector2d scroll_position_dip =
1559         scroll_detector_->GetLastScrollPosition();
1560     const float device_scale_factor = display::Screen::GetScreen()
1561                                           ->GetPrimaryDisplay()
1562                                           .device_scale_factor();
1563     if (x) {
1564       *x = base::ClampRound((scroll_position_dip.x() - x_delta_) *
1565                             device_scale_factor);
1566     }
1567     if (y) {
1568       *y = base::ClampRound((scroll_position_dip.y() - y_delta_) *
1569                             device_scale_factor);
1570     }
1571   }
1572   return true;
1573 }
1574
1575 void EWebView::ChangeScroll(int& x, int& y) {
1576   if (!rwhva()) {
1577     LOG(ERROR) << "rwhva() returns nullptr";
1578     return;
1579   }
1580   int max_x = 0;
1581   int max_y = 0;
1582   GetScrollSize(&max_x, &max_y);
1583   previous_scroll_position_.set_x(std::min(std::max(x, 0), max_x));
1584   previous_scroll_position_.set_y(std::min(std::max(y, 0), max_y));
1585
1586   const float device_scale_factor = display::Screen::GetScreen()
1587                                         ->GetPrimaryDisplay()
1588                                         .device_scale_factor();
1589   int x_input = x;
1590   int y_input = y;
1591
1592   x = base::ClampCeil(x / device_scale_factor);
1593   y = base::ClampCeil(y / device_scale_factor);
1594
1595   x_delta_ = x - (x_input / device_scale_factor);
1596   y_delta_ = y - (y_input / device_scale_factor);
1597
1598   scroll_detector_->SetScrollOffsetChanged();
1599 }
1600
1601 void EWebView::SetScroll(int x, int y) {
1602   if (auto* render_view_host = web_contents_->GetRenderViewHost()) {
1603     if (auto& broadcast = static_cast<RenderViewHostImpl*>(render_view_host)
1604                               ->GetAssociatedPageBroadcast()) {
1605       ChangeScroll(x, y);
1606       broadcast->SetScrollOffset(x, y);
1607     }
1608   }
1609 }
1610
1611 void EWebView::UseSettingsFont() {
1612 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1613   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1614   if (render_view_host)
1615     render_view_host->Send(
1616         new EwkViewMsg_UseSettingsFont(render_view_host->GetRoutingID()));
1617 #endif
1618 }
1619
1620 void EWebView::DidChangeContentsSize(int width, int height) {
1621   contents_size_ = gfx::Size(width, height);
1622   SmartCallback<EWebViewCallbacks::ContentsSizeChanged>().call();
1623   SetScaledContentsSize();
1624 }
1625
1626 const Eina_Rectangle EWebView::GetContentsSize() const {
1627   Eina_Rectangle rect;
1628   EINA_RECTANGLE_SET(&rect, 0, 0, contents_size_.width(),
1629                      contents_size_.height());
1630   return rect;
1631 }
1632
1633 void EWebView::SetScaledContentsSize() {
1634   if (!rwhva())
1635     return;  // LCOV_EXCL_LINE
1636
1637   const float device_scale_factor =
1638       display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1639   gfx::SizeF scaled_contents_size = gfx::ConvertSizeToPixels(
1640       contents_size_, device_scale_factor * page_scale_factor_);
1641   rwhva()->offscreen_helper()->SetScaledContentSize(scaled_contents_size);
1642 }
1643
1644 void EWebView::GetScrollSize(int* width, int* height) {
1645   int w = 0, h = 0;
1646   if (width) {
1647     *width = (rwhva() &&
1648               (w = rwhva()->offscreen_helper()->GetScrollableSize().width()))
1649                  ? w
1650                  : 0;
1651   }
1652   if (height) {
1653     *height = (rwhva() &&
1654                (h = rwhva()->offscreen_helper()->GetScrollableSize().height()))
1655                   ? h
1656                   : 0;
1657   }
1658 }
1659
1660 void EWebView::MoveCaret(const gfx::Point& point) {
1661   if (rwhva())
1662     rwhva()->offscreen_helper()->MoveCaret(point);
1663 }
1664
1665 SelectionControllerEfl* EWebView::GetSelectionController() const {
1666   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1667   RenderWidgetHostViewAura* view = static_cast<RenderWidgetHostViewAura*>(
1668       render_view_host->GetWidget()->GetView());
1669   return view ? view->offscreen_helper()->GetSelectionController() : 0;
1670 }
1671
1672 void EWebView::SelectFocusedLink() {
1673   rwhva()->host()->SelectFocusedLink();
1674 }
1675
1676 bool EWebView::GetSelectionRange(Eina_Rectangle* left_rect,
1677                                  Eina_Rectangle* right_rect) {
1678   if (left_rect && right_rect) {
1679     gfx::Rect left, right;
1680     if (GetSelectionController()) {
1681       GetSelectionController()->GetSelectionBounds(&left, &right);
1682       GetEinaRectFromGfxRect(left, left_rect);
1683       GetEinaRectFromGfxRect(right, right_rect);
1684       return true;
1685     }
1686   }
1687   return false;
1688 }
1689
1690 void EWebView::OnSelectionRectReceived(const gfx::Rect& selection_rect) const {
1691   if (context_menu_)
1692     context_menu_->OnSelectionRectReceived(selection_rect);
1693 }
1694
1695 Eina_Bool EWebView::ClearSelection() {
1696   if (!rwhva())
1697     return EINA_FALSE;
1698
1699   ResetContextMenuController();
1700   rwhva()->SelectionChanged(std::u16string(), 0, gfx::Range());
1701
1702   if (GetSelectionController())
1703     return GetSelectionController()->ClearSelectionViaEWebView();
1704
1705   return EINA_FALSE;
1706 }
1707
1708 _Ewk_Hit_Test* EWebView::RequestHitTestDataAt(int x,
1709                                               int y,
1710                                               Ewk_Hit_Test_Mode mode) {
1711   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1712
1713   int view_x, view_y;
1714   EvasToBlinkCords(x, y, &view_x, &view_y);
1715
1716   return RequestHitTestDataAtBlinkCoords(view_x, view_y, mode);
1717 }
1718
1719 Eina_Bool EWebView::AsyncRequestHitTestDataAt(
1720     int x,
1721     int y,
1722     Ewk_Hit_Test_Mode mode,
1723     Ewk_View_Hit_Test_Request_Callback callback,
1724     void* user_data) {
1725   int view_x, view_y;
1726   EvasToBlinkCords(x, y, &view_x, &view_y);
1727   return AsyncRequestHitTestDataAtBlinkCords(
1728       view_x, view_y, mode,
1729       new WebViewAsyncRequestHitTestDataUserCallback(x, y, mode, callback,
1730                                                      user_data));
1731 }
1732
1733 Eina_Bool EWebView::AsyncRequestHitTestDataAtBlinkCords(
1734     int x,
1735     int y,
1736     Ewk_Hit_Test_Mode mode,
1737     Ewk_View_Hit_Test_Request_Callback callback,
1738     void* user_data) {
1739   return AsyncRequestHitTestDataAtBlinkCords(
1740       x, y, mode,
1741       new WebViewAsyncRequestHitTestDataUserCallback(x, y, mode, callback,
1742                                                      user_data));
1743 }
1744
1745 Eina_Bool EWebView::AsyncRequestHitTestDataAtBlinkCords(
1746     int x,
1747     int y,
1748     Ewk_Hit_Test_Mode mode,
1749     WebViewAsyncRequestHitTestDataCallback* cb) {
1750   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1751   DCHECK(cb);
1752
1753   static int64_t request_id = 1;
1754
1755   if (cb) {
1756     RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1757     DCHECK(render_view_host);
1758
1759     if (render_view_host) {
1760 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1761       render_view_host->Send(new EwkViewMsg_DoHitTestAsync(
1762           render_view_host->GetRoutingID(), x, y, mode, request_id));
1763 #endif
1764       hit_test_callback_[request_id] = cb;
1765       ++request_id;
1766       return EINA_TRUE;
1767     }
1768   }
1769
1770   // if failed we delete callback as it is not needed anymore
1771   delete cb;
1772   return EINA_FALSE;
1773 }
1774
1775 void EWebView::DispatchAsyncHitTestData(const Hit_Test_Params& params,
1776                                         int64_t request_id) {
1777   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1778
1779   std::map<int64_t, WebViewAsyncRequestHitTestDataCallback*>::iterator it =
1780       hit_test_callback_.find(request_id);
1781
1782   if (it == hit_test_callback_.end())
1783     return;
1784   std::unique_ptr<_Ewk_Hit_Test> hit_test(new _Ewk_Hit_Test(params));
1785
1786   it->second->Run(hit_test.get(), this);
1787   delete it->second;
1788   hit_test_callback_.erase(it);
1789 }
1790
1791 _Ewk_Hit_Test* EWebView::RequestHitTestDataAtBlinkCoords(
1792     int x,
1793     int y,
1794     Ewk_Hit_Test_Mode mode) {
1795   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1796
1797   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1798
1799   if (render_view_host) {
1800     // We wait on UI thread till hit test data is updated.
1801 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
1802     render_view_host->Send(
1803         new EwkViewMsg_DoHitTest(render_view_host->GetRoutingID(), x, y, mode));
1804 #endif
1805     hit_test_completion_.Wait();
1806     return new _Ewk_Hit_Test(hit_test_params_);
1807   }
1808
1809   return nullptr;
1810 }
1811
1812 void EWebView::EvasToBlinkCords(int x, int y, int* view_x, int* view_y) {
1813   DCHECK(display::Screen::GetScreen());
1814   if (!rwhva())
1815     return;
1816
1817   gfx::Rect view_bounds = rwhva()->offscreen_helper()->GetViewBoundsInPix();
1818
1819   if (view_x) {
1820     *view_x = x - view_bounds.x();
1821     *view_x /=
1822         display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1823   }
1824
1825   if (view_y) {
1826     *view_y = y - view_bounds.y();
1827     *view_y /=
1828         display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1829   }
1830 }
1831
1832 void EWebView::UpdateHitTestData(const Hit_Test_Params& params) {
1833   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1834   hit_test_params_ = params;
1835   hit_test_completion_.Signal();
1836 }
1837
1838 void EWebView::OnCopyFromBackingStore(bool success, const SkBitmap& bitmap) {}
1839
1840 void EWebView::OnFocusIn() {
1841   SmartCallback<EWebViewCallbacks::FocusIn>().call();
1842 #if defined(USE_WAYLAND)
1843   if (!rwhva() || !rwhva()->offscreen_helper())
1844     return;
1845   if (GetSettings()->getClipboardEnabled()) {
1846     ClipboardHelperEfl::GetInstance()->OnWebviewFocusIn(
1847         this, rwhva()->offscreen_helper()->content_image_elm_host(),
1848         rwhva()->offscreen_helper()->IsFocusedNodeContentEditable(),
1849         base::BindRepeating(&EWebView::ExecuteEditCommand,
1850                             base::Unretained(this)));
1851   }
1852 #endif
1853 }
1854
1855 void EWebView::OnFocusOut() {
1856 #if defined(TIZEN_ATK_SUPPORT)
1857   if (IsMobileProfile())
1858     eweb_accessibility_->OnFocusOut();
1859 #endif
1860   SmartCallback<EWebViewCallbacks::FocusOut>().call();
1861 #if defined(USE_WAYLAND)
1862   if (GetSettings()->getClipboardEnabled())
1863     ClipboardHelperEfl::GetInstance()->MaybeInvalidateActiveWebview(this);
1864 #endif
1865 }
1866
1867 void EWebView::RenderViewReady() {
1868   if (rwhva()) {
1869     rwhva()->offscreen_helper()->SetFocusInOutCallbacks(
1870         base::BindRepeating(&EWebView::OnFocusIn, base::Unretained(this)),
1871         base::BindRepeating(&EWebView::OnFocusOut, base::Unretained(this)));
1872   }
1873
1874 #if defined(TIZEN_VIDEO_HOLE)
1875   if (rwhva() && pending_video_hole_setting_) {
1876     EnableVideoHoleSupportInternal();
1877     pending_video_hole_setting_ = false;
1878   }
1879 #endif
1880
1881   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1882
1883   SendDelayedMessages(render_view_host);
1884   UpdateWebkitPreferencesEfl(render_view_host);
1885
1886   if (render_view_host) {
1887     WebContents* content = WebContents::FromRenderViewHost(render_view_host);
1888     if (content) {
1889       RenderProcessHost* host = render_view_host->GetProcess();
1890       if (host)
1891         host->AddFilter(new WebViewBrowserMessageFilter(content));
1892     }
1893   }
1894 }
1895
1896 void EWebView::SetQuotaPermissionRequestCallback(
1897     Ewk_Quota_Permission_Request_Callback callback,
1898     void* user_data) {
1899   quota_request_callback_.Set(callback, user_data);
1900 }
1901
1902 #if !defined(EWK_BRINGUP)  // FIXME: m114 bringup
1903 void EWebView::InvokeQuotaPermissionRequest(
1904     _Ewk_Quota_Permission_Request* request,
1905     content::QuotaPermissionContext::PermissionCallback cb) {
1906   quota_permission_request_map_[request] = std::move(cb);
1907   request->setView(ewk_view());
1908   if (quota_request_callback_.IsCallbackSet())
1909     quota_request_callback_.Run(ewk_view(), request);
1910   else
1911     QuotaRequestCancel(request);
1912 }
1913
1914 void EWebView::QuotaRequestReply(const _Ewk_Quota_Permission_Request* request,
1915                                  bool allow) {
1916   DCHECK(quota_permission_request_map_.find(request) !=
1917          quota_permission_request_map_.end());
1918
1919   QuotaPermissionContextEfl::DispatchCallback(
1920       std::move(quota_permission_request_map_[request]),
1921       (allow ? QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
1922              : QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW));
1923
1924   quota_permission_request_map_.erase(request);
1925   delete request;
1926 }
1927
1928 void EWebView::QuotaRequestCancel(
1929     const _Ewk_Quota_Permission_Request* request) {
1930   DCHECK(quota_permission_request_map_.find(request) !=
1931          quota_permission_request_map_.end());
1932
1933   QuotaPermissionContextEfl::DispatchCallback(
1934       std::move(quota_permission_request_map_[request]),
1935       QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
1936   quota_permission_request_map_.erase(request);
1937   delete request;
1938 }
1939 #endif
1940
1941 bool EWebView::GetLinkMagnifierEnabled() const {
1942 #if !defined(EWK_BRINGUP)  // FIXME: m71 bringup
1943   return web_contents_->GetMutableRendererPrefs()
1944              ->tap_multiple_targets_strategy ==
1945          TAP_MULTIPLE_TARGETS_STRATEGY_POPUP;
1946 #else
1947   return false;
1948 #endif
1949 }
1950
1951 void EWebView::SetLinkMagnifierEnabled(bool enabled) {
1952 #if !defined(EWK_BRINGUP)  // FIXME: m71 bringup
1953   web_contents_->GetMutableRendererPrefs()->tap_multiple_targets_strategy =
1954       enabled ? TAP_MULTIPLE_TARGETS_STRATEGY_POPUP
1955               : TAP_MULTIPLE_TARGETS_STRATEGY_NONE;
1956 #endif
1957   web_contents_->SyncRendererPrefs();
1958 }
1959
1960 bool EWebView::GetSnapshotAsync(
1961     Eina_Rectangle rect,
1962     Ewk_Web_App_Screenshot_Captured_Callback callback,
1963     void* user_data,
1964     float scale_factor) {
1965   if (!rwhva() || !rwhva()->offscreen_helper())
1966     return false;
1967
1968   rwhva()->offscreen_helper()->RequestSnapshotAsync(
1969       gfx::Rect(rect.x, rect.y, rect.w, rect.h), callback, user_data,
1970       scale_factor);
1971   return true;
1972 }
1973
1974 Evas_Object* EWebView::GetSnapshot(Eina_Rectangle rect, float scale_factor) {
1975   if (!rwhva() || !rwhva()->offscreen_helper())
1976     return nullptr;
1977
1978   return rwhva()->offscreen_helper()->GetSnapshot(
1979       gfx::Rect(rect.x, rect.y, rect.w, rect.h), scale_factor);
1980 }
1981
1982 void EWebView::BackForwardListClear() {
1983   content::NavigationController& controller = web_contents_->GetController();
1984
1985   int entry_count = controller.GetEntryCount();
1986   bool entry_removed = false;
1987
1988   for (int i = 0; i < entry_count; i++) {
1989     if (controller.RemoveEntryAtIndex(i)) {
1990       entry_removed = true;
1991       entry_count = controller.GetEntryCount();
1992       i--;
1993     }
1994   }
1995
1996   if (entry_removed) {
1997     back_forward_list_->ClearCache();
1998     InvokeBackForwardListChangedCallback();
1999   }
2000 }
2001
2002 _Ewk_Back_Forward_List* EWebView::GetBackForwardList() const {
2003   return back_forward_list_.get();
2004 }
2005
2006 void EWebView::InvokeBackForwardListChangedCallback() {
2007   SmartCallback<EWebViewCallbacks::BackForwardListChange>().call();
2008 }
2009
2010 _Ewk_History* EWebView::GetBackForwardHistory() const {
2011   return new _Ewk_History(web_contents_->GetController());
2012 }
2013
2014 bool EWebView::WebAppCapableGet(Ewk_Web_App_Capable_Get_Callback callback,
2015                                 void* userData) {
2016   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
2017   if (!renderViewHost) {
2018     return false;
2019   }
2020 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2021   WebApplicationCapableGetCallback* cb =
2022       new WebApplicationCapableGetCallback(callback, userData);
2023   int callbackId = web_app_capable_get_callback_map_.Add(cb);
2024   return renderViewHost->Send(new EwkViewMsg_WebAppCapableGet(
2025       renderViewHost->GetRoutingID(), callbackId));
2026 #else
2027   return false;
2028 #endif
2029 }
2030
2031 bool EWebView::WebAppIconUrlGet(Ewk_Web_App_Icon_URL_Get_Callback callback,
2032                                 void* userData) {
2033   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
2034   if (!renderViewHost) {
2035     return false;
2036   }
2037 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2038   WebApplicationIconUrlGetCallback* cb =
2039       new WebApplicationIconUrlGetCallback(callback, userData);
2040   int callbackId = web_app_icon_url_get_callback_map_.Add(cb);
2041   return renderViewHost->Send(new EwkViewMsg_WebAppIconUrlGet(
2042       renderViewHost->GetRoutingID(), callbackId));
2043 #else
2044   return false;
2045 #endif
2046 }
2047
2048 bool EWebView::WebAppIconUrlsGet(Ewk_Web_App_Icon_URLs_Get_Callback callback,
2049                                  void* userData) {
2050   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
2051   if (!renderViewHost) {
2052     return false;
2053   }
2054 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2055   WebApplicationIconUrlsGetCallback* cb =
2056       new WebApplicationIconUrlsGetCallback(callback, userData);
2057   int callbackId = web_app_icon_urls_get_callback_map_.Add(cb);
2058   return renderViewHost->Send(new EwkViewMsg_WebAppIconUrlsGet(
2059       renderViewHost->GetRoutingID(), callbackId));
2060 #else
2061   return false;
2062 #endif
2063 }
2064
2065 void EWebView::InvokeWebAppCapableGetCallback(bool capable, int callbackId) {
2066   WebApplicationCapableGetCallback* callback =
2067       web_app_capable_get_callback_map_.Lookup(callbackId);
2068   if (!callback)
2069     return;
2070   callback->Run(capable);
2071   web_app_capable_get_callback_map_.Remove(callbackId);
2072 }
2073
2074 void EWebView::InvokeWebAppIconUrlGetCallback(const std::string& iconUrl,
2075                                               int callbackId) {
2076   WebApplicationIconUrlGetCallback* callback =
2077       web_app_icon_url_get_callback_map_.Lookup(callbackId);
2078   if (!callback)
2079     return;
2080   callback->Run(iconUrl);
2081   web_app_icon_url_get_callback_map_.Remove(callbackId);
2082 }
2083
2084 void EWebView::InvokeWebAppIconUrlsGetCallback(const StringMap& iconUrls,
2085                                                int callbackId) {
2086   WebApplicationIconUrlsGetCallback* callback =
2087       web_app_icon_urls_get_callback_map_.Lookup(callbackId);
2088   if (!callback) {
2089     return;
2090   }
2091   callback->Run(iconUrls);
2092   web_app_icon_urls_get_callback_map_.Remove(callbackId);
2093 }
2094
2095 void EWebView::SetNotificationPermissionCallback(
2096     Ewk_View_Notification_Permission_Callback callback,
2097     void* user_data) {
2098   notification_permission_callback_.Set(callback, user_data);
2099 }
2100
2101 bool EWebView::IsNotificationPermissionCallbackSet() const {
2102   return notification_permission_callback_.IsCallbackSet();
2103 }
2104
2105 bool EWebView::InvokeNotificationPermissionCallback(
2106     Ewk_Notification_Permission_Request* request) {
2107   Eina_Bool ret = EINA_FALSE;
2108   notification_permission_callback_.Run(ewk_view_, request, &ret);
2109   return ret;
2110 }
2111
2112 int EWebView::SetEwkViewPlainTextGetCallback(
2113     Ewk_View_Plain_Text_Get_Callback callback,
2114     void* user_data) {
2115   EwkViewPlainTextGetCallback* view_plain_text_callback_ptr =
2116       new EwkViewPlainTextGetCallback;
2117   view_plain_text_callback_ptr->Set(callback, user_data);
2118   return plain_text_get_callback_map_.Add(view_plain_text_callback_ptr);
2119 }
2120
2121 bool EWebView::PlainTextGet(Ewk_View_Plain_Text_Get_Callback callback,
2122                             void* user_data) {
2123   auto* render_frame_host = web_contents_->GetPrimaryMainFrame();
2124   if (!render_frame_host)
2125     return false;
2126
2127   auto callback_id = SetEwkViewPlainTextGetCallback(callback, user_data);
2128   return render_frame_host->Send(new EwkFrameMsg_GetPlainText(
2129       render_frame_host->GetRoutingID(), callback_id));
2130 }
2131
2132 void EWebView::InvokePlainTextGetCallback(const std::string& content_text,
2133                                           int plain_text_get_callback_id) {
2134   EwkViewPlainTextGetCallback* view_plain_text_callback_invoke_ptr =
2135       plain_text_get_callback_map_.Lookup(plain_text_get_callback_id);
2136   view_plain_text_callback_invoke_ptr->Run(ewk_view(), content_text.c_str());
2137   plain_text_get_callback_map_.Remove(plain_text_get_callback_id);
2138 }
2139
2140 void EWebView::SetViewGeolocationPermissionCallback(
2141     Ewk_View_Geolocation_Permission_Callback callback,
2142     void* user_data) {
2143   geolocation_permission_cb_.Set(callback, user_data);
2144 }
2145
2146 bool EWebView::InvokeViewGeolocationPermissionCallback(
2147     _Ewk_Geolocation_Permission_Request* permission_context,
2148     Eina_Bool* callback_result) {
2149   return geolocation_permission_cb_.Run(ewk_view_, permission_context,
2150                                         callback_result);
2151 }
2152
2153 void EWebView::SetViewUserMediaPermissionCallback(
2154     Ewk_View_User_Media_Permission_Callback callback,
2155     void* user_data) {
2156   user_media_permission_cb_.Set(callback, user_data);
2157 }
2158
2159 bool EWebView::InvokeViewUserMediaPermissionCallback(
2160     _Ewk_User_Media_Permission_Request* permission_context,
2161     Eina_Bool* callback_result) {
2162   return user_media_permission_cb_.Run(ewk_view_, permission_context,
2163                                        callback_result);
2164 }
2165
2166 void EWebView::SetViewUserMediaPermissionQueryCallback(
2167     Ewk_View_User_Media_Permission_Query_Callback callback,
2168     void* user_data) {
2169   user_media_permission_query_cb_.Set(callback, user_data);
2170 }
2171
2172 Ewk_User_Media_Permission_Query_Result
2173 EWebView::InvokeViewUserMediaPermissionQueryCallback(
2174     _Ewk_User_Media_Permission_Query* permission_context) {
2175   return user_media_permission_query_cb_.Run(ewk_view_, permission_context);
2176 }
2177
2178 void EWebView::SetViewUnfocusAllowCallback(
2179     Ewk_View_Unfocus_Allow_Callback callback,
2180     void* user_data) {
2181   unfocus_allow_cb_.Set(callback, user_data);
2182 }
2183
2184 bool EWebView::InvokeViewUnfocusAllowCallback(Ewk_Unfocus_Direction direction,
2185                                               Eina_Bool* callback_result) {
2186   return unfocus_allow_cb_.Run(ewk_view_, direction, callback_result);
2187 }
2188
2189 void EWebView::StopFinding() {
2190   web_contents_->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION);
2191 }
2192
2193 void EWebView::SetProgressValue(double progress) {
2194   progress_ = progress;
2195 }
2196
2197 double EWebView::GetProgressValue() {
2198   return progress_;
2199 }
2200
2201 const char* EWebView::GetTitle() {
2202   title_ = base::UTF16ToUTF8(web_contents_->GetTitle());
2203   return title_.c_str();
2204 }
2205
2206 bool EWebView::SaveAsPdf(int width, int height, const std::string& filename) {
2207   if (!rwhva())
2208     return false;
2209   rwhva()->host()->PrintToPdf(width, height, base::FilePath(filename));
2210   return true;
2211 }
2212
2213 bool EWebView::GetMHTMLData(Ewk_View_MHTML_Data_Get_Callback callback,
2214                             void* user_data) {
2215   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2216   if (!render_view_host)
2217     return false;
2218
2219 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2220   MHTMLCallbackDetails* callback_details = new MHTMLCallbackDetails;
2221   callback_details->Set(callback, user_data);
2222   int mhtml_callback_id = mhtml_callback_map_.Add(callback_details);
2223   return render_view_host->Send(new EwkViewMsg_GetMHTMLData(
2224       render_view_host->GetRoutingID(), mhtml_callback_id));
2225 #else
2226   return false;
2227 #endif
2228 }
2229
2230 void EWebView::OnMHTMLContentGet(const std::string& mhtml_content,
2231                                  int callback_id) {
2232   MHTMLCallbackDetails* callback_details =
2233       mhtml_callback_map_.Lookup(callback_id);
2234   callback_details->Run(ewk_view(), mhtml_content.c_str());
2235   mhtml_callback_map_.Remove(callback_id);
2236 }
2237
2238 bool EWebView::SavePageAsMHTML(const std::string& path,
2239                                Ewk_View_Save_Page_Callback callback,
2240                                void* user_data) {
2241   if (!web_contents_)
2242     return false;
2243
2244   GURL url(web_contents_->GetLastCommittedURL());
2245   std::u16string title(web_contents_->GetTitle());
2246
2247   // Post function that has file access to blocking task runner.
2248   base::ThreadPool::PostTaskAndReplyWithResult(
2249       FROM_HERE,
2250       {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
2251        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
2252       base::BindOnce(&GenerateMHTMLFilePath, url, base::UTF16ToUTF8(title),
2253                      path),
2254       base::BindOnce(&EWebView::GenerateMHTML, base::Unretained(this), callback,
2255                      user_data));
2256   return true;
2257 }
2258
2259 void EWebView::GenerateMHTML(Ewk_View_Save_Page_Callback callback,
2260                              void* user_data,
2261                              const base::FilePath& file_path) {
2262   if (file_path.empty()) {
2263     LOG(ERROR) << "Generating file path was failed";
2264     callback(ewk_view_, nullptr, user_data);
2265     return;
2266   }
2267
2268   MHTMLGenerationParams params(file_path);
2269   web_contents_->GenerateMHTML(
2270       params, base::BindOnce(&EWebView::MHTMLGenerated, base::Unretained(this),
2271                              callback, user_data, file_path));
2272 }
2273
2274 void EWebView::MHTMLGenerated(Ewk_View_Save_Page_Callback callback,
2275                               void* user_data,
2276                               const base::FilePath& file_path,
2277                               int64_t file_size) {
2278   callback(ewk_view_, file_size > 0 ? file_path.value().c_str() : nullptr,
2279            user_data);
2280 }
2281
2282 bool EWebView::GetBackgroundColor(
2283     Ewk_View_Background_Color_Get_Callback callback,
2284     void* user_data) {
2285   if (!rwhva())
2286     return false;
2287   BackgroundColorGetCallback* cb =
2288       new BackgroundColorGetCallback(callback, user_data);
2289   int callback_id = background_color_get_callback_map_.Add(cb);
2290
2291   rwhva()->host()->RequestBackgroundColor(callback_id);
2292   return true;
2293 }
2294
2295 void EWebView::OnGetBackgroundColor(int callback_id, SkColor bg_color) {
2296   BackgroundColorGetCallback* cb =
2297       background_color_get_callback_map_.Lookup(callback_id);
2298
2299   if (!cb)
2300     return;
2301
2302   cb->Run(ewk_view(), SkColorGetR(bg_color), SkColorGetG(bg_color),
2303           SkColorGetB(bg_color), SkColorGetA(bg_color));
2304   background_color_get_callback_map_.Remove(callback_id);
2305 }
2306
2307 bool EWebView::IsFullscreen() {
2308   return web_contents_delegate_->IsFullscreenForTabOrPending(
2309       web_contents_.get());
2310 }
2311
2312 void EWebView::ExitFullscreen() {
2313   WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents_.get());
2314   wci->ExitFullscreen(false);
2315 }
2316
2317 double EWebView::GetScale() {
2318   return page_scale_factor_;
2319 }
2320
2321 void EWebView::DidChangePageScaleFactor(double scale_factor) {
2322   page_scale_factor_ = scale_factor;
2323   wcva()->wcva_helper()->SetPageScaleFactor(scale_factor);
2324   SetScaledContentsSize();
2325
2326   // Notify app about the scale change.
2327   scale_changed_cb_.Run(ewk_view_, scale_factor);
2328 }
2329
2330 inline JavaScriptDialogManagerEfl* EWebView::GetJavaScriptDialogManagerEfl() {
2331   return static_cast<JavaScriptDialogManagerEfl*>(
2332       web_contents_delegate_->GetJavaScriptDialogManager(web_contents_.get()));
2333 }
2334
2335 void EWebView::SetJavaScriptAlertCallback(
2336     Ewk_View_JavaScript_Alert_Callback callback,
2337     void* user_data) {
2338   GetJavaScriptDialogManagerEfl()->SetAlertCallback(callback, user_data);
2339 }
2340
2341 void EWebView::JavaScriptAlertReply() {
2342   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(true,
2343                                                                std::string());
2344   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
2345 }
2346
2347 void EWebView::SetJavaScriptConfirmCallback(
2348     Ewk_View_JavaScript_Confirm_Callback callback,
2349     void* user_data) {
2350   GetJavaScriptDialogManagerEfl()->SetConfirmCallback(callback, user_data);
2351 }
2352
2353 void EWebView::JavaScriptConfirmReply(bool result) {
2354   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(result,
2355                                                                std::string());
2356   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
2357 }
2358
2359 void EWebView::SetJavaScriptPromptCallback(
2360     Ewk_View_JavaScript_Prompt_Callback callback,
2361     void* user_data) {
2362   GetJavaScriptDialogManagerEfl()->SetPromptCallback(callback, user_data);
2363 }
2364
2365 void EWebView::JavaScriptPromptReply(const char* result) {
2366   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(
2367       true, (std::string(result)));
2368   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
2369 }
2370
2371 void EWebView::GetPageScaleRange(double* min_scale, double* max_scale) {
2372   auto& prefs = web_contents_->GetOrCreateWebPreferences();
2373   if (min_scale)
2374     *min_scale = prefs.default_minimum_page_scale_factor;
2375   if (max_scale)
2376     *max_scale = prefs.default_maximum_page_scale_factor;
2377 }
2378
2379 content::WebContentsViewAura* EWebView::GetWebContentsViewAura() const {
2380   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
2381   return static_cast<WebContentsViewAura*>(wc->GetView());
2382 }
2383
2384 bool EWebView::SetDrawsTransparentBackground(bool enabled) {
2385 #if BUILDFLAG(IS_TIZEN)
2386   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2387   if (!render_view_host || !rwhva())
2388     return false;
2389
2390   if (!rwhva()->offscreen_helper())
2391     return false;
2392   elm_object_style_set(rwhva()->offscreen_helper()->content_image_elm_host(),
2393                        enabled ? "transparent" : "default");
2394   evas_object_image_alpha_set(rwhva()->offscreen_helper()->content_image(),
2395                               enabled);
2396   GetWebContentsViewAura()->SetBackgroundColor(enabled ? SK_ColorTRANSPARENT
2397                                                        : SK_ColorWHITE);
2398   static_cast<RenderViewHostImpl*>(render_view_host)
2399       ->GetWidget()
2400       ->GetAssociatedFrameWidget()
2401       ->SetDrawsTransparentBackground(enabled);
2402   rwhva()->SetBackgroundColor(enabled ? SK_ColorTRANSPARENT : SK_ColorWHITE);
2403   return true;
2404 #else
2405   return false;
2406 #endif
2407 }
2408
2409 bool EWebView::GetDrawsTransparentBackground() {
2410 #if BUILDFLAG(IS_TIZEN)
2411   return GetWebContentsViewAura()->GetBackgroundColor() == SK_ColorTRANSPARENT;
2412 #else
2413   return false;
2414 #endif
2415 }
2416
2417 bool EWebView::SetBackgroundColor(int red, int green, int blue, int alpha) {
2418 #if BUILDFLAG(IS_TIZEN)
2419   if (!alpha)
2420     return SetDrawsTransparentBackground(true);
2421
2422   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2423   if (!render_view_host || !rwhva())
2424     return false;
2425
2426   if (!rwhva()->offscreen_helper())
2427     return false;
2428   elm_object_style_set(rwhva()->offscreen_helper()->content_image_elm_host(),
2429                        alpha < 255 ? "transparent" : "default");
2430   evas_object_image_alpha_set(rwhva()->offscreen_helper()->content_image(),
2431                               alpha < 255);
2432   GetWebContentsViewAura()->SetBackgroundColor(
2433       SkColorSetARGB(alpha, red, green, blue));
2434   static_cast<RenderViewHostImpl*>(render_view_host)
2435       ->GetWidget()
2436       ->GetAssociatedFrameWidget()
2437       ->SetBackgroundColor(red, green, blue, alpha);
2438   rwhva()->SetBackgroundColor(SkColorSetARGB(alpha, red, green, blue));
2439
2440   return true;
2441 #else
2442   return false;
2443 #endif
2444 }
2445
2446 void EWebView::GetSessionData(const char** data, unsigned* length) const {
2447   static const int MAX_SESSION_ENTRY_SIZE = std::numeric_limits<int>::max();
2448
2449   NavigationController& navigationController = web_contents_->GetController();
2450   base::Pickle sessionPickle;
2451   const int itemCount = navigationController.GetEntryCount();
2452
2453   sessionPickle.WriteInt(itemCount);
2454   sessionPickle.WriteInt(navigationController.GetCurrentEntryIndex());
2455
2456   for (int i = 0; i < itemCount; i++) {
2457     NavigationEntry* navigationEntry = navigationController.GetEntryAtIndex(i);
2458     sessions::SerializedNavigationEntry serializedEntry =
2459         sessions::ContentSerializedNavigationBuilder::FromNavigationEntry(
2460             i, navigationEntry);
2461     serializedEntry.WriteToPickle(MAX_SESSION_ENTRY_SIZE, &sessionPickle);
2462   }
2463
2464   if (sessionPickle.size() <= 0 ||
2465       !(*data =
2466             static_cast<char*>(malloc(sizeof(char) * sessionPickle.size())))) {
2467     LOG(ERROR) << "Failed to get session data";
2468     *length = 0;
2469     return;
2470   }
2471   memcpy(const_cast<char*>(*data), sessionPickle.data(), sessionPickle.size());
2472   *length = sessionPickle.size();
2473 }
2474
2475 bool EWebView::RestoreFromSessionData(const char* data, unsigned length) {
2476   base::Pickle sessionPickle(data, length);
2477   base::PickleIterator pickleIterator(sessionPickle);
2478   int entryCount;
2479   int currentEntry;
2480
2481   if (!pickleIterator.ReadInt(&entryCount))
2482     return false;
2483   if (!pickleIterator.ReadInt(&currentEntry))
2484     return false;
2485
2486   std::vector<sessions::SerializedNavigationEntry> serializedEntries;
2487   serializedEntries.resize(entryCount);
2488   for (int i = 0; i < entryCount; ++i) {
2489     if (!serializedEntries.at(i).ReadFromPickle(&pickleIterator))
2490       return false;
2491   }
2492
2493   if (!entryCount)
2494     return true;
2495
2496   if (!context())
2497     return false;
2498
2499   std::vector<std::unique_ptr<content::NavigationEntry>> scopedEntries =
2500       sessions::ContentSerializedNavigationBuilder::ToNavigationEntries(
2501           serializedEntries, context()->browser_context());
2502
2503   NavigationController& navigationController = web_contents_->GetController();
2504
2505   if (currentEntry < 0)
2506     currentEntry = 0;
2507
2508   if (currentEntry >= static_cast<int>(scopedEntries.size()))
2509     currentEntry = scopedEntries.size() - 1;
2510
2511   navigationController.Restore(currentEntry, RestoreType::kRestored,
2512                                &scopedEntries);
2513   return true;
2514 }
2515
2516 void EWebView::SetBrowserFont() {
2517 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2518   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2519   if (render_view_host) {
2520     IPC::Message* message =
2521         new EwkViewMsg_SetBrowserFont(render_view_host->GetRoutingID());
2522
2523     if (render_view_host->IsRenderViewLive())
2524       render_view_host->Send(message);
2525     else
2526       delayed_messages_.push_back(message);
2527   }
2528 #endif
2529 }
2530
2531 bool EWebView::IsDragging() const {
2532   return wcva()->wcva_helper()->IsDragging();
2533 }
2534
2535 void EWebView::ShowFileChooser(
2536     scoped_refptr<content::FileSelectListener> listener,
2537     const blink::mojom::FileChooserParams& params) {
2538 #if BUILDFLAG(IS_TIZEN_TV)
2539   LOG(INFO) << "File chooser request callback.";
2540   file_chooser_request_.reset(new _Ewk_File_Chooser_Request(
2541       std::move(listener), params.accept_types, params.mode));
2542   SmartCallback<EWebViewCallbacks::FileChooserRequest>().call(
2543       file_chooser_request_.get());
2544 #else
2545   if (!IsMobileProfile() && !IsWearableProfile())
2546     return;
2547   file_chooser_.reset(
2548       new content::FileChooserControllerEfl(std::move(listener), params));
2549   file_chooser_->Open();
2550 #endif
2551 }
2552
2553 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
2554 void EWebView::SetViewMode(blink::WebViewMode view_mode) {
2555   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2556   if (!render_view_host)
2557     return;
2558
2559   IPC::Message* message =
2560       new ViewMsg_SetViewMode(render_view_host->GetRoutingID(), view_mode);
2561   if (render_view_host->IsRenderViewLive()) {
2562     render_view_host->Send(message);
2563   } else {
2564     delayed_messages_.push_back(message);
2565   }
2566 }
2567 #endif
2568
2569 gfx::Point EWebView::GetContextMenuPosition() const {
2570   return context_menu_position_;
2571 }
2572
2573 void EWebView::ShowContentsDetectedPopup(const char* message) {
2574   popup_controller_.reset(new PopupControllerEfl(this));
2575   popup_controller_->openPopup(message);
2576 }
2577
2578 void EWebView::RequestColorPicker(int r, int g, int b, int a) {
2579   input_picker_.reset(new InputPicker(this, web_contents_.get(), ewk_view()));
2580   input_picker_->ShowColorPicker(r, g, b, a);
2581 }
2582
2583 bool EWebView::SetColorPickerColor(int r, int g, int b, int a) {
2584 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2585   web_contents_->DidChooseColorInColorChooser(SkColorSetARGB(a, r, g, b));
2586 #endif
2587   return true;
2588 }
2589
2590 void EWebView::InputPickerShow(ui::TextInputType input_type,
2591                                double input_value,
2592                                content::DateTimeChooserEfl* date_time_chooser) {
2593   input_picker_.reset(new InputPicker(this, web_contents_.get(), ewk_view(),
2594                                       date_time_chooser));
2595   input_picker_->ShowDatePicker(input_type, input_value);
2596 }
2597
2598 void EWebView::LoadNotFoundErrorPage(const std::string& invalidUrl) {
2599 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
2600   RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
2601   if (render_frame_host)
2602     render_frame_host->Send(new EwkFrameMsg_LoadNotFoundErrorPage(
2603         render_frame_host->GetRoutingID(), invalidUrl));
2604 #endif
2605 }
2606
2607 std::string EWebView::GetPlatformLocale() {
2608   char* local_default = setlocale(LC_CTYPE, 0);
2609   if (!local_default)
2610     return std::string("en-US");
2611   std::string locale = std::string(local_default);
2612   size_t position = locale.find('_');
2613   if (position != std::string::npos)
2614     locale.replace(position, 1, "-");
2615   position = locale.find('.');
2616   if (position != std::string::npos)
2617     locale = locale.substr(0, position);
2618   return locale;
2619 }
2620
2621 int EWebView::StartInspectorServer(int port) {
2622 #if BUILDFLAG(IS_TIZEN_TV)
2623   if (IsTIZENWRT()) {
2624     use_early_rwi_ = false;
2625     rwi_info_showed_ = false;
2626   }
2627   if (!context_->GetImpl()->GetInspectorServerState()) {
2628     int validPort = 0;
2629     if (!devtools_http_handler::DevToolsPortManager::GetInstance()
2630              ->GetValidPort(validPort))
2631       return 0;
2632
2633     port = validPort;
2634   }
2635 #endif
2636   return context_->InspectorServerStart(port);
2637 }
2638
2639 bool EWebView::StopInspectorServer() {
2640 #if BUILDFLAG(IS_TIZEN_TV)
2641   if (IsTIZENWRT()) {
2642     use_early_rwi_ = false;
2643     rwi_info_showed_ = false;
2644   }
2645 #endif
2646   return context_->InspectorServerStop();
2647 }
2648
2649 void EWebView::InvokeWebProcessCrashedCallback() {
2650   DCHECK_CURRENTLY_ON(BrowserThread::UI);
2651   const GURL last_url = GetURL();
2652   bool callback_handled = false;
2653   SmartCallback<EWebViewCallbacks::WebProcessCrashed>().call(&callback_handled);
2654   if (!callback_handled)
2655     LoadHTMLString(kRendererCrashedHTMLMessage, NULL,
2656                    last_url.possibly_invalid_spec().c_str());
2657 }
2658
2659 void EWebView::SyncAcceptLanguages(const std::string& accept_languages) {
2660   web_contents_->GetMutableRendererPrefs()->accept_languages = accept_languages;
2661   web_contents_->SyncRendererPrefs();
2662   BrowserContext* browser_context = web_contents_->GetBrowserContext();
2663   if (!browser_context)
2664     return;
2665
2666   auto* storage_partition = browser_context->GetDefaultStoragePartition();
2667   if (!storage_partition)
2668     return;
2669
2670   if (auto* network_context = storage_partition->GetNetworkContext())
2671     network_context->SetAcceptLanguage(accept_languages);
2672 }
2673
2674 #if BUILDFLAG(IS_TIZEN_TV)
2675 bool EWebView::EdgeScrollBy(int delta_x, int delta_y) {
2676   if ((delta_x == 0 && delta_y == 0) || is_processing_edge_scroll_)
2677     return false;
2678
2679   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
2680   if (!render_view_host)
2681     return false;
2682
2683   if (!rwhva())
2684     return false;
2685
2686   gfx::Point offset = gfx::Point(delta_x, delta_y);
2687   gfx::Point mouse_position;
2688   GetMousePosition(mouse_position);
2689   is_processing_edge_scroll_ = true;
2690
2691   static_cast<RenderViewHostImpl*>(render_view_host)
2692       ->GetWidget()
2693       ->GetAssociatedFrameWidget()
2694       ->EdgeScrollBy(offset, mouse_position);
2695   return true;
2696 }
2697
2698 void EWebView::GetMousePosition(gfx::Point& mouse_position) {
2699   int mouse_x, mouse_y;
2700   evas_pointer_output_xy_get(GetEvas(), &mouse_x, &mouse_y);
2701   Evas_Coord x, y, width, height;
2702   evas_object_geometry_get(ewk_view(), &x, &y, &width, &height);
2703
2704   if (mouse_y < y)
2705     mouse_y = y + 1;
2706   else if (mouse_y > y + height)
2707     mouse_y = y + height - 1;
2708   if (mouse_x < x)
2709     mouse_x = x + 1;
2710   else if (mouse_x > x + width)
2711     mouse_x = x + width - 1;
2712
2713   mouse_x -= x;
2714   mouse_y -= y;
2715
2716   mouse_x /=
2717       display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
2718   mouse_y /=
2719       display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
2720
2721   mouse_position.set_x(mouse_x);
2722   mouse_position.set_y(mouse_y);
2723 }
2724
2725 void EWebView::InvokeEdgeScrollByCallback(const gfx::Point& offset,
2726                                           bool handled) {
2727   is_processing_edge_scroll_ = false;
2728
2729   if (offset.x() < 0)
2730     SmartCallback<EWebViewCallbacks::EdgeScrollLeft>().call(&handled);
2731   else if (offset.x() > 0)
2732     SmartCallback<EWebViewCallbacks::EdgeScrollRight>().call(&handled);
2733
2734   if (offset.y() < 0)
2735     SmartCallback<EWebViewCallbacks::EdgeScrollTop>().call(&handled);
2736   else if (offset.y() > 0)
2737     SmartCallback<EWebViewCallbacks::EdgeScrollBottom>().call(&handled);
2738 }
2739 #endif
2740
2741 void EWebView::HandleRendererProcessCrash() {
2742   content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
2743       base::BindOnce(&EWebView::InvokeWebProcessCrashedCallback,
2744                      base::Unretained(this)));
2745 }
2746
2747 void EWebView::InitializeContent() {
2748   LOG(INFO) << "eweb_view.cc  InitializeContent" ;
2749 #if BUILDFLAG(IS_TIZEN_TV)
2750   // When initialize content init inspector server
2751   InitInspectorServer();
2752 #endif
2753   WebContents* new_contents = create_new_window_web_contents_cb_.Run(this);
2754   if (!new_contents) {
2755     WebContents::CreateParams params(context_->browser_context());
2756     web_contents_.reset(
2757         new WebContentsImplEfl(context_->browser_context(), this));
2758     static_cast<WebContentsImpl*>(web_contents_.get())
2759         ->Init(params, blink::FramePolicy());
2760   } else {
2761     web_contents_.reset(new_contents);
2762
2763     // When a new webview is created in response to a request from the
2764     // engine, the BrowserContext instance of the originator WebContents
2765     // is used by the newly created WebContents object.
2766     // See more in WebContentsImplEfl::HandleNewWebContentsCreate.
2767     //
2768     // Hence, if as part of the WebView creation, the embedding APP
2769     // passes in a Ewk_Context instance that wraps a different instance of
2770     // BrowserContext than the one the originator WebContents holds,
2771     // undefined behavior can be seen.
2772     //
2773     // This is a snippet code that illustrate the scenario:
2774     //
2775     // (..)
2776     // evas_object_smart_callback_add(web_view_, "create,window",
2777     //                                &OnNewWindowRequest, this);
2778     // (..)
2779     //
2780     // void OnNewWindowRequest(void *data, Evas_Object*, void* out_view) {
2781     //   (..)
2782     //   EvasObject* new_web_view = ewk_view_add_with_context(GetEvas(),
2783     //   ewk_context_new());
2784     //   *static_cast<Evas_Object**>(out_view) = new_web_view;
2785     //   (..)
2786     // }
2787     //
2788     // The new Ewk_Context object created and passed in as parameter to
2789     // ewk_view_add_with_context wraps a different instance of BrowserContext
2790     // than the one the new WebContents object will hold.
2791     //
2792     // CHECK below aims at catching misuse of this API.
2793     bool should_crash = context_->GetImpl()->browser_context() !=
2794                         web_contents_->GetBrowserContext();
2795     if (should_crash) {
2796       CHECK(false)
2797           << "BrowserContext of new WebContents does not match EWebView's. "
2798           << "Please see 'ewk_view_add*' documentation. "
2799           << "Aborting execution ...";
2800     }
2801   }
2802
2803   web_contents_delegate_.reset(new WebContentsDelegateEfl(this));
2804   web_contents_->SetDelegate(web_contents_delegate_.get());
2805
2806   // EWebView's delegate. Calls to WebContentsImplEfl and
2807   // WebContentsViewAuraHelperEfl are delegated to this class.
2808   // For more details, refer commit message of patch 301647.
2809   webview_delegate_.reset(new WebViewDelegateEfl(this));
2810   WebContentsImplEfl* wc_efl =
2811       static_cast<WebContentsImplEfl*>(web_contents_.get());
2812   wc_efl->SetWebviewDelegate(webview_delegate_.get());
2813   wcva()->wcva_helper()->SetWebviewDelegate(webview_delegate_.get());
2814
2815   back_forward_list_.reset(new _Ewk_Back_Forward_List(web_contents_.get()));
2816
2817   permission_popup_manager_.reset(new PermissionPopupManager(ewk_view_));
2818   gin_native_bridge_dispatcher_host_.reset(
2819       new content::GinNativeBridgeDispatcherHost(web_contents_.get()));
2820
2821   efl_main_layout_ =
2822       static_cast<WebContentsImplEfl*>(web_contents_.get())->GetEflMainLayout();
2823   evas_object_smart_member_add(efl_main_layout_, ewk_view_);
2824   static_cast<WebContentsImpl*>(web_contents_.get())->set_ewk_view(ewk_view_);
2825   InitializeWindowTreeHost();
2826 }
2827
2828 #if BUILDFLAG(IS_TIZEN_TV)
2829 void EWebView::OnDialogClosed() {
2830   if (!use_early_rwi_)
2831     return;
2832
2833   use_early_rwi_ = false;
2834   LOG(INFO) << "[FAST RWI] SetURL Restore [" << rwi_gurl_.spec()
2835             << "] from [about:blank]";
2836   SetURL(rwi_gurl_);
2837   rwi_gurl_ = GURL();
2838   rwi_info_showed_ = true;
2839 }
2840
2841 void EWebView::InitInspectorServer() {
2842   if (devtools_http_handler::DevToolsPortManager::GetInstance()
2843           ->ProcessCompare()) {
2844     int res = StartInspectorServer(0);
2845     if (res) {
2846       LOG(INFO) << "InitInspectorServer SetPort";
2847       devtools_http_handler::DevToolsPortManager::GetInstance()->SetPort(res);
2848     }
2849   }
2850 }
2851 #endif
2852
2853 #if defined(TIZEN_TBM_SUPPORT)
2854 void EWebView::SetOffscreenRendering(bool enable) {
2855   if (host_)
2856     host_->compositor()->SetUseTbmSuraceForOffscreenRendering(enable);
2857 }
2858 #endif
2859
2860 void EWebView::InitializeWindowTreeHost() {
2861   CHECK(aura::Env::GetInstance());
2862
2863   int x, y, width, height;
2864   Ecore_Evas* ee =
2865       ecore_evas_ecore_evas_get(evas_object_evas_get(efl_main_layout_));
2866   ecore_evas_geometry_get(ee, &x, &y, &width, &height);
2867
2868   gfx::Rect bounds(x, y, width, height);
2869   ui::PlatformWindowInitProperties properties;
2870   properties.bounds = bounds;
2871
2872   host_ = aura::WindowTreeHost::Create(std::move(properties));
2873   host_->InitHost();
2874   host_->window()->Show();
2875
2876   focus_client_ =
2877       std::make_unique<aura::test::TestFocusClient>(host_->window());
2878   window_parenting_client_ =
2879       std::make_unique<aura::test::TestWindowParentingClient>(host_->window());
2880   compositor_observer_ = std::make_unique<ui::CompositorObserverEfl>(
2881       host_->compositor(), web_contents_.get());
2882
2883   aura::Window* content = web_contents_->GetNativeView();
2884   aura::Window* parent = host_->window();
2885   if (!parent->Contains(content)) {
2886     parent->AddChild(content);
2887     content->Show();
2888   }
2889   content->SetBounds(bounds);
2890   RenderWidgetHostView* host_view = web_contents_->GetRenderWidgetHostView();
2891   if (host_view)
2892     host_view->SetSize(bounds.size());
2893 }
2894
2895 void EWebView::UrlRequestSet(
2896     const char* url,
2897     content::NavigationController::LoadURLType loadtype,
2898     Eina_Hash* headers,
2899     const char* body) {
2900   GURL gurl(url);
2901   content::NavigationController::LoadURLParams params(gurl);
2902   params.load_type = loadtype;
2903   params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
2904
2905   if (body) {
2906     std::string s(body);
2907     params.post_data =
2908         network::ResourceRequestBody::CreateFromBytes(s.data(), s.size());
2909   }
2910
2911   net::HttpRequestHeaders header;
2912   if (headers) {
2913     Eina_Iterator* it = eina_hash_iterator_tuple_new(headers);
2914     Eina_Hash_Tuple* t;
2915     while (eina_iterator_next(it, reinterpret_cast<void**>(&t))) {
2916       if (t->key) {
2917         const char* value_str =
2918             t->data ? static_cast<const char*>(t->data) : "";
2919         base::StringPiece name = static_cast<const char*>(t->key);
2920         base::StringPiece value = value_str;
2921         header.SetHeader(name, value);
2922         // net::HttpRequestHeaders.ToString() returns string with newline
2923         params.extra_headers += header.ToString();
2924       }
2925     }
2926     eina_iterator_free(it);
2927   }
2928
2929   web_contents_->GetController().LoadURLWithParams(params);
2930 }
2931
2932 #if defined(TIZEN_VIDEO_HOLE)
2933 void EWebView::EnableVideoHoleSupport() {
2934   if (!web_contents_->GetPrimaryMainFrame() ||
2935       !web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive() || !rwhva()) {
2936     pending_video_hole_setting_ = true;
2937     return;
2938   }
2939
2940   EnableVideoHoleSupportInternal();
2941 }
2942
2943 void EWebView::EnableVideoHoleSupportInternal() {
2944   if (settings_->getPreferences().video_hole_enabled)
2945     return;
2946
2947   settings_->getPreferences().video_hole_enabled = true;
2948   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
2949   if (wc)
2950     wc->EnableVideoHole();
2951 }
2952 #endif
2953
2954 bool EWebView::HandleShow() {
2955   if (!efl_main_layout_)
2956     return false;
2957
2958   Show();
2959   return true;
2960 }
2961
2962 bool EWebView::HandleHide() {
2963   if (!efl_main_layout_)
2964     return false;
2965
2966   Hide();
2967   return true;
2968 }
2969
2970 bool EWebView::HandleMove(int x, int y) {
2971   if (!efl_main_layout_)
2972     return false;
2973   evas_object_move(efl_main_layout_, x, y);
2974   LOG(INFO) << "Move x " << x << " y " << y;
2975 #if defined(TIZEN_VIDEO_HOLE)
2976   if (rwhva())
2977     rwhva()->DidMoveWebView();
2978 #endif
2979
2980   if (context_menu_)
2981     context_menu_->Move(x, y);
2982
2983   return true;
2984 }
2985
2986 bool EWebView::HandleResize(int width, int height) {
2987   if (!efl_main_layout_)
2988     return false;
2989   evas_object_resize(efl_main_layout_, width, height);
2990
2991 #if defined(TIZEN_VIDEO_HOLE)
2992   LOG(INFO) << __func__ << " new size " << width << "*" << height;
2993   if (rwhva())
2994     rwhva()->DidMoveWebView();
2995 #endif
2996
2997   if (select_picker_) {
2998     AdjustViewPortHeightToPopupMenu(true /* is_popup_menu_visible */);
2999     ScrollFocusedNodeIntoView();
3000   }
3001
3002 #if defined(USE_AURA) && BUILDFLAG(IS_TIZEN_TV)
3003   if (host_) {
3004     int x, y;
3005     evas_object_geometry_get(efl_main_layout_, &x, &y, nullptr, nullptr);
3006     gfx::Rect bounds(x, y, width, height);
3007     host_->SetBoundsInPixels(bounds);
3008   }
3009 #endif
3010
3011   return true;
3012 }
3013
3014 bool EWebView::HandleTextSelectionDown(int x, int y) {
3015   if (!GetSelectionController())
3016     return false;
3017   return GetSelectionController()->TextSelectionDown(x, y);
3018 }
3019
3020 bool EWebView::HandleTextSelectionUp(int x, int y) {
3021   if (!GetSelectionController())
3022     return false;
3023   return GetSelectionController()->TextSelectionUp(x, y);
3024 }
3025
3026 void EWebView::HandleTapGestureForSelection(bool is_content_editable) {
3027   if (!GetSelectionController())
3028     return;
3029
3030   GetSelectionController()->PostHandleTapGesture(is_content_editable);
3031 }
3032
3033 void EWebView::HandleZoomGesture(blink::WebGestureEvent& event) {
3034   blink::WebInputEvent::Type event_type = event.GetType();
3035   if (event_type == blink::WebInputEvent::Type::kGestureDoubleTap ||
3036       event_type == blink::WebInputEvent::Type::kGesturePinchBegin) {
3037     SmartCallback<EWebViewCallbacks::ZoomStarted>().call();
3038   }
3039   if (event_type == blink::WebInputEvent::Type::kGestureDoubleTap ||
3040       event_type == blink::WebInputEvent::Type::kGesturePinchEnd) {
3041     SmartCallback<EWebViewCallbacks::ZoomFinished>().call();
3042   }
3043 }
3044
3045 bool EWebView::GetHorizontalPanningHold() const {
3046   if (!rwhva())
3047     return false;
3048   return rwhva()->offscreen_helper()->GetHorizontalPanningHold();
3049 }
3050
3051 void EWebView::SetHorizontalPanningHold(bool hold) {
3052   if (rwhva())
3053     rwhva()->offscreen_helper()->SetHorizontalPanningHold(hold);
3054 }
3055
3056 bool EWebView::GetVerticalPanningHold() const {
3057   if (!rwhva())
3058     return false;
3059   return rwhva()->offscreen_helper()->GetVerticalPanningHold();
3060 }
3061
3062 void EWebView::SetVerticalPanningHold(bool hold) {
3063   if (rwhva())
3064     rwhva()->offscreen_helper()->SetVerticalPanningHold(hold);
3065 }
3066
3067 void EWebView::SendDelayedMessages(RenderViewHost* render_view_host) {
3068   DCHECK(render_view_host);
3069
3070   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
3071     content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
3072         base::BindOnce(&EWebView::SendDelayedMessages, base::Unretained(this),
3073                        render_view_host));
3074     return;
3075   }
3076
3077   for (auto iter = delayed_messages_.begin(); iter != delayed_messages_.end();
3078        ++iter) {
3079     IPC::Message* message = *iter;
3080     message->set_routing_id(render_view_host->GetRoutingID());
3081 #if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
3082     render_view_host->Send(message);
3083 #endif
3084   }
3085
3086   delayed_messages_.clear();
3087 }
3088
3089 void EWebView::ClosePage() {
3090   web_contents_->ClosePage();
3091 }
3092
3093 bool EWebView::SetMainFrameScrollbarVisible(bool visible) {
3094   if (web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive() && rwhva())
3095     rwhva()->host()->SetMainFrameScrollbarVisible(visible);
3096   return true;
3097 }
3098
3099 bool EWebView::GetMainFrameScrollbarVisible(
3100     Ewk_View_Main_Frame_Scrollbar_Visible_Get_Callback callback,
3101     void* user_data) {
3102   if (!rwhva())
3103     return false;
3104
3105   MainFrameScrollbarVisibleGetCallback* callback_ptr =
3106       new MainFrameScrollbarVisibleGetCallback;
3107   callback_ptr->Set(callback, user_data);
3108   int callback_id =
3109       main_frame_scrollbar_visible_callback_map_.Add(callback_ptr);
3110   rwhva()->host()->RequestMainFrameScrollbarVisible(callback_id);
3111   return true;
3112 }
3113
3114 void EWebView::InvokeMainFrameScrollbarVisibleCallback(int callback_id,
3115                                                        bool visible) {
3116   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
3117     content::GetUIThreadTaskRunner({})->PostTask(
3118         FROM_HERE,
3119         base::BindOnce(&EWebView::InvokeMainFrameScrollbarVisibleCallback,
3120                        base::Unretained(this), visible, callback_id));
3121     return;
3122   }
3123
3124   MainFrameScrollbarVisibleGetCallback* callback =
3125       main_frame_scrollbar_visible_callback_map_.Lookup(callback_id);
3126   if (!callback)
3127     return;
3128
3129   main_frame_scrollbar_visible_callback_map_.Remove(callback_id);
3130   callback->Run(ewk_view(), visible);
3131   main_frame_scrollbar_visible_callback_map_.Remove(callback_id);
3132 }
3133
3134 void EWebView::OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll,
3135                               const gfx::Vector2dF& latest_overscroll_delta) {
3136   const gfx::Vector2dF old_overscroll =
3137       accumulated_overscroll - latest_overscroll_delta;
3138
3139   if (latest_overscroll_delta.x() && !old_overscroll.x()) {
3140     latest_overscroll_delta.x() < 0
3141         ? SmartCallback<EWebViewCallbacks::OverscrolledLeft>().call()
3142         : SmartCallback<EWebViewCallbacks::OverscrolledRight>().call();
3143   }
3144   if (latest_overscroll_delta.y() && !old_overscroll.y()) {
3145     latest_overscroll_delta.y() < 0
3146         ? SmartCallback<EWebViewCallbacks::OverscrolledTop>().call()
3147         : SmartCallback<EWebViewCallbacks::OverscrolledBottom>().call();
3148   }
3149 }
3150
3151 void EWebView::SetDidChangeThemeColorCallback(
3152     Ewk_View_Did_Change_Theme_Color_Callback callback,
3153     void* user_data) {
3154   did_change_theme_color_callback_.Set(callback, user_data);
3155 }
3156
3157 void EWebView::DidChangeThemeColor(const SkColor& color) {
3158   did_change_theme_color_callback_.Run(ewk_view_, color);
3159 }
3160
3161 #if BUILDFLAG(IS_TIZEN_TV)
3162 void EWebView::DrawLabel(Evas_Object* image, Eina_Rectangle rect) {
3163   if (rwhva())
3164     rwhva()->offscreen_helper()->DrawLabel(image, rect);
3165 }
3166
3167 void EWebView::DeactivateAtk(bool deactivated) {
3168 #if defined(TIZEN_ATK_SUPPORT)
3169   EWebAccessibilityUtil::GetInstance()->Deactivate(deactivated);
3170 #endif
3171 }
3172
3173 void EWebView::ClearLabels() {
3174   if (rwhva())
3175     rwhva()->offscreen_helper()->ClearLabels();
3176 }
3177 #endif
3178
3179 void EWebView::RequestManifest(Ewk_View_Request_Manifest_Callback callback,
3180                                void* user_data) {
3181   web_contents_delegate_->RequestManifestInfo(callback, user_data);
3182 }
3183
3184 void EWebView::DidRespondRequestManifest(
3185     _Ewk_View_Request_Manifest* manifest,
3186     Ewk_View_Request_Manifest_Callback callback,
3187     void* user_data) {
3188   callback(ewk_view_, manifest, user_data);
3189 }
3190
3191 void EWebView::SetSessionTimeout(uint64_t timeout) {
3192   if (web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive() && rwhva())
3193     rwhva()->host()->SetLongPollingGlobalTimeout(timeout);
3194 }
3195
3196 void EWebView::SetBeforeUnloadConfirmPanelCallback(
3197     Ewk_View_Before_Unload_Confirm_Panel_Callback callback,
3198     void* user_data) {
3199   GetJavaScriptDialogManagerEfl()->SetBeforeUnloadConfirmPanelCallback(
3200       callback, user_data);
3201 }
3202
3203 void EWebView::ReplyBeforeUnloadConfirmPanel(Eina_Bool result) {
3204   GetJavaScriptDialogManagerEfl()->ReplyBeforeUnloadConfirmPanel(result);
3205 }
3206
3207 #if defined(TIZEN_PEPPER_EXTENSIONS)
3208 void EWebView::InitializePepperExtensionSystem() {
3209   RegisterPepperExtensionDelegate();
3210   SetWindowId();
3211 }
3212
3213 EwkExtensionSystemDelegate* EWebView::GetExtensionDelegate() {
3214   RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
3215   if (!render_frame_host)
3216     return nullptr;
3217
3218   return static_cast<EwkExtensionSystemDelegate*>(
3219       ExtensionSystemDelegateManager::GetInstance()->GetDelegateForFrame(render_frame_id_));
3220 }
3221
3222 void EWebView::SetWindowId() {
3223   EwkExtensionSystemDelegate* delegate = GetExtensionDelegate();
3224   if (!delegate) {
3225     LOG(WARNING) << "No delegate is available to set window id";
3226     return;
3227   }
3228   Evas_Object* main_wind =
3229       efl::WindowFactory::GetHostWindow(web_contents_.get());
3230   if (!main_wind) {
3231     LOG(ERROR) << "Can`t get main window";
3232     return;
3233   }
3234   delegate->SetWindowId(main_wind);
3235 }
3236
3237 void EWebView::SetPepperExtensionWidgetInfo(Ewk_Value widget_pepper_ext_info) {
3238   EwkExtensionSystemDelegate* delegate = GetExtensionDelegate();
3239   if (!delegate) {
3240     LOG(WARNING) << "No delegate is available to set extension info";
3241     return;
3242   }
3243   delegate->SetExtensionInfo(widget_pepper_ext_info);
3244 }
3245
3246 void EWebView::SetPepperExtensionCallback(Generic_Sync_Call_Callback cb,
3247                                           void* data) {
3248   EwkExtensionSystemDelegate* delegate = GetExtensionDelegate();
3249   if (!delegate) {
3250     LOG(WARNING) << "No delegate is available to set generic callback";
3251     return;
3252   }
3253   delegate->SetGenericSyncCallback(cb, data);
3254 }
3255
3256 void EWebView::RegisterPepperExtensionDelegate() {
3257   RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame();
3258   if (!render_frame_host) {
3259     LOG(WARNING) << "render_frame_host is nullptr, can't register delegate";
3260     return;
3261   }
3262
3263   render_frame_id_.render_process_id = render_frame_host->GetProcess()->GetID();
3264   render_frame_id_.render_frame_id = render_frame_host->GetRoutingID();
3265
3266   EwkExtensionSystemDelegate* delegate = new EwkExtensionSystemDelegate;
3267   ExtensionSystemDelegateManager::GetInstance()->RegisterDelegate(
3268       render_frame_id_, std::unique_ptr<EwkExtensionSystemDelegate>{delegate});
3269 }
3270
3271 void EWebView::UnregisterPepperExtensionDelegate() {
3272   if (!web_contents_) {
3273     LOG(WARNING) << "web_contents_ is nullptr, can't unregister delegate";
3274     return;
3275   }
3276   if (!ExtensionSystemDelegateManager::GetInstance()->UnregisterDelegate(render_frame_id_))
3277     LOG(WARNING) << "Unregistering pepper extension delegate failed";
3278 }
3279 #endif  // defined(TIZEN_PEPPER_EXTENSIONS)
3280
3281 void EWebView::SetExceededIndexedDatabaseQuotaCallback(
3282     Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback,
3283     void* user_data) {
3284   exceeded_indexed_db_quota_callback_.Set(callback, user_data);
3285   content::BrowserContextEfl* browser_context =
3286       static_cast<content::BrowserContextEfl*>(
3287           web_contents_->GetBrowserContext());
3288   if (browser_context) {
3289     browser_context->GetSpecialStoragePolicyEfl()->SetQuotaExceededCallback(
3290         base::BindOnce(&EWebView::InvokeExceededIndexedDatabaseQuotaCallback,
3291                        base::Unretained(this)));
3292   }
3293 }
3294
3295 void EWebView::InvokeExceededIndexedDatabaseQuotaCallback(
3296     const GURL& origin,
3297     int64_t current_quota) {
3298   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
3299     content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
3300         base::BindOnce(&EWebView::InvokeExceededIndexedDatabaseQuotaCallback,
3301                        base::Unretained(this), origin, current_quota));
3302     return;
3303   }
3304   LOG(INFO) << __func__ << "()" << origin << ", " << current_quota;
3305   CHECK(!exceeded_indexed_db_quota_origin_.get());
3306   exceeded_indexed_db_quota_origin_.reset(new Ewk_Security_Origin(origin));
3307   exceeded_indexed_db_quota_callback_.Run(
3308       ewk_view_, exceeded_indexed_db_quota_origin_.get(), current_quota);
3309 }
3310
3311 void EWebView::ExceededIndexedDatabaseQuotaReply(bool allow) {
3312   if (!exceeded_indexed_db_quota_origin_.get()) {
3313     LOG(WARNING) << __func__ << "() : callback is not invoked!";
3314     return;
3315   }
3316   LOG(INFO) << __func__ << "()" << exceeded_indexed_db_quota_origin_->GetURL()
3317             << ", " << allow;
3318   content::BrowserContextEfl* browser_context =
3319       static_cast<content::BrowserContextEfl*>(
3320           web_contents_->GetBrowserContext());
3321   if (browser_context) {
3322     browser_context->GetSpecialStoragePolicyEfl()->SetUnlimitedStoragePolicy(
3323         exceeded_indexed_db_quota_origin_->GetURL(), allow);
3324   }
3325   exceeded_indexed_db_quota_origin_.reset();
3326 }
3327
3328 bool EWebView::ShouldIgnoreNavigation(
3329     content::NavigationHandle* navigation_handle) {
3330   if (!navigation_handle->GetURL().is_valid() ||
3331       !navigation_handle->GetURL().SchemeIs("appcontrol") ||
3332       (!navigation_handle->HasUserGesture() &&
3333        !navigation_handle->WasServerRedirect())) {
3334     return false;
3335   }
3336
3337   _Ewk_App_Control app_control(
3338       this, navigation_handle->GetURL().possibly_invalid_spec());
3339   return app_control.Proceed();
3340 }
3341
3342 #if BUILDFLAG(IS_TIZEN_TV)
3343 void EWebView::AddDynamicCertificatePath(const std::string& host,
3344                                          const std::string& cert_path) {
3345   web_contents_->AddDynamicCertificatePath(host, cert_path);
3346 }
3347 #endif
3348
3349 bool EWebView::SetVisibility(bool enable) {
3350   if (!web_contents_)
3351     return false;
3352
3353   if (enable)
3354     web_contents_->WasShown();
3355   else
3356     web_contents_->WasHidden();
3357
3358   return true;
3359 }
3360
3361 void EWebView::SetDoNotTrack(Eina_Bool enable) {
3362   // enable: 0 User tend to allow tracking on the target site.
3363   // enable: 1 User tend to not be tracked on the target site.
3364   if (web_contents_->GetMutableRendererPrefs()->enable_do_not_track == enable)
3365     return;
3366
3367   // Set navigator.doNotTrack attribute
3368   web_contents_->GetMutableRendererPrefs()->enable_do_not_track = enable;
3369   web_contents_->SyncRendererPrefs();
3370
3371   // Set or remove DNT HTTP header, the effects will depend on design of target
3372   // site.
3373   if (!context())
3374     return;
3375
3376   if (enable)
3377     context()->HTTPCustomHeaderAdd("DNT", "1");
3378   else
3379     context()->HTTPCustomHeaderRemove("DNT");
3380 }
3381
3382 #if defined(TIZEN_ATK_SUPPORT)
3383 void EWebView::UpdateSpatialNavigationStatus(Eina_Bool enable) {
3384   if (settings_->getPreferences().spatial_navigation_enabled == enable)
3385     return;
3386
3387   settings_->getPreferences().spatial_navigation_enabled = enable;
3388   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
3389   if (wc)
3390     wc->SetSpatialNavigationEnabled(enable);
3391 }
3392
3393 void EWebView::UpdateAccessibilityStatus(Eina_Bool enable) {
3394   if (settings_->getPreferences().atk_enabled == enable)
3395     return;
3396
3397   settings_->getPreferences().atk_enabled = enable;
3398   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
3399   if (wc)
3400     wc->SetAtkEnabled(enable);
3401 }
3402
3403 void EWebView::InitAtk() {
3404 #if defined(TIZEN_ATK_SUPPORT)
3405   EWebAccessibilityUtil::GetInstance()->ToggleAtk(lazy_initialize_atk_);
3406 #endif
3407 }
3408
3409 /* LCOV_EXCL_START */
3410 bool EWebView::GetAtkStatus() {
3411   auto state = content::BrowserAccessibilityStateImpl::GetInstance();
3412   if (!state)
3413     return false;
3414   return state->IsAccessibleBrowser();
3415 }
3416 /* LCOV_EXCL_STOP */
3417 #endif
3418
3419 #if BUILDFLAG(IS_TIZEN_TV)
3420 bool EWebView::SetMixedContents(bool allow) {
3421   MixedContentObserver* mixed_content_observer =
3422       MixedContentObserver::FromWebContents(web_contents_.get());
3423   return mixed_content_observer->MixedContentReply(allow);
3424 }
3425
3426 void EWebView::NotifyDownloadableFontInfo(const char* scheme_id_uri,
3427                                           const char* value,
3428                                           const char* data,
3429                                           int type) {
3430   LOG(INFO) << "scheme_id_uri:" << scheme_id_uri << ",value:" << value
3431             << ",data:" << data << ",type:" << type;
3432   Ewk_Media_Downloadable_Font_Info* info =
3433       ewkMediaDownloadableFontInfoCreate(scheme_id_uri, value, data, type);
3434   SmartCallback<EWebViewCallbacks::DownloadableFontInfo>().call(
3435       static_cast<void*>(info));
3436   ewkMediaDownloadableFontInfoDelete(info);
3437 }
3438
3439 void EWebView::NotifyMediaStateChanged(uint32_t device_type,
3440                                        uint32_t previous,
3441                                        uint32_t current) {
3442   LOG(INFO) << "NotifyMediaStateChanged type : " << device_type
3443             << " ;previous: " << previous << " ; current: " << current;
3444   Ewk_User_Media_State_Info* user_media_state_info =
3445       new _Ewk_User_Media_State_Info;
3446   user_media_state_info->device_type =
3447       static_cast<Ewk_User_Media_Device_Type>(device_type);
3448   user_media_state_info->previous_state = previous;
3449   user_media_state_info->current_state = current;
3450   SmartCallback<EWebViewCallbacks::UserMediaState>().call(
3451       static_cast<void*>(user_media_state_info));
3452
3453   delete user_media_state_info;
3454 }
3455
3456 void EWebView::SetHighBitRate(Eina_Bool high_bitrate) {
3457   LOG(INFO) << "high_bitrate: " << std::boolalpha << high_bitrate;
3458   is_high_bitrate_ = high_bitrate;
3459 }
3460
3461 void EWebView::OnDeviceListed(const MediaDeviceEnumeration& devices) {
3462   int device_count = 0;
3463   EwkMediaDeviceInfo* device_list = nullptr;
3464   for (const auto& device : devices)
3465     device_count += device.size();
3466
3467   device_list =
3468       (EwkMediaDeviceInfo*)malloc(sizeof(EwkMediaDeviceInfo) * device_count);
3469   if (!device_list) {
3470     LOG(ERROR) << "malloc EwkMediaDeviceInfo failed";
3471     device_cb_.Run(device_list, 0);
3472     return;
3473   }
3474
3475   int idx = 0;
3476   for (int i = 0; i < NUM_MEDIA_DEVICE_TYPES; i++) {
3477     blink::WebMediaDeviceInfoArray array = devices[i];
3478     for (const auto& device : array) {
3479       LOG(INFO) << "OnDeviceListed type:" << i
3480                 << ",device_id:" << device.device_id
3481                 << ",lable:" << device.label;
3482
3483       // convert device info to ewk structure
3484       EwkMediaDeviceInfo* data = &device_list[idx++];
3485       data->device_id = eina_stringshare_add(device.device_id.c_str());
3486       data->label = eina_stringshare_add(device.label.c_str());
3487       data->type = static_cast<EwkMediaDeviceType>(i);
3488       data->connected = true;
3489     }
3490   }
3491
3492   device_cb_.Run(device_list, device_count);
3493
3494   // free data
3495   for (int i = 0; i < device_count; i++) {
3496     EwkMediaDeviceInfo* device = &device_list[i];
3497     if (device->device_id)
3498       eina_stringshare_del(device->device_id);
3499     if (device->label)
3500       eina_stringshare_del(device->label);
3501   }
3502   if (device_list) {
3503     free(device_list);
3504     device_list = NULL;
3505   }
3506 }
3507
3508 void EWebView::GetMediaDeviceList(Ewk_Media_Device_List_Get_Callback callback,
3509                                   void* userData) {
3510   if (!web_contents_delegate_) {
3511     LOG(ERROR) << "no web_contents_delegate_";
3512     return;
3513   }
3514
3515   device_cb_.Set(callback, userData);
3516
3517   web_contents_delegate_->GetMediaDeviceList(
3518       base::BindOnce(&EWebView::OnDeviceListed, weak_factory_.GetWeakPtr()));
3519 }
3520 #endif