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