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