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