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