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