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