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