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