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