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