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