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