[M69 Dev][Tizen] Enable touch events for mobile/wearable profile
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / eweb_view.cc
1 // Copyright 2014 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 "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/pickle.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "browser/navigation_policy_handler_efl.h"
13 #include "browser/quota_permission_context_efl.h"
14 #include "browser/web_view_browser_message_filter.h"
15 #include "common/content_client_efl.h"
16 #include "common/render_messages_ewk.h"
17 #include "common/version_info.h"
18 #include "common/web_contents_utils.h"
19 #include "components/sessions/content/content_serialized_navigation_builder.h"
20 #include "components/sessions/core/serialized_navigation_entry.h"
21 #include "content/browser/renderer_host/render_view_host_impl.h"
22 #include "content/browser/renderer_host/render_widget_host_view_efl.h"
23 #include "content/browser/renderer_host/ui_events_helper.h"
24 #include "content/browser/renderer_host/web_event_factory_efl.h"
25 #include "content/browser/web_contents/web_contents_impl_efl.h"
26 #include "content/browser/web_contents/web_contents_view.h"
27 #include "content/browser/web_contents/web_contents_view_efl.h"
28 #include "content/common/content_client_export.h"
29 #include "content/common/frame_messages.h"
30 #include "content/common/view_messages.h"
31 #include "content/public/browser/browser_message_filter.h"
32 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/host_zoom_map.h"
34 #include "content/public/browser/navigation_controller.h"
35 #include "content/public/browser/navigation_entry.h"
36 #include "content/public/browser/resource_dispatcher_host.h"
37 #include "content/public/common/content_client.h"
38 #include "content/public/common/content_switches.h"
39 #include "content/public/common/user_agent.h"
40 #include "permission_popup_manager.cc"
41 #include "private/ewk_back_forward_list_private.h"
42 #include "private/ewk_context_private.h"
43 #include "private/ewk_frame_private.h"
44 #include "private/ewk_policy_decision_private.h"
45 #include "private/ewk_quota_permission_request_private.h"
46 #include "private/ewk_settings_private.h"
47 #include "private/ewk_text_style_private.h"
48 #include "private/webview_delegate_ewk.h"
49 #include "public/ewk_hit_test_internal.h"
50 #include "services/network/public/cpp/resource_request_body.h"
51 #include "skia/ext/platform_canvas.h"
52 #include "third_party/blink/public/platform/web_string.h"
53 #include "third_party/blink/public/web/web_find_options.h"
54 #include "tizen/system_info.h"
55 #include "ui/base/l10n/l10n_util.h"
56 #include "ui/display/screen.h"
57 #include "web_contents_delegate_efl.h"
58 #include "web_contents_efl_delegate_ewk.h"
59 #include "web_contents_view_efl_delegate_ewk.h"
60
61 #include "browser/web_view_evas_handler.h"
62
63 #include "browser/selectpicker/popup_menu_item.h"
64 #include "browser/selectpicker/popup_menu_item_private.h"
65 #include <Ecore_Evas.h>
66 #include <Elementary.h>
67 #include <Eina.h>
68
69 #include <iostream>
70
71 using namespace content;
72 using web_contents_utils::WebViewFromWebContents;
73
74 namespace {
75
76 int screen_orientation_ = 0;
77
78 static const char* kRendererCrashedHTMLMessage =
79     "<html><body><h1>Renderer process has crashed!</h1></body></html>";
80
81 inline void SetDefaultStringIfNull(const char*& variable,
82                                    const char* default_string) {
83   if (!variable) {
84     variable = default_string;
85   }
86 }
87
88 void GetEinaRectFromGfxRect(const gfx::Rect& gfx_rect,
89                             Eina_Rectangle* eina_rect) {
90   eina_rect->x = gfx_rect.x();
91   eina_rect->y = gfx_rect.y();
92   eina_rect->w = gfx_rect.width();
93   eina_rect->h = gfx_rect.height();
94 }
95
96 static content::WebContents* NullCreateWebContents(void*) {
97   return NULL;
98 }
99
100 }  // namespace
101
102 class WebViewAsyncRequestHitTestDataCallback {
103  public:
104   WebViewAsyncRequestHitTestDataCallback(int x, int y, Ewk_Hit_Test_Mode mode)
105       : x_(x), y_(y), mode_(mode) {}
106   virtual ~WebViewAsyncRequestHitTestDataCallback(){};
107
108   virtual void Run(_Ewk_Hit_Test* hit_test, EWebView* web_view) = 0;
109
110  protected:
111   int GetX() const { return x_; }
112   int GetY() const { return y_; }
113   Ewk_Hit_Test_Mode GetMode() const { return mode_; }
114
115  private:
116   int x_;
117   int y_;
118   Ewk_Hit_Test_Mode mode_;
119 };
120
121 class WebViewAsyncRequestHitTestDataUserCallback
122     : public WebViewAsyncRequestHitTestDataCallback {
123  public:
124   WebViewAsyncRequestHitTestDataUserCallback(
125       int x,
126       int y,
127       Ewk_Hit_Test_Mode mode,
128       Ewk_View_Hit_Test_Request_Callback callback,
129       void* user_data)
130       : WebViewAsyncRequestHitTestDataCallback(x, y, mode),
131         callback_(callback),
132         user_data_(user_data) {}
133
134   void Run(_Ewk_Hit_Test* hit_test, EWebView* web_view) override {
135     DCHECK(callback_);
136     callback_(web_view->evas_object(), GetX(), GetY(), GetMode(), hit_test,
137               user_data_);
138   }
139
140  private:
141   Ewk_View_Hit_Test_Request_Callback callback_;
142   void* user_data_;
143 };
144
145 int EWebView::find_request_id_counter_ = 0;
146 content::WebContentsEflDelegate::WebContentsCreateCallback
147     EWebView::create_new_window_web_contents_cb_ =
148         base::Bind(&NullCreateWebContents);
149
150 EWebView* EWebView::FromEvasObject(Evas_Object* eo) {
151   return WebViewDelegateEwk::GetInstance().GetWebViewFromEvasObject(eo);
152 }
153
154 RenderWidgetHostViewEfl* EWebView::rwhv() const {
155   return static_cast<RenderWidgetHostViewEfl*>(
156       web_contents_->GetRenderWidgetHostView());
157 }
158
159 EWebView::EWebView(Ewk_Context* context, Evas_Object* object)
160     : context_(context),
161       evas_object_(object),
162       native_view_(object),
163       touch_events_enabled_(false),
164       mouse_events_enabled_(false),
165       text_zoom_factor_(1.0),
166       formIsNavigating_(false),
167       current_find_request_id_(find_request_id_counter_++),
168       progress_(0.0),
169       hit_test_completion_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
170                            base::WaitableEvent::InitialState::NOT_SIGNALED),
171       page_scale_factor_(1.0),
172       is_initialized_(false) {}
173
174 void EWebView::Initialize() {
175   if (is_initialized_) {
176     return;
177   }
178
179   InitializeContent();
180
181   evas_event_handler_ = new WebViewEvasEventHandler(this);
182
183   scroll_detector_.reset(new ScrollDetector(this));
184
185   web_contents_delegate_.reset(new WebContentsDelegateEfl(this));
186   web_contents_->SetDelegate(web_contents_delegate_.get());
187   back_forward_list_.reset(
188       new _Ewk_Back_Forward_List(web_contents_->GetController()));
189
190   DCHECK(web_contents_->GetRenderViewHost());
191   // Settings (content::WebPreferences) will be initalized by
192   // RenderViewHostImpl::ComputeWebkitPrefs() based on command line switches.
193   settings_.reset(new Ewk_Settings(
194       evas_object_,
195       web_contents_->GetRenderViewHost()->GetWebkitPreferences()));
196   base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
197   if (cmdline->HasSwitch(switches::kTouchEventFeatureDetection)) {
198     SetTouchEventsEnabled(
199         cmdline->GetSwitchValueASCII(switches::kTouchEventFeatureDetection) ==
200         switches::kTouchEventFeatureDetectionEnabled);
201   } else {
202     SetMouseEventsEnabled(true);
203   }
204
205   popupMenuItems_ = 0;
206   popupPicker_ = 0;
207
208   formNavigation_.count = 1;
209   formNavigation_.position = 0;
210   formNavigation_.prevState = false;
211   formNavigation_.nextState = false;
212
213   // allow this object and its children to get a focus
214   elm_object_tree_focus_allow_set(native_view_, EINA_TRUE);
215   is_initialized_ = true;
216 }
217
218 EWebView::~EWebView() {
219   std::map<int64_t, WebViewAsyncRequestHitTestDataCallback*>::iterator
220       hit_test_callback_iterator;
221   for (hit_test_callback_iterator = hit_test_callback_.begin();
222        hit_test_callback_iterator != hit_test_callback_.end();
223        hit_test_callback_iterator++)
224     delete hit_test_callback_iterator->second;
225   hit_test_callback_.clear();
226
227   for (auto iter = delayed_messages_.begin(); iter != delayed_messages_.end();
228        ++iter)
229     delete *iter;
230
231   delayed_messages_.clear();
232
233   if (!is_initialized_) {
234     return;
235   }
236
237   context_menu_.reset();
238   mhtml_callback_map_.Clear();
239
240   ReleasePopupMenuList();
241
242   if (popupPicker_)
243     popup_picker_del(popupPicker_);
244
245   formNavigation_.count = 1;
246   formNavigation_.position = 0;
247   formNavigation_.prevState = false;
248   formNavigation_.nextState = false;
249
250   //  evas_object_del(evas_object());
251
252   // Release manually those scoped pointers to
253   // make sure they are released in correct order
254   web_contents_.reset();
255   web_contents_delegate_.reset();
256
257   // This code must be executed after WebContents deletion
258   // because WebContents depends on BrowserContext which
259   // is deleted along with EwkContext.
260   CHECK(!web_contents_);
261   if (old_context_.get()) {
262     Ewk_Context::Delete(context_.get());
263     context_ = old_context_;
264     old_context_ = NULL;
265   }
266
267   GetPermissionPopupManager()->DeleteAllPermissionRequest();
268   permission_popup_manager_.reset();
269
270   if (context_->GetImpl()->browser_context()->IsOffTheRecord())
271     Ewk_Context::Delete(context_.get());
272 }
273
274 void EWebView::ReleasePopupMenuList() {
275   if (!popupMenuItems_)
276     return;
277
278   void* dummyItem;
279   EINA_LIST_FREE(popupMenuItems_, dummyItem) {
280     delete static_cast<Popup_Menu_Item*>(dummyItem);
281   }
282
283   popupMenuItems_ = 0;
284 }
285
286 void EWebView::ResetContextMenuController() {
287   return context_menu_.reset();
288 }
289
290 void EWebView::SetFocus(Eina_Bool focus) {
291   if (HasFocus() != focus)
292     elm_object_focus_set(native_view_, focus);
293 }
294
295 void EWebView::CreateNewWindow(
296     content::WebContentsEflDelegate::WebContentsCreateCallback cb) {
297   create_new_window_web_contents_cb_ = cb;
298   Evas_Object* new_object = NULL;
299   SmartCallback<EWebViewCallbacks::CreateNewWindow>().call(&new_object);
300   create_new_window_web_contents_cb_ = base::Bind(&NullCreateWebContents);
301   DCHECK(new_object);
302 }
303
304 // static
305 Evas_Object* EWebView::GetHostWindowDelegate(const content::WebContents* wc) {
306   EWebView* thiz = WebViewFromWebContents(wc);
307   DCHECK(thiz->evas_object_);
308   Evas_Object* parent = evas_object_above_get(thiz->evas_object_);
309   if (!parent) {
310     LOG(WARNING) << "Could not find and visual parents for EWK smart object!.";
311     return thiz->evas_object_;
312   }
313
314   if (elm_object_widget_check(parent)) {
315     Evas_Object* elm_parent = elm_object_top_widget_get(parent);
316     if (elm_parent)
317       return elm_parent;
318     return parent;
319   }
320
321   LOG(WARNING) << "Could not find elementary parent for WebView object!";
322   return thiz->evas_object_;
323 }
324
325 void EWebView::SetURL(const GURL& url) {
326   NavigationController::LoadURLParams params(url);
327   params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
328   web_contents_->GetController().LoadURLWithParams(params);
329 }
330
331 const GURL& EWebView::GetURL() const {
332   return web_contents_->GetVisibleURL();
333 }
334
335 void EWebView::Reload() {
336   web_contents_->GetController().Reload(content::ReloadType::NORMAL, true);
337 }
338
339 void EWebView::ReloadBypassingCache() {
340   web_contents_->GetController().Reload(content::ReloadType::BYPASSING_CACHE,
341                                         true);
342 }
343
344 Eina_Bool EWebView::CanGoBack() {
345   return web_contents_->GetController().CanGoBack();
346 }
347
348 Eina_Bool EWebView::CanGoForward() {
349   return web_contents_->GetController().CanGoForward();
350 }
351
352 Eina_Bool EWebView::HasFocus() const {
353   return elm_object_focus_get(native_view_);
354 }
355
356 Eina_Bool EWebView::GoBack() {
357   if (!web_contents_->GetController().CanGoBack())
358     return EINA_FALSE;
359
360   web_contents_->GetController().GoBack();
361   return EINA_TRUE;
362 }
363
364 Eina_Bool EWebView::GoForward() {
365   if (!web_contents_->GetController().CanGoForward())
366     return EINA_FALSE;
367
368   web_contents_->GetController().GoForward();
369   return EINA_TRUE;
370 }
371
372 void EWebView::Stop() {
373   if (web_contents_->IsLoading())
374     web_contents_->Stop();
375 }
376
377 void EWebView::Suspend() {
378   CHECK(web_contents_);
379   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
380   RenderFrameHost* rfh = web_contents_->GetMainFrame();
381   CHECK(rvh);
382   CHECK(rfh);
383 #if !defined(EWK_BRINGUP)  // FIXME: m69 bringup
384   rfh->BlockRequestsForFrame();
385 #endif
386 #if 0
387   content::BrowserThread::PostTask(
388       content::BrowserThread::IO, FROM_HERE,
389       base::Bind(&content::ResourceDispatcherHost::BlockRequestsForFrameFromUI,
390                  rfh));
391
392   if (rvh)
393     rvh->Send(new EwkViewMsg_SuspendScheduledTask(rvh->GetRoutingID()));
394 #endif
395 }
396
397 void EWebView::Resume() {
398   CHECK(web_contents_);
399   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
400   RenderFrameHost* rfh = web_contents_->GetMainFrame();
401   CHECK(rvh);
402   CHECK(rfh);
403 #if !defined(EWK_BRINGUP)  // FIXME: m69 bringup
404   rfh->ResumeBlockedRequestsForFrame();
405 #endif
406 #if 0
407   content::BrowserThread::PostTask(
408       content::BrowserThread::IO, FROM_HERE,
409       base::Bind(
410           &content::ResourceDispatcherHost::ResumeBlockedRequestsForFrameFromUI,
411           rfh));
412
413   if (rvh)
414     rvh->Send(new EwkViewMsg_ResumeScheduledTasks(rvh->GetRoutingID()));
415 #endif
416 }
417
418 double EWebView::GetTextZoomFactor() const {
419   if (text_zoom_factor_ < 0.0)
420     return -1.0;
421
422   return text_zoom_factor_;
423 }
424
425 void EWebView::SetTextZoomFactor(double text_zoom_factor) {
426   if (text_zoom_factor_ == text_zoom_factor || text_zoom_factor < 0.0)
427     return;
428
429   text_zoom_factor_ = text_zoom_factor;
430   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
431   if (!render_view_host)
432     return;
433
434   render_view_host->Send(new ViewMsg_SetTextZoomFactor(
435       render_view_host->GetRoutingID(), text_zoom_factor));
436 }
437
438 double EWebView::GetPageZoomFactor() const {
439   return content::ZoomLevelToZoomFactor(
440       content::HostZoomMap::GetZoomLevel(web_contents_.get()));
441 }
442
443 void EWebView::SetPageZoomFactor(double page_zoom_factor) {
444   content::HostZoomMap::SetZoomLevel(
445       web_contents_.get(), content::ZoomFactorToZoomLevel(page_zoom_factor));
446 }
447
448 void EWebView::ExecuteEditCommand(const char* command, const char* value) {
449   EINA_SAFETY_ON_NULL_RETURN(command);
450
451   value = (value == NULL) ? "" : value;
452
453   RenderWidgetHostImpl* rwhi = static_cast<RenderWidgetHostImpl*>(
454       web_contents_->GetRenderViewHost()->GetWidget());
455
456 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
457   // This is moved to mojo in upstream. Change it.
458   // https://chromium-review.googlesource.com/c/chromium/src/+/541036
459   rwhi->ExecuteEditCommand(command, value);
460 #endif
461
462   // This is workaround for rich text toolbar buttons in email application
463   if (!strcmp(command, "InsertOrderedList") ||
464       !strcmp(command, "InsertUnorderedList") ||
465       !strcmp(command, "AlignCenter") || !strcmp(command, "AlignJustified") ||
466       !strcmp(command, "AlignLeft") || !strcmp(command, "AlignRight")) {
467     QuerySelectionStyle();
468   }
469 }
470
471 void EWebView::SetOrientation(int orientation) {
472   // For backward compatibility, a value in range of [0, 360] is used
473   // instead of [-90, 180] because the class gfx::Display, containing
474   // orientaion value, supports the former range.
475   if (orientation == -90)
476     orientation = 270;
477   screen_orientation_ = orientation;
478
479   if (screen_orientation_ == 0 || screen_orientation_ == 90 ||
480       screen_orientation_ == 180 || screen_orientation_ == 270) {
481     GetWebContentsViewEfl()->SetOrientation(screen_orientation_);
482
483     // workaround for platform issue not resizing popup after rotation
484     // this should be removed when when proper fix will be applied for platorm.
485
486     int width = 0;
487     int height = 0;
488     const Ecore_Evas* ee =
489         ecore_evas_ecore_evas_get(evas_object_evas_get(evas_object_));
490     ecore_evas_screen_geometry_get(ee, nullptr, nullptr, &width, &height);
491     if (orientation == 90 || orientation == 270)
492       std::swap(width, height);
493
494     if (context_menu_)
495       context_menu_->SetPopupSize(width, height);
496     if (inputPicker_)
497       inputPicker_->SetPopupSize(width, height);
498     if (popup_controller_)
499       popup_controller_->SetPopupSize(width, height);
500     if (JavaScriptDialogManagerEfl* dialogMG = GetJavaScriptDialogManagerEfl())
501       dialogMG->SetPopupSize(width, height);
502     if (popupPicker_)
503       popup_picker_resize(popupPicker_, width, height);
504   }
505 }
506
507 int EWebView::GetOrientation() {
508   return screen_orientation_;
509 }
510
511 void EWebView::Show() {
512   evas_object_show(native_view_);
513   web_contents_->WasShown();
514 }
515
516 void EWebView::Hide() {
517   evas_object_hide(native_view_);
518   web_contents_->WasHidden();
519 }
520
521 void EWebView::InvokeAuthCallback(LoginDelegateEfl* login_delegate,
522                                   const GURL& url,
523                                   const std::string& realm) {
524   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
525
526   auth_challenge_.reset(new _Ewk_Auth_Challenge(login_delegate, url, realm));
527   SmartCallback<EWebViewCallbacks::AuthChallenge>().call(auth_challenge_.get());
528
529   if (!auth_challenge_->is_decided && !auth_challenge_->is_suspended) {
530     auth_challenge_->is_decided = true;
531     auth_challenge_->login_delegate->Cancel();
532   }
533 }
534
535 void EWebView::InvokePolicyResponseCallback(
536     _Ewk_Policy_Decision* policy_decision) {
537   SmartCallback<EWebViewCallbacks::PolicyResponseDecide>().call(
538       policy_decision);
539
540   if (policy_decision->isSuspended())
541     return;
542
543   if (!policy_decision->isDecided())
544     policy_decision->Use();
545
546   delete policy_decision;
547 }
548
549 void EWebView::InvokePolicyNavigationCallback(
550     RenderViewHost* rvh,
551     const NavigationPolicyParams params,
552     bool* handled) {
553   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
554
555   SmartCallback<EWebViewCallbacks::SaveSessionData>().call();
556
557   std::unique_ptr<_Ewk_Policy_Decision> policy_decision(
558       new _Ewk_Policy_Decision(params, rvh));
559
560   SmartCallback<EWebViewCallbacks::NavigationPolicyDecision>().call(
561       policy_decision.get());
562
563   CHECK(!policy_decision->isSuspended());
564
565   // TODO: Navigation can't be suspended
566   // this aproach is synchronous and requires immediate response
567   // Maybe there is different approach (like resource throttle response
568   // mechanism) that allows us to
569   // suspend navigation
570   if (!policy_decision->isDecided())
571     policy_decision->Use();
572
573   *handled = policy_decision->GetNavigationPolicyHandler()->GetDecision() ==
574              NavigationPolicyHandlerEfl::Handled;
575 }
576
577 void EWebView::HandleTouchEvents(Ewk_Touch_Event_Type type,
578                                  const Eina_List* points,
579                                  const Evas_Modifier* modifiers) {
580   const Eina_List* l;
581   void* data;
582   EINA_LIST_FOREACH(points, l, data) {
583     const Ewk_Touch_Point* point = static_cast<Ewk_Touch_Point*>(data);
584     if (point->state == EVAS_TOUCH_POINT_STILL) {
585       // Chromium doesn't expect (and doesn't like) these events.
586       continue;
587     }
588     if (rwhv()) {
589       Evas_Coord_Point pt;
590       pt.x = point->x;
591       pt.y = point->y;
592       ui::TouchEvent touch_event =
593           MakeTouchEvent(pt, point->state, point->id, evas_object());
594       rwhv()->HandleTouchEvent(&touch_event);
595     }
596   }
597 }
598
599 content::WebContentsViewEfl* EWebView::GetWebContentsViewEfl() const {
600   WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
601   return static_cast<WebContentsViewEfl*>(wc->GetView());
602 }
603
604 bool EWebView::TouchEventsEnabled() const {
605   return touch_events_enabled_;
606 }
607
608 // TODO: Touch events use the same mouse events in EFL API.
609 // Figure out how to distinguish touch and mouse events on touch&mice devices.
610 // Currently mouse and touch support is mutually exclusive.
611 void EWebView::SetTouchEventsEnabled(bool enabled) {
612   if (touch_events_enabled_ == enabled)
613     return;
614
615   touch_events_enabled_ = enabled;
616   GetWebContentsViewEfl()->SetTouchEventsEnabled(enabled);
617
618 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
619   // there is no flag touch_enabled in web preferences
620   GetSettings()->getPreferences().touch_enabled = enabled;
621   GetSettings()->getPreferences().double_tap_to_zoom_enabled = enabled;
622 #endif
623   GetSettings()->getPreferences().editing_behavior =
624       enabled ? content::EDITING_BEHAVIOR_ANDROID
625               : content::EDITING_BEHAVIOR_UNIX;
626   UpdateWebKitPreferences();
627 }
628
629 bool EWebView::MouseEventsEnabled() const {
630   return mouse_events_enabled_;
631 }
632
633 void EWebView::SetMouseEventsEnabled(bool enabled) {
634   if (mouse_events_enabled_ == enabled)
635     return;
636
637   mouse_events_enabled_ = enabled;
638   GetWebContentsViewEfl()->SetTouchEventsEnabled(!enabled);
639 }
640
641 namespace {
642
643 class JavaScriptCallbackDetails {
644  public:
645   JavaScriptCallbackDetails(Ewk_View_Script_Execute_Callback callback_func,
646                             void* user_data,
647                             Evas_Object* view)
648       : callback_func_(callback_func), user_data_(user_data), view_(view) {}
649
650   Ewk_View_Script_Execute_Callback callback_func_;
651   void* user_data_;
652   Evas_Object* view_;
653 };
654
655 void JavaScriptComplete(JavaScriptCallbackDetails* script_callback_data,
656                         const base::Value* result) {
657   if (!script_callback_data->callback_func_)
658     return;
659
660   std::string return_string;
661   result->GetAsString(&return_string);
662   script_callback_data->callback_func_(script_callback_data->view_,
663                                        return_string.c_str(),
664                                        script_callback_data->user_data_);
665 }
666
667 }  // namespace
668
669 bool EWebView::ExecuteJavaScript(const char* script,
670                                  Ewk_View_Script_Execute_Callback callback,
671                                  void* userdata) {
672   if (!script)
673     return false;
674
675   if (!web_contents_delegate_)  // question, can I remove this check?
676     return false;
677
678   if (!web_contents_)
679     return false;
680
681   RenderFrameHost* render_frame_host = web_contents_->GetMainFrame();
682   if (!render_frame_host)
683     return false;
684
685   // Note: M37. Execute JavaScript, |script| with
686   // |RenderFrameHost::ExecuteJavaScript|.
687   // @see also https://codereview.chromium.org/188893005 for more details.
688   base::string16 js_script;
689   base::UTF8ToUTF16(script, strlen(script), &js_script);
690   if (callback) {
691 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
692     JavaScriptCallbackDetails* script_callback_data =
693         new JavaScriptCallbackDetails(callback, userdata, evas_object_);
694     // In M47, it isn't possible anymore to execute javascript in the generic
695     // case. We need to call ExecuteJavaScriptForTests to keep the behaviour
696     // unchanged @see https://codereview.chromium.org/1123783002
697     render_frame_host->ExecuteJavaScriptWithUserGestureForTests(
698         js_script,
699         base::Bind(&JavaScriptComplete, base::Owned(script_callback_data)));
700 #endif
701   } else {
702     // We use ExecuteJavaScriptWithUserGestureForTests instead of
703     // ExecuteJavaScript because
704     // ExecuteJavaScriptWithUserGestureForTests sets user_gesture to true. This
705     // was the
706     // behaviour is m34, and we want to keep it that way.
707     render_frame_host->ExecuteJavaScriptWithUserGestureForTests(js_script);
708   }
709
710   return true;
711 }
712
713 bool EWebView::SetUserAgent(const char* userAgent) {
714   const content::NavigationController& controller =
715       web_contents_->GetController();
716   bool override = userAgent && strlen(userAgent);
717   for (int i = 0; i < controller.GetEntryCount(); ++i)
718     controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(override);
719   // TODO: Check if override_in_new_tabs has to be true.
720   web_contents_->SetUserAgentOverride(override ? userAgent : std::string(),
721                                       false /* override_in_new_tabs */);
722   return true;
723 }
724
725 bool EWebView::SetUserAgentAppName(const char* application_name) {
726   EflWebView::VersionInfo::GetInstance()->SetProductName(
727       application_name ? application_name : "");
728
729   return true;
730 }
731
732 bool EWebView::SetPrivateBrowsing(bool incognito) {
733   if (context_->GetImpl()->browser_context()->IsOffTheRecord() == incognito)
734     return false;
735
736   GURL url = web_contents_->GetVisibleURL();
737   if (old_context_.get()) {
738     DCHECK(!incognito);
739     web_contents_.reset();
740     web_contents_delegate_.reset();
741     Ewk_Context::Delete(context_.get());
742     context_ = old_context_;
743     old_context_ = NULL;
744   } else {
745     if (incognito) {
746       old_context_ = context_;
747     }
748     context_ = Ewk_Context::Create(incognito);
749   }
750
751   InitializeContent();
752   SetURL(url);
753   return true;
754 }
755
756 bool EWebView::GetPrivateBrowsing() const {
757   return context_->GetImpl()->browser_context()->IsOffTheRecord();
758 }
759
760 void EWebView::set_magnifier(bool status) {
761   rwhv()->set_magnifier(status);
762 }
763
764 const char* EWebView::GetUserAgent() const {
765   if (!web_contents_->GetUserAgentOverride().empty())
766     user_agent_ = web_contents_->GetUserAgentOverride();
767   else
768     user_agent_ = content::GetContentClientExport()->GetUserAgent();
769   return user_agent_.c_str();
770 }
771
772 const char* EWebView::GetUserAgentAppName() const {
773   user_agent_app_name_ = EflWebView::VersionInfo::GetInstance()->Name();
774   return user_agent_app_name_.c_str();
775 }
776
777 const char* EWebView::GetSelectedText() const {
778   if (!rwhv())
779     return "";
780
781   return base::UTF16ToUTF8(rwhv()->GetSelectedText()).c_str();
782 }
783
784 _Ewk_Frame* EWebView::GetMainFrame() {
785   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
786
787   if (!frame_.get()) {
788     RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
789
790     if (render_view_host)
791       frame_.reset(new _Ewk_Frame(render_view_host->GetMainFrame()));
792   }
793
794   return frame_.get();
795 }
796
797 void EWebView::UpdateWebKitPreferences() {
798   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
799
800   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
801   if (!render_view_host)
802     return;
803
804   web_contents_delegate_->OnUpdateSettings(settings_.get());
805   render_view_host->UpdateWebkitPreferences(settings_->getPreferences());
806
807   UpdateWebkitPreferencesEfl(render_view_host);
808 }
809
810 void EWebView::UpdateWebkitPreferencesEfl(RenderViewHost* render_view_host) {
811   DCHECK(render_view_host);
812
813   IPC::Message* message = new EwkSettingsMsg_UpdateWebKitPreferencesEfl(
814       render_view_host->GetRoutingID(), settings_->getPreferencesEfl());
815
816   if (render_view_host->IsRenderViewLive()) {
817     render_view_host->Send(message);
818   } else {
819     delayed_messages_.push_back(message);
820   }
821 }
822
823 void EWebView::SetContentSecurityPolicy(const char* policy,
824                                         Ewk_CSP_Header_Type type) {
825   web_contents_delegate_->SetContentSecurityPolicy(
826       (policy ? policy : std::string()), type);
827 }
828
829 void EWebView::LoadHTMLString(const char* html,
830                               const char* base_uri,
831                               const char* unreachable_uri) {
832   LoadData(html, std::string::npos, NULL, NULL, base_uri, unreachable_uri);
833 }
834
835 void EWebView::LoadPlainTextString(const char* plain_text) {
836   LoadData(plain_text, std::string::npos, "text/plain", NULL, NULL, NULL);
837 }
838
839 void EWebView::LoadData(const char* data,
840                         size_t size,
841                         const char* mime_type,
842                         const char* encoding,
843                         const char* base_uri,
844                         const char* unreachable_uri) {
845   SetDefaultStringIfNull(mime_type, "text/html");
846   SetDefaultStringIfNull(encoding, "utf-8");
847   SetDefaultStringIfNull(base_uri, "about:blank");  // Webkit2 compatible
848   SetDefaultStringIfNull(unreachable_uri, "");
849
850   std::string str_data = data;
851
852   if (size < str_data.length())
853     str_data = str_data.substr(0, size);
854
855   std::string url_str("data:");
856   url_str.append(mime_type);
857   url_str.append(";charset=");
858   url_str.append(encoding);
859   url_str.append(",");
860   url_str.append(str_data);
861
862   NavigationController::LoadURLParams data_params(GURL(url_str.c_str()));
863
864   data_params.base_url_for_data_url = GURL(base_uri);
865   data_params.virtual_url_for_data_url = GURL(unreachable_uri);
866
867   data_params.load_type = NavigationController::LOAD_TYPE_DATA;
868   data_params.should_replace_current_entry = false;
869   data_params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
870   web_contents_->GetController().LoadURLWithParams(data_params);
871 }
872
873 void EWebView::InvokeLoadError(const GURL& url,
874                                int error_code,
875                                const std::string& error_description,
876                                bool is_main_frame) {
877   if (!is_main_frame)
878     return;
879
880   std::unique_ptr<_Ewk_Error> err(
881       new _Ewk_Error(error_code, url.possibly_invalid_spec().c_str(),
882                      error_description.c_str()));
883
884   SmartCallback<EWebViewCallbacks::LoadError>().call(err.get());
885 }
886
887 void EWebView::ShowPopupMenu(const std::vector<content::MenuItem>& items,
888                              int selectedIndex,
889                              bool multiple) {
890   // Request form navigation information as early as possible,
891   // given that is renderer will ping-back with actual requested data.
892   RenderFrameHostImpl* render_frame_host =
893       static_cast<RenderFrameHostImpl*>(web_contents_->GetMainFrame());
894   if (render_frame_host)
895     render_frame_host->Send(new EwkFrameMsg_RequestSelectCollectionInformation(
896         render_frame_host->GetRoutingID()));
897
898   Eina_List* popupItems = 0;
899   const size_t size = items.size();
900   for (size_t i = 0; i < size; ++i) {
901     popupItems = eina_list_append(popupItems, new Popup_Menu_Item(items[i]));
902   }
903
904   ReleasePopupMenuList();
905   popupMenuItems_ = popupItems;
906
907   if (popupPicker_ && FormIsNavigating()) {
908     popupPicker_->multiSelect = multiple;
909     PopupMenuUpdate(popupMenuItems_, selectedIndex);
910     SetFormIsNavigating(false);
911     return;
912   }
913
914   if (popupPicker_)
915     popup_picker_del(popupPicker_);
916   popupPicker_ = 0;
917
918   if (multiple)
919     popupPicker_ =
920         popup_picker_new(this, evas_object(), popupMenuItems_, 0, multiple);
921   else
922     popupPicker_ = popup_picker_new(this, evas_object(), popupMenuItems_,
923                                     selectedIndex, multiple);
924
925   popup_picker_buttons_update(popupPicker_, formNavigation_.position,
926                               formNavigation_.count, false);
927 }
928
929 Eina_Bool EWebView::HidePopupMenu() {
930   if (!popupPicker_)
931     return false;
932
933   if (FormIsNavigating())
934     return true;
935
936   popup_picker_del(popupPicker_);
937   popupPicker_ = 0;
938   return true;
939 }
940
941 void EWebView::UpdateFormNavigation(int formElementCount,
942                                     int currentNodeIndex,
943                                     bool prevState,
944                                     bool nextState) {
945   formNavigation_.count = formElementCount;
946   formNavigation_.position = currentNodeIndex;
947   formNavigation_.prevState = prevState;
948   formNavigation_.nextState = nextState;
949 }
950
951 bool EWebView::IsSelectPickerShown() const {
952   return (popupPicker_ != NULL);
953 }
954
955 void EWebView::CloseSelectPicker() {
956   listClosed(popupPicker_, 0, 0, 0);
957 }
958
959 void EWebView::SetFormIsNavigating(bool formIsNavigating) {
960   formIsNavigating_ = formIsNavigating;
961 }
962
963 Eina_Bool EWebView::PopupMenuUpdate(Eina_List* items, int selectedIndex) {
964   if (!popupPicker_)
965     return false;
966
967   popup_picker_update(evas_object(), popupPicker_, items, selectedIndex);
968   popup_picker_buttons_update(popupPicker_, formNavigation_.position,
969                               formNavigation_.count, false);
970   return true;
971 }
972
973 void EWebView::FormNavigate(bool direction) {
974   RenderFrameHostImpl* render_frame_host =
975       static_cast<RenderFrameHostImpl*>(web_contents_->GetMainFrame());
976   if (!render_frame_host)
977     return;
978
979   popup_picker_buttons_update(popupPicker_, formNavigation_.position,
980                               formNavigation_.count, true);
981
982   if ((direction && formNavigation_.nextState) ||
983       (!direction && formNavigation_.prevState))
984     SetFormIsNavigating(true);
985
986   listClosed(popupPicker_, 0, 0, 0);
987   render_frame_host->Send(new EwkFrameMsg_MoveToNextOrPreviousSelectElement(
988       render_frame_host->GetRoutingID(), direction));
989 }
990
991 Eina_Bool EWebView::DidSelectPopupMenuItem(int selectedIndex) {
992   RenderFrameHostImpl* render_frame_host =
993       static_cast<RenderFrameHostImpl*>(web_contents_->GetMainFrame());
994   if (!render_frame_host)
995     return false;
996
997   if (!popupMenuItems_)
998     return false;
999
1000   // When user select empty space then no index is selected, so selectedIndex
1001   // value is -1
1002   // In that case we should call valueChanged() with -1 index.That in turn call
1003   // popupDidHide()
1004   // in didChangeSelectedIndex() for reseting the value of m_popupIsVisible in
1005   // RenderMenuList.
1006   if (selectedIndex != -1 &&
1007       selectedIndex >= (int)eina_list_count(popupMenuItems_))
1008     return false;
1009
1010   // In order to reuse RenderFrameHostImpl::DidSelectPopupMenuItems() method in
1011   // Android,
1012   // put selectedIndex into std::vector<int>.
1013   std::vector<int> selectedIndices;
1014   selectedIndices.push_back(selectedIndex);
1015 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1016   render_frame_host->DidSelectPopupMenuItems(selectedIndices);
1017 #endif
1018   return true;
1019 }
1020
1021 Eina_Bool EWebView::DidMultipleSelectPopupMenuItem(
1022     std::vector<int>& selectedIndices) {
1023   RenderFrameHostImpl* render_frame_host =
1024       static_cast<RenderFrameHostImpl*>(web_contents_->GetMainFrame());
1025   if (!render_frame_host)
1026     return false;
1027
1028   if (!popupMenuItems_)
1029     return false;
1030 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1031   render_frame_host->DidSelectPopupMenuItems(selectedIndices);
1032 #endif
1033   return true;
1034 }
1035
1036 Eina_Bool EWebView::PopupMenuClose() {
1037 // DJKim : FIXME
1038 #if 0
1039   if (!impl->popupMenuProxy)
1040     return false;
1041
1042   impl->popupMenuProxy = 0;
1043 #endif
1044   HidePopupMenu();
1045
1046   if (!popupMenuItems_)
1047     return false;
1048
1049   void* item;
1050   EINA_LIST_FREE(popupMenuItems_, item)
1051   delete static_cast<Popup_Menu_Item*>(item);
1052   popupMenuItems_ = 0;
1053
1054   RenderFrameHostImpl* render_frame_host =
1055       static_cast<RenderFrameHostImpl*>(web_contents_->GetMainFrame());
1056   if (!render_frame_host)
1057     return false;
1058 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1059   render_frame_host->DidCancelPopupMenu();
1060 #endif
1061   return true;
1062 }
1063
1064 void EWebView::HandleLongPressGesture(
1065     const content::ContextMenuParams& params) {
1066   // This menu is created in renderer process and it does not now anything about
1067   // view scaling factor and it has another calling sequence, so coordinates is
1068   // not updated.
1069   content::ContextMenuParams convertedParams = params;
1070   gfx::Point convertedPoint =
1071       rwhv()->ConvertPointInViewPix(gfx::Point(params.x, params.y));
1072   convertedParams.x = convertedPoint.x();
1073   convertedParams.y = convertedPoint.y();
1074
1075   Evas_Coord x, y;
1076   evas_object_geometry_get(evas_object(), &x, &y, 0, 0);
1077   convertedParams.x += x;
1078   convertedParams.y += y;
1079
1080   if (GetSelectionController() && GetSelectionController()->GetLongPressed()) {
1081     bool show_context_menu_now =
1082         !GetSelectionController()->HandleLongPressEvent(convertedPoint,
1083                                                         convertedParams);
1084     if (show_context_menu_now)
1085       ShowContextMenuInternal(convertedParams);
1086   }
1087 }
1088
1089 void EWebView::ShowContextMenu(const content::ContextMenuParams& params) {
1090   // This menu is created in renderer process and it does not now anything about
1091   // view scaling factor and it has another calling sequence, so coordinates is
1092   // not updated.
1093   content::ContextMenuParams convertedParams = params;
1094   gfx::Point convertedPoint =
1095       rwhv()->ConvertPointInViewPix(gfx::Point(params.x, params.y));
1096   convertedParams.x = convertedPoint.x();
1097   convertedParams.y = convertedPoint.y();
1098
1099   Evas_Coord x, y;
1100   evas_object_geometry_get(evas_object(), &x, &y, 0, 0);
1101   convertedParams.x += x;
1102   convertedParams.y += y;
1103
1104   context_menu_position_ = gfx::Point(convertedParams.x, convertedParams.y);
1105
1106   ShowContextMenuInternal(convertedParams);
1107 }
1108
1109 void EWebView::ShowContextMenuInternal(
1110     const content::ContextMenuParams& params) {
1111   context_menu_.reset(
1112       new content::ContextMenuControllerEfl(this, *web_contents_.get()));
1113   if (!context_menu_->PopulateAndShowContextMenu(params)) {
1114     context_menu_.reset();
1115     if (GetSelectionController())
1116       GetSelectionController()->HideHandles();
1117   }
1118 }
1119
1120 void EWebView::CancelContextMenu(int request_id) {
1121   if (context_menu_)
1122     context_menu_->HideContextMenu();
1123 }
1124
1125 void EWebView::Find(const char* text, Ewk_Find_Options find_options) {
1126   base::string16 find_text = base::UTF8ToUTF16(text);
1127   bool find_next = (previous_text_ == find_text);
1128
1129   if (!find_next) {
1130     current_find_request_id_ = find_request_id_counter_++;
1131     previous_text_ = find_text;
1132   }
1133
1134   blink::WebFindOptions web_find_options;
1135   web_find_options.forward = !(find_options & EWK_FIND_OPTIONS_BACKWARDS);
1136   web_find_options.match_case =
1137       !(find_options & EWK_FIND_OPTIONS_CASE_INSENSITIVE);
1138   web_find_options.find_next = find_next;
1139
1140   web_contents_->Find(current_find_request_id_, find_text, web_find_options);
1141 }
1142
1143 void EWebView::SetScale(double scale_factor, int x, int y) {
1144   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1145   // Do not cache |scale_factor| here as it may be discarded by Blink's
1146   // minimumPageScaleFactor and maximumPageScaleFactor.
1147   // |scale_factor| is cached as responde to DidChangePageScaleFactor.
1148   render_view_host->Send(new EwkViewMsg_Scale(render_view_host->GetRoutingID(),
1149                                               scale_factor, x, y));
1150 }
1151
1152 bool EWebView::GetScrollPosition(int* x, int* y) const {
1153   DCHECK(x);
1154   DCHECK(y);
1155
1156   if (scroll_detector_->IsScrollOffsetChanged()) {
1157     *x = previous_scroll_position_.x();
1158     *y = previous_scroll_position_.y();
1159   } else {
1160     const gfx::Vector2d scroll_position =
1161         scroll_detector_->GetLastScrollPosition();
1162     *x = scroll_position.x();
1163     *y = scroll_position.y();
1164   }
1165   return true;
1166 }
1167
1168 void EWebView::SetScroll(int x, int y) {
1169   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1170   if (!render_view_host)
1171     return;
1172
1173   int maxX, maxY;
1174   GetScrollSize(&maxX, &maxY);
1175   previous_scroll_position_.set_x(std::min(std::max(x, 0), maxX));
1176   previous_scroll_position_.set_y(std::min(std::max(y, 0), maxY));
1177
1178   scroll_detector_->SetScrollOffsetChanged();
1179
1180   render_view_host->Send(
1181       new EwkViewMsg_SetScroll(render_view_host->GetRoutingID(), x, y));
1182 }
1183
1184 void EWebView::UseSettingsFont() {
1185   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1186   if (render_view_host)
1187     render_view_host->Send(
1188         new EwkViewMsg_UseSettingsFont(render_view_host->GetRoutingID()));
1189 }
1190
1191 void EWebView::DidChangeContentsSize(int width, int height) {
1192   contents_size_ = gfx::Size(width, height);
1193   SmartCallback<EWebViewCallbacks::ContentsSizeChanged>().call();
1194 }
1195
1196 const Eina_Rectangle EWebView::GetContentsSize() const {
1197   Eina_Rectangle rect;
1198   EINA_RECTANGLE_SET(&rect, 0, 0, contents_size_.width(),
1199                      contents_size_.height());
1200   return rect;
1201 }
1202
1203 void EWebView::GetScrollSize(int* width, int* height) {
1204   if (width)
1205     *width = 0;
1206   if (height)
1207     *height = 0;
1208
1209   Eina_Rectangle last_view_port =
1210       WebViewDelegateEwk::GetInstance().GetLastUsedViewPortArea(evas_object());
1211   int scaled_content_width =
1212       static_cast<int>(contents_size_.width() * page_scale_factor_);
1213   int scaled_content_height =
1214       static_cast<int>(contents_size_.height() * page_scale_factor_);
1215
1216   if (width && scaled_content_width > last_view_port.w)
1217     *width = scaled_content_width - last_view_port.w;
1218   if (height && scaled_content_height > last_view_port.h)
1219     *height = scaled_content_height - last_view_port.h;
1220 }
1221
1222 void EWebView::MoveCaret(const gfx::Point& point) {
1223   if (rwhv())
1224     rwhv()->MoveCaret(point);
1225 }
1226
1227 void EWebView::QuerySelectionStyle() {
1228   if (GetSettings()->textStyleStateState()) {
1229     RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1230     render_view_host->Send(
1231         new EwkViewMsg_GetSelectionStyle(render_view_host->GetRoutingID()));
1232   }
1233 }
1234
1235 void EWebView::OnQuerySelectionStyleReply(const SelectionStylePrams& params) {
1236   gfx::Rect left_rect, right_rect;
1237   if (GetSelectionController()) {
1238     GetSelectionController()->GetSelectionBounds(&left_rect, &right_rect);
1239     _Ewk_Text_Style style_data(params, left_rect.origin(),
1240                                right_rect.bottom_right());
1241     SmartCallback<EWebViewCallbacks::TextStyleState>().call(&style_data);
1242   }
1243 }
1244
1245 SelectionControllerEfl* EWebView::GetSelectionController() const {
1246   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1247   RenderWidgetHostViewEfl* view = static_cast<RenderWidgetHostViewEfl*>(
1248       render_view_host->GetWidget()->GetView());
1249   return view ? view->GetSelectionController() : 0;
1250 }
1251
1252 void EWebView::SelectLinkText(const gfx::Point& touch_point) {
1253 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1254   float device_scale_factor =
1255       display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1256   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1257   render_view_host->Send(new ViewMsg_SelectLinkText(
1258       render_view_host->GetRoutingID(),
1259       gfx::Point(touch_point.x() / device_scale_factor,
1260                  touch_point.y() / device_scale_factor)));
1261 #endif
1262 }
1263
1264 bool EWebView::GetSelectionRange(Eina_Rectangle* left_rect,
1265                                  Eina_Rectangle* right_rect) {
1266   if (left_rect && right_rect) {
1267     gfx::Rect left, right;
1268     if (GetSelectionController()) {
1269       GetSelectionController()->GetSelectionBounds(&left, &right);
1270       GetEinaRectFromGfxRect(left, left_rect);
1271       GetEinaRectFromGfxRect(right, right_rect);
1272       return true;
1273     }
1274   }
1275   return false;
1276 }
1277
1278 Eina_Bool EWebView::ClearSelection() {
1279   if (!rwhv())
1280     return EINA_FALSE;
1281
1282   ResetContextMenuController();
1283   rwhv()->SelectionChanged(base::string16(), 0, gfx::Range());
1284
1285   if (GetSelectionController())
1286     return GetSelectionController()->ClearSelectionViaEWebView();
1287
1288   return EINA_FALSE;
1289 }
1290
1291 _Ewk_Hit_Test* EWebView::RequestHitTestDataAt(int x,
1292                                               int y,
1293                                               Ewk_Hit_Test_Mode mode) {
1294   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1295
1296   int view_x, view_y;
1297   EvasToBlinkCords(x, y, &view_x, &view_y);
1298
1299   return RequestHitTestDataAtBlinkCoords(view_x, view_y, mode);
1300 }
1301
1302 Eina_Bool EWebView::AsyncRequestHitTestDataAt(
1303     int x,
1304     int y,
1305     Ewk_Hit_Test_Mode mode,
1306     Ewk_View_Hit_Test_Request_Callback callback,
1307     void* user_data) {
1308   int view_x, view_y;
1309   EvasToBlinkCords(x, y, &view_x, &view_y);
1310   return AsyncRequestHitTestDataAtBlinkCords(
1311       view_x, view_y, mode,
1312       new WebViewAsyncRequestHitTestDataUserCallback(x, y, mode, callback,
1313                                                      user_data));
1314 }
1315
1316 Eina_Bool EWebView::AsyncRequestHitTestDataAtBlinkCords(
1317     int x,
1318     int y,
1319     Ewk_Hit_Test_Mode mode,
1320     Ewk_View_Hit_Test_Request_Callback callback,
1321     void* user_data) {
1322   return AsyncRequestHitTestDataAtBlinkCords(
1323       x, y, mode,
1324       new WebViewAsyncRequestHitTestDataUserCallback(x, y, mode, callback,
1325                                                      user_data));
1326 }
1327
1328 Eina_Bool EWebView::AsyncRequestHitTestDataAtBlinkCords(
1329     int x,
1330     int y,
1331     Ewk_Hit_Test_Mode mode,
1332     WebViewAsyncRequestHitTestDataCallback* cb) {
1333   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1334   DCHECK(cb);
1335
1336   static int64_t request_id = 1;
1337
1338   if (cb) {
1339     RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1340     DCHECK(render_view_host);
1341
1342     if (render_view_host) {
1343       render_view_host->Send(new EwkViewMsg_DoHitTestAsync(
1344           render_view_host->GetRoutingID(), x, y, mode, request_id));
1345       hit_test_callback_[request_id] = cb;
1346       ++request_id;
1347       return EINA_TRUE;
1348     }
1349   }
1350
1351   // if failed we delete callback as it is not needed anymore
1352   delete cb;
1353   return EINA_FALSE;
1354 }
1355
1356 void EWebView::DispatchAsyncHitTestData(const Hit_Test_Params& params,
1357                                         int64_t request_id) {
1358   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1359
1360   std::map<int64_t, WebViewAsyncRequestHitTestDataCallback*>::iterator it =
1361       hit_test_callback_.find(request_id);
1362
1363   if (it == hit_test_callback_.end())
1364     return;
1365   std::unique_ptr<_Ewk_Hit_Test> hit_test(new _Ewk_Hit_Test(params));
1366
1367   it->second->Run(hit_test.get(), this);
1368   delete it->second;
1369   hit_test_callback_.erase(it);
1370 }
1371
1372 _Ewk_Hit_Test* EWebView::RequestHitTestDataAtBlinkCoords(
1373     int x,
1374     int y,
1375     Ewk_Hit_Test_Mode mode) {
1376   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1377
1378   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1379   DCHECK(render_view_host);
1380
1381   if (render_view_host) {
1382     // We wait on UI thread till hit test data is updated.
1383     render_view_host->Send(
1384         new EwkViewMsg_DoHitTest(render_view_host->GetRoutingID(), x, y, mode));
1385     hit_test_completion_.Wait();
1386     return new _Ewk_Hit_Test(hit_test_params_);
1387   }
1388
1389   return NULL;
1390 }
1391
1392 void EWebView::EvasToBlinkCords(int x, int y, int* view_x, int* view_y) {
1393   DCHECK(display::Screen::GetScreen());
1394   Evas_Coord tmpX, tmpY;
1395   evas_object_geometry_get(evas_object_, &tmpX, &tmpY, NULL, NULL);
1396
1397   if (view_x) {
1398     *view_x = x - tmpX;
1399     *view_x /=
1400         display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1401   }
1402
1403   if (view_y) {
1404     *view_y = y - tmpY;
1405     *view_y /=
1406         display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
1407   }
1408 }
1409
1410 void EWebView::UpdateHitTestData(const Hit_Test_Params& params) {
1411   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1412   hit_test_params_ = params;
1413   hit_test_completion_.Signal();
1414 }
1415
1416 void EWebView::OnCopyFromBackingStore(bool success, const SkBitmap& bitmap) {}
1417
1418 void EWebView::RenderViewCreated(RenderViewHost* render_view_host) {
1419   SendDelayedMessages(render_view_host);
1420   UpdateWebkitPreferencesEfl(render_view_host);
1421   RenderWidgetHostViewEfl* view = static_cast<RenderWidgetHostViewEfl*>(
1422       render_view_host->GetWidget()->GetView());
1423   if (view)
1424     view->SetEvasHandler(evas_event_handler_);
1425
1426   if (render_view_host) {
1427     WebContents* content = WebContents::FromRenderViewHost(render_view_host);
1428     if (content) {
1429       RenderProcessHost* host = render_view_host->GetProcess();
1430       if (host)
1431         host->AddFilter(new WebViewBrowserMessageFilter(content));
1432     }
1433   }
1434 }
1435
1436 void EWebView::SetOverrideEncoding(const std::string& encoding) {
1437 // EWK_BRINGUP definition should be removed.
1438 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1439   web_contents_->SetOverrideEncoding(encoding);
1440 #endif  // !defined(EWK_BRINGUP)
1441 }
1442
1443 void EWebView::SetQuotaPermissionRequestCallback(
1444     Ewk_Quota_Permission_Request_Callback callback,
1445     void* user_data) {
1446   quota_request_callback_.Set(callback, user_data);
1447 }
1448
1449 void EWebView::InvokeQuotaPermissionRequest(
1450     _Ewk_Quota_Permission_Request* request,
1451     const content::QuotaPermissionContext::PermissionCallback& cb) {
1452   quota_permission_request_map_[request] = cb;
1453   request->setView(evas_object());
1454   if (quota_request_callback_.IsCallbackSet())
1455     quota_request_callback_.Run(evas_object(), request);
1456   else
1457     QuotaRequestCancel(request);
1458 }
1459
1460 void EWebView::QuotaRequestReply(const _Ewk_Quota_Permission_Request* request,
1461                                  bool allow) {
1462   DCHECK(quota_permission_request_map_.find(request) !=
1463          quota_permission_request_map_.end());
1464
1465   QuotaPermissionContext::PermissionCallback cb =
1466       quota_permission_request_map_[request];
1467
1468   if (allow)
1469     QuotaPermissionContextEfl::DispatchCallback(
1470         cb, QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW);
1471   else
1472     QuotaPermissionContextEfl::DispatchCallback(
1473         cb, QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW);
1474
1475   quota_permission_request_map_.erase(request);
1476   delete request;
1477 }
1478
1479 void EWebView::QuotaRequestCancel(
1480     const _Ewk_Quota_Permission_Request* request) {
1481   DCHECK(quota_permission_request_map_.find(request) !=
1482          quota_permission_request_map_.end());
1483
1484   QuotaPermissionContext::PermissionCallback cb =
1485       quota_permission_request_map_[request];
1486   QuotaPermissionContextEfl::DispatchCallback(
1487       cb, QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
1488   quota_permission_request_map_.erase(request);
1489   delete request;
1490 }
1491
1492 bool EWebView::GetLinkMagnifierEnabled() const {
1493   return web_contents_->GetMutableRendererPrefs()
1494              ->tap_multiple_targets_strategy ==
1495          TAP_MULTIPLE_TARGETS_STRATEGY_POPUP;
1496 }
1497
1498 void EWebView::SetLinkMagnifierEnabled(bool enabled) {
1499   web_contents_->GetMutableRendererPrefs()->tap_multiple_targets_strategy =
1500       enabled ? TAP_MULTIPLE_TARGETS_STRATEGY_POPUP
1501               : TAP_MULTIPLE_TARGETS_STRATEGY_NONE;
1502   web_contents_->GetRenderViewHost()->SyncRendererPrefs();
1503 }
1504
1505 bool EWebView::GetSnapshotAsync(
1506     Eina_Rectangle rect,
1507     Ewk_Web_App_Screenshot_Captured_Callback callback,
1508     void* user_data) {
1509   if (!rwhv())
1510     return false;
1511
1512   return rwhv()->RequestSnapshotAsync(rect, callback, user_data);
1513 }
1514
1515 Evas_Object* EWebView::GetSnapshot(Eina_Rectangle rect) {
1516   Evas_Object* image = NULL;
1517 #ifdef OS_TIZEN
1518   if (!rwhv() || !rwhv()->MakeCurrent())
1519     return NULL;
1520
1521   int width = rect.w;
1522   int height = rect.h;
1523
1524   if (width > rwhv()->GetViewBoundsInPix().width() - rect.x)
1525     width = rwhv()->GetViewBoundsInPix().width() - rect.x;
1526   if (height > rwhv()->GetViewBoundsInPix().height() - rect.y)
1527     height = rwhv()->GetViewBoundsInPix().height() - rect.y;
1528
1529   int x = rect.x;
1530   int y = rwhv()->GetViewBoundsInPix().height() - height + rect.y;
1531
1532   Evas_GL_API* gl_api = rwhv()->evasGlApi();
1533   DCHECK(gl_api);
1534   int size = width * height * sizeof(GLuint);
1535
1536   GLuint* tmp = (GLuint*)malloc(size);
1537   if (!tmp)
1538     return NULL;
1539
1540   GLuint* bits = (GLuint*)malloc(size);
1541   if (!bits) {
1542     free(tmp);
1543     return NULL;
1544   }
1545
1546   gl_api->glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
1547                        (GLubyte*)bits);
1548
1549   // flip the Y axis and change color format from RGBA to BGRA
1550   int i, j, idx1, idx2;
1551   GLuint d;
1552   for (j = 0; j < height; j++) {
1553     for (i = 0; i < width; i++) {
1554       idx1 = (j * width) + i;
1555       idx2 = ((height - 1) - j) * width + i;
1556       d = bits[idx1];
1557       tmp[idx2] = ((d & 0x000000ff) << 16) + ((d & 0x00ff0000) >> 16) +
1558                   ((d & 0xff00ff00));
1559     }
1560   }
1561
1562   image = evas_object_image_filled_add(rwhv()->evas());
1563   if (image) {
1564     evas_object_image_size_set(image, width, height);
1565     evas_object_image_alpha_set(image, EINA_TRUE);
1566     evas_object_image_data_copy_set(image, tmp);
1567     evas_object_resize(image, width, height);
1568   }
1569 #endif
1570   return image;
1571 }
1572
1573 void EWebView::BackForwardListClear() {
1574   content::NavigationController& controller = web_contents_->GetController();
1575
1576   int entry_count = controller.GetEntryCount();
1577   bool entry_removed = false;
1578
1579   for (int i = 0; i < entry_count; i++) {
1580     if (controller.RemoveEntryAtIndex(i)) {
1581       entry_removed = true;
1582       entry_count = controller.GetEntryCount();
1583       i--;
1584     }
1585   }
1586
1587   if (entry_removed) {
1588     back_forward_list_->ClearCache();
1589     InvokeBackForwardListChangedCallback();
1590   }
1591 }
1592
1593 _Ewk_Back_Forward_List* EWebView::GetBackForwardList() const {
1594   return back_forward_list_.get();
1595 }
1596
1597 void EWebView::InvokeBackForwardListChangedCallback() {
1598   SmartCallback<EWebViewCallbacks::BackForwardListChange>().call();
1599 }
1600
1601 _Ewk_History* EWebView::GetBackForwardHistory() const {
1602   return new _Ewk_History(web_contents_->GetController());
1603 }
1604
1605 bool EWebView::WebAppCapableGet(Ewk_Web_App_Capable_Get_Callback callback,
1606                                 void* userData) {
1607   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
1608   if (!renderViewHost) {
1609     return false;
1610   }
1611   WebApplicationCapableGetCallback* cb =
1612       new WebApplicationCapableGetCallback(callback, userData);
1613   int callbackId = web_app_capable_get_callback_map_.Add(cb);
1614   return renderViewHost->Send(new EwkViewMsg_WebAppCapableGet(
1615       renderViewHost->GetRoutingID(), callbackId));
1616 }
1617
1618 bool EWebView::WebAppIconUrlGet(Ewk_Web_App_Icon_URL_Get_Callback callback,
1619                                 void* userData) {
1620   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
1621   if (!renderViewHost) {
1622     return false;
1623   }
1624   WebApplicationIconUrlGetCallback* cb =
1625       new WebApplicationIconUrlGetCallback(callback, userData);
1626   int callbackId = web_app_icon_url_get_callback_map_.Add(cb);
1627   return renderViewHost->Send(new EwkViewMsg_WebAppIconUrlGet(
1628       renderViewHost->GetRoutingID(), callbackId));
1629 }
1630
1631 bool EWebView::WebAppIconUrlsGet(Ewk_Web_App_Icon_URLs_Get_Callback callback,
1632                                  void* userData) {
1633   RenderViewHost* renderViewHost = web_contents_->GetRenderViewHost();
1634   if (!renderViewHost) {
1635     return false;
1636   }
1637   WebApplicationIconUrlsGetCallback* cb =
1638       new WebApplicationIconUrlsGetCallback(callback, userData);
1639   int callbackId = web_app_icon_urls_get_callback_map_.Add(cb);
1640   return renderViewHost->Send(new EwkViewMsg_WebAppIconUrlsGet(
1641       renderViewHost->GetRoutingID(), callbackId));
1642 }
1643
1644 void EWebView::InvokeWebAppCapableGetCallback(bool capable, int callbackId) {
1645   WebApplicationCapableGetCallback* callback =
1646       web_app_capable_get_callback_map_.Lookup(callbackId);
1647   if (!callback)
1648     return;
1649   callback->Run(capable);
1650 }
1651
1652 void EWebView::InvokeWebAppIconUrlGetCallback(const std::string& iconUrl,
1653                                               int callbackId) {
1654   WebApplicationIconUrlGetCallback* callback =
1655       web_app_icon_url_get_callback_map_.Lookup(callbackId);
1656   if (!callback)
1657     return;
1658   callback->Run(iconUrl);
1659 }
1660
1661 void EWebView::InvokeWebAppIconUrlsGetCallback(const StringMap& iconUrls,
1662                                                int callbackId) {
1663   WebApplicationIconUrlsGetCallback* callback =
1664       web_app_icon_urls_get_callback_map_.Lookup(callbackId);
1665   if (!callback) {
1666     return;
1667   }
1668   callback->Run(iconUrls);
1669 }
1670
1671 void EWebView::SetNotificationPermissionCallback(
1672     Ewk_View_Notification_Permission_Callback callback,
1673     void* user_data) {
1674   notification_permission_callback_.Set(callback, user_data);
1675 }
1676
1677 bool EWebView::IsNotificationPermissionCallbackSet() const {
1678   return notification_permission_callback_.IsCallbackSet();
1679 }
1680
1681 bool EWebView::InvokeNotificationPermissionCallback(
1682     Ewk_Notification_Permission_Request* request) {
1683   Eina_Bool ret = EINA_FALSE;
1684   notification_permission_callback_.Run(evas_object_, request, &ret);
1685   return ret;
1686 }
1687
1688 int EWebView::SetEwkViewPlainTextGetCallback(
1689     Ewk_View_Plain_Text_Get_Callback callback,
1690     void* user_data) {
1691   EwkViewPlainTextGetCallback* view_plain_text_callback_ptr =
1692       new EwkViewPlainTextGetCallback;
1693   view_plain_text_callback_ptr->Set(callback, user_data);
1694   return plain_text_get_callback_map_.Add(view_plain_text_callback_ptr);
1695 }
1696
1697 bool EWebView::PlainTextGet(Ewk_View_Plain_Text_Get_Callback callback,
1698                             void* user_data) {
1699   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1700   if (!render_view_host)
1701     return false;
1702   int plain_text_get_callback_id =
1703       SetEwkViewPlainTextGetCallback(callback, user_data);
1704   return render_view_host->Send(new EwkViewMsg_PlainTextGet(
1705       render_view_host->GetRoutingID(), plain_text_get_callback_id));
1706 }
1707
1708 void EWebView::InvokePlainTextGetCallback(const std::string& content_text,
1709                                           int plain_text_get_callback_id) {
1710   EwkViewPlainTextGetCallback* view_plain_text_callback_invoke_ptr =
1711       plain_text_get_callback_map_.Lookup(plain_text_get_callback_id);
1712   view_plain_text_callback_invoke_ptr->Run(evas_object(), content_text.c_str());
1713   plain_text_get_callback_map_.Remove(plain_text_get_callback_id);
1714 }
1715
1716 void EWebView::SetViewGeolocationPermissionCallback(
1717     Ewk_View_Geolocation_Permission_Callback callback,
1718     void* user_data) {
1719   geolocation_permission_cb_.Set(callback, user_data);
1720 }
1721
1722 bool EWebView::InvokeViewGeolocationPermissionCallback(
1723     _Ewk_Geolocation_Permission_Request* permission_context,
1724     Eina_Bool* callback_result) {
1725   return geolocation_permission_cb_.Run(evas_object_, permission_context,
1726                                         callback_result);
1727 }
1728
1729 void EWebView::SetViewUserMediaPermissionCallback(
1730     Ewk_View_User_Media_Permission_Callback callback,
1731     void* user_data) {
1732   user_media_permission_cb_.Set(callback, user_data);
1733 }
1734
1735 bool EWebView::InvokeViewUserMediaPermissionCallback(
1736     _Ewk_User_Media_Permission_Request* permission_context,
1737     Eina_Bool* callback_result) {
1738   return user_media_permission_cb_.Run(evas_object_, permission_context,
1739                                        callback_result);
1740 }
1741
1742 void EWebView::SetViewUnfocusAllowCallback(
1743     Ewk_View_Unfocus_Allow_Callback callback,
1744     void* user_data) {
1745   unfocus_allow_cb_.Set(callback, user_data);
1746 }
1747
1748 bool EWebView::InvokeViewUnfocusAllowCallback(Ewk_Unfocus_Direction direction,
1749                                               Eina_Bool* callback_result) {
1750   return unfocus_allow_cb_.Run(evas_object_, direction, callback_result);
1751 }
1752
1753 void EWebView::StopFinding() {
1754   web_contents_->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION);
1755 }
1756
1757 void EWebView::SetProgressValue(double progress) {
1758   progress_ = progress;
1759 }
1760
1761 double EWebView::GetProgressValue() {
1762   return progress_;
1763 }
1764
1765 const char* EWebView::GetTitle() {
1766   title_ = base::UTF16ToUTF8(web_contents_->GetTitle());
1767   return title_.c_str();
1768 }
1769
1770 bool EWebView::SaveAsPdf(int width, int height, const std::string& filename) {
1771   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1772   if (!render_view_host)
1773     return false;
1774
1775   return render_view_host->Send(
1776       new EwkViewMsg_PrintToPdf(render_view_host->GetRoutingID(), width, height,
1777                                 base::FilePath(filename)));
1778 }
1779
1780 bool EWebView::GetMHTMLData(Ewk_View_MHTML_Data_Get_Callback callback,
1781                             void* user_data) {
1782   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1783   if (!render_view_host)
1784     return false;
1785
1786   MHTMLCallbackDetails* callback_details = new MHTMLCallbackDetails;
1787   callback_details->Set(callback, user_data);
1788   int mhtml_callback_id = mhtml_callback_map_.Add(callback_details);
1789   return render_view_host->Send(new EwkViewMsg_GetMHTMLData(
1790       render_view_host->GetRoutingID(), mhtml_callback_id));
1791 }
1792
1793 void EWebView::OnMHTMLContentGet(const std::string& mhtml_content,
1794                                  int callback_id) {
1795   MHTMLCallbackDetails* callback_details =
1796       mhtml_callback_map_.Lookup(callback_id);
1797   callback_details->Run(evas_object(), mhtml_content.c_str());
1798   mhtml_callback_map_.Remove(callback_id);
1799 }
1800
1801 bool EWebView::IsFullscreen() {
1802   return web_contents_delegate_->IsFullscreenForTabOrPending(
1803       web_contents_.get());
1804 }
1805
1806 void EWebView::ExitFullscreen() {
1807   WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents_.get());
1808   wci->ExitFullscreen(false);
1809 }
1810
1811 double EWebView::GetScale() {
1812   return page_scale_factor_;
1813 }
1814
1815 void EWebView::DidChangePageScaleFactor(double scale_factor) {
1816   page_scale_factor_ = scale_factor;
1817   GetWebContentsViewEfl()->SetPageScaleFactor(scale_factor);
1818 }
1819
1820 inline JavaScriptDialogManagerEfl* EWebView::GetJavaScriptDialogManagerEfl() {
1821   return static_cast<JavaScriptDialogManagerEfl*>(
1822       web_contents_delegate_->GetJavaScriptDialogManager(web_contents_.get()));
1823 }
1824
1825 void EWebView::SetJavaScriptAlertCallback(
1826     Ewk_View_JavaScript_Alert_Callback callback,
1827     void* user_data) {
1828   GetJavaScriptDialogManagerEfl()->SetAlertCallback(callback, user_data);
1829 }
1830
1831 void EWebView::JavaScriptAlertReply() {
1832   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(true,
1833                                                                std::string());
1834   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
1835 }
1836
1837 void EWebView::SetJavaScriptConfirmCallback(
1838     Ewk_View_JavaScript_Confirm_Callback callback,
1839     void* user_data) {
1840   GetJavaScriptDialogManagerEfl()->SetConfirmCallback(callback, user_data);
1841 }
1842
1843 void EWebView::JavaScriptConfirmReply(bool result) {
1844   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(result,
1845                                                                std::string());
1846   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
1847 }
1848
1849 void EWebView::SetJavaScriptPromptCallback(
1850     Ewk_View_JavaScript_Prompt_Callback callback,
1851     void* user_data) {
1852   GetJavaScriptDialogManagerEfl()->SetPromptCallback(callback, user_data);
1853 }
1854
1855 void EWebView::JavaScriptPromptReply(const char* result) {
1856   GetJavaScriptDialogManagerEfl()->ExecuteDialogClosedCallBack(
1857       true, (std::string(result)));
1858   SmartCallback<EWebViewCallbacks::PopupReplyWaitFinish>().call(0);
1859 }
1860
1861 void EWebView::GetPageScaleRange(double* min_scale, double* max_scale) {
1862   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1863   if (!render_view_host) {
1864     if (min_scale)
1865       *min_scale = -1.f;
1866     if (max_scale)
1867       *max_scale = -1.f;
1868     return;
1869   }
1870
1871   WebPreferences prefs = render_view_host->GetWebkitPreferences();
1872   if (min_scale)
1873     *min_scale = prefs.default_minimum_page_scale_factor;
1874   if (max_scale)
1875     *max_scale = prefs.default_maximum_page_scale_factor;
1876 }
1877
1878 void EWebView::SetDrawsTransparentBackground(bool enabled) {
1879   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1880   if (!render_view_host)
1881     return;
1882
1883   render_view_host->Send(new EwkViewMsg_SetDrawsTransparentBackground(
1884       render_view_host->GetRoutingID(), enabled));
1885 }
1886
1887 void EWebView::GetSessionData(const char** data, unsigned* length) const {
1888   static const int MAX_SESSION_ENTRY_SIZE = std::numeric_limits<int>::max();
1889
1890   NavigationController& navigationController = web_contents_->GetController();
1891   base::Pickle sessionPickle;
1892   const int itemCount = navigationController.GetEntryCount();
1893
1894   sessionPickle.WriteInt(itemCount);
1895   sessionPickle.WriteInt(navigationController.GetCurrentEntryIndex());
1896
1897   for (int i = 0; i < itemCount; i++) {
1898     NavigationEntry* navigationEntry = navigationController.GetEntryAtIndex(i);
1899     sessions::SerializedNavigationEntry serializedEntry =
1900         sessions::ContentSerializedNavigationBuilder::FromNavigationEntry(
1901             i, *navigationEntry);
1902     serializedEntry.WriteToPickle(MAX_SESSION_ENTRY_SIZE, &sessionPickle);
1903   }
1904
1905   *data = static_cast<char*>(malloc(sizeof(char) * sessionPickle.size()));
1906   memcpy(const_cast<char*>(*data), sessionPickle.data(), sessionPickle.size());
1907   *length = sessionPickle.size();
1908 }
1909
1910 bool EWebView::RestoreFromSessionData(const char* data, unsigned length) {
1911   base::Pickle sessionPickle(data, length);
1912   base::PickleIterator pickleIterator(sessionPickle);
1913   int entryCount;
1914   int currentEntry;
1915
1916   if (!pickleIterator.ReadInt(&entryCount))
1917     return false;
1918   if (!pickleIterator.ReadInt(&currentEntry))
1919     return false;
1920
1921   std::vector<sessions::SerializedNavigationEntry> serializedEntries;
1922   serializedEntries.resize(entryCount);
1923   for (int i = 0; i < entryCount; ++i) {
1924     if (!serializedEntries.at(i).ReadFromPickle(&pickleIterator))
1925       return false;
1926   }
1927
1928   if (!entryCount)
1929     return true;
1930
1931   std::vector<std::unique_ptr<content::NavigationEntry>> scopedEntries =
1932       sessions::ContentSerializedNavigationBuilder::ToNavigationEntries(
1933           serializedEntries, context()->browser_context());
1934
1935   NavigationController& navigationController = web_contents_->GetController();
1936
1937   if (currentEntry < 0)
1938     currentEntry = 0;
1939
1940   if (currentEntry >= static_cast<int>(scopedEntries.size()))
1941     currentEntry = scopedEntries.size() - 1;
1942
1943 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1944   // FIXME: EWK_BRINGUP definition should be removed.
1945   navigationController.Restore(
1946       currentEntry, NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY,
1947       &scopedEntries);
1948 #endif  // !defined(EWK_BRINGUP)
1949   return true;
1950 }
1951
1952 void EWebView::SetBrowserFont() {
1953   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1954   if (render_view_host)
1955     render_view_host->Send(
1956         new EwkViewMsg_SetBrowserFont(render_view_host->GetRoutingID()));
1957 }
1958
1959 void EWebView::SetCertificatePem(const std::string& certificate) {
1960   pem_certificate_ = certificate;
1961   SmartCallback<EWebViewCallbacks::SetCertificatePem>().call(
1962       pem_certificate_.c_str());
1963 }
1964
1965 bool EWebView::IsDragging() const {
1966   return GetWebContentsViewEfl()->IsDragging();
1967 }
1968
1969 void EWebView::ShowFileChooser(content::RenderFrameHost* render_frame_host,
1970                                const content::FileChooserParams& params) {
1971   if (!IsMobileProfile() && !IsWearableProfile())
1972     return;
1973
1974 #if !defined(EWK_BRINGUP)
1975   if (params.capture) {
1976     const std::string capture_types[] = {"video/*", "audio/*", "image/*"};
1977     unsigned int capture_types_num =
1978         sizeof(capture_types) / sizeof(*capture_types);
1979     for (unsigned int i = 0; i < capture_types_num; ++i) {
1980       for (unsigned int j = 0; j < params.accept_types.size(); ++j) {
1981         if (UTF16ToUTF8(params.accept_types[j]) == capture_types[i]) {
1982           filechooser_mode_ = params.mode;
1983           LaunchCamera(params.accept_types[j]);
1984           return;
1985         }
1986       }
1987     }
1988   }
1989 #endif
1990   file_chooser_.reset(
1991       new content::FileChooserControllerEfl(render_frame_host, &params));
1992   file_chooser_->Open();
1993 }
1994
1995 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
1996 void EWebView::SetViewMode(blink::WebViewMode view_mode) {
1997   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1998   if (!render_view_host)
1999     return;
2000
2001   IPC::Message* message =
2002       new ViewMsg_SetViewMode(render_view_host->GetRoutingID(), view_mode);
2003   if (render_view_host->IsRenderViewLive()) {
2004     render_view_host->Send(message);
2005   } else {
2006     delayed_messages_.push_back(message);
2007   }
2008 }
2009 #endif
2010
2011 gfx::Point EWebView::GetContextMenuPosition() const {
2012   return context_menu_position_;
2013 }
2014
2015 void EWebView::ShowContentsDetectedPopup(const char* message) {
2016   popup_controller_.reset(new PopupControllerEfl(this));
2017   popup_controller_->openPopup(message);
2018 }
2019
2020 void EWebView::RequestColorPicker(int r, int g, int b, int a) {
2021   inputPicker_.reset(new InputPicker(*this));
2022   inputPicker_->ShowColorPicker(r, g, b, a);
2023 }
2024
2025 void EWebView::DismissColorPicker() {
2026   inputPicker_->HideColorPicker();
2027 }
2028
2029 bool EWebView::SetColorPickerColor(int r, int g, int b, int a) {
2030   web_contents_->DidChooseColorInColorChooser(SkColorSetARGB(a, r, g, b));
2031   return true;
2032 }
2033
2034 void EWebView::InputPickerShow(ui::TextInputType input_type,
2035                                double input_value) {
2036   inputPicker_.reset(new InputPicker(*this));
2037   inputPicker_->showDatePicker(input_type, input_value);
2038 }
2039
2040 void EWebView::LoadNotFoundErrorPage(const std::string& invalidUrl) {
2041   RenderFrameHost* render_frame_host = web_contents_->GetMainFrame();
2042   if (render_frame_host)
2043     render_frame_host->Send(new EwkFrameMsg_LoadNotFoundErrorPage(
2044         render_frame_host->GetRoutingID(), invalidUrl));
2045 }
2046
2047 std::string EWebView::GetPlatformLocale() {
2048   char* local_default = setlocale(LC_CTYPE, 0);
2049   if (!local_default)
2050     return std::string("en-US");
2051   std::string locale = std::string(local_default);
2052   size_t position = locale.find('_');
2053   if (position != std::string::npos)
2054     locale.replace(position, 1, "-");
2055   position = locale.find('.');
2056   if (position != std::string::npos)
2057     locale = locale.substr(0, position);
2058   return locale;
2059 }
2060
2061 int EWebView::StartInspectorServer(int port) {
2062   return context_->InspectorServerStart(port);
2063 }
2064
2065 bool EWebView::StopInspectorServer() {
2066   return context_->InspectorServerStop();
2067 }
2068
2069 void EWebView::InvokeWebProcessCrashedCallback() {
2070   DCHECK_CURRENTLY_ON(BrowserThread::UI);
2071   const GURL last_url = GetURL();
2072   bool callback_handled = false;
2073   SmartCallback<EWebViewCallbacks::WebProcessCrashed>().call(&callback_handled);
2074   if (!callback_handled)
2075     LoadHTMLString(kRendererCrashedHTMLMessage, NULL,
2076                    last_url.possibly_invalid_spec().c_str());
2077 }
2078
2079 void EWebView::HandleRendererProcessCrash() {
2080   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
2081                           base::Bind(&EWebView::InvokeWebProcessCrashedCallback,
2082                                      base::Unretained(this)));
2083 }
2084
2085 void EWebView::InitializeContent() {
2086   int width, height;
2087   evas_object_geometry_get(evas_object_, 0, 0, &width, &height);
2088
2089   WebContents* new_contents = create_new_window_web_contents_cb_.Run(this);
2090   if (!new_contents) {
2091     WebContents::CreateParams params(context_->browser_context());
2092     params.initial_size = gfx::Size(width, height);
2093     web_contents_.reset(
2094         new WebContentsImplEfl(context_->browser_context(), this));
2095     static_cast<WebContentsImpl*>(web_contents_.get())->Init(params);
2096     VLOG(1) << "Initial WebContents size: " << params.initial_size.ToString();
2097   } else {
2098     web_contents_.reset(new_contents);
2099
2100     // When a new webview is created in response to a request from the
2101     // engine, the BrowserContext instance of the originator WebContents
2102     // is used by the newly created WebContents object.
2103     // See more in WebContentsImplEfl::HandleNewWebContentsCreate.
2104     //
2105     // Hence, if as part of the WebView creation, the embedding APP
2106     // passes in a Ewk_Context instance that wraps a different instance of
2107     // BrowserContext than the one the originator WebContents holds,
2108     // undefined behavior can be seen.
2109     //
2110     // This is a snippet code that illustrate the scenario:
2111     //
2112     // (..)
2113     // evas_object_smart_callback_add(web_view_, "create,window",
2114     //                                &OnNewWindowRequest, this);
2115     // (..)
2116     //
2117     // void OnNewWindowRequest(void *data, Evas_Object*, void* out_view) {
2118     //   (..)
2119     //   EvasObject* new_web_view = ewk_view_add_with_context(GetEvas(),
2120     //   ewk_context_new());
2121     //   *static_cast<Evas_Object**>(out_view) = new_web_view;
2122     //   (..)
2123     // }
2124     //
2125     // The new Ewk_Context object created and passed in as parameter to
2126     // ewk_view_add_with_context wraps a different instance of BrowserContext
2127     // than the one the new WebContents object will hold.
2128     //
2129     // CHECK below aims at catching misuse of this API.
2130     bool should_crash = context_->GetImpl()->browser_context() !=
2131                         web_contents_->GetBrowserContext();
2132     if (should_crash) {
2133       CHECK(false)
2134           << "BrowserContext of new WebContents does not match EWebView's. "
2135           << "Please see 'ewk_view_add*' documentation. "
2136           << "Aborting execution ...";
2137     }
2138   }
2139   web_contents_delegate_.reset(new WebContentsDelegateEfl(this));
2140   web_contents_->SetDelegate(web_contents_delegate_.get());
2141   GetWebContentsViewEfl()->SetEflDelegate(
2142       new WebContentsViewEflDelegateEwk(this));
2143   WebContentsImplEfl* wc_efl =
2144       static_cast<WebContentsImplEfl*>(web_contents_.get());
2145   wc_efl->SetEflDelegate(new WebContentsEflDelegateEwk(this));
2146   back_forward_list_.reset(
2147       new _Ewk_Back_Forward_List(web_contents_->GetController()));
2148   back_forward_list_.reset(
2149       new _Ewk_Back_Forward_List(web_contents_->GetController()));
2150
2151   permission_popup_manager_.reset(new PermissionPopupManager(evas_object_));
2152
2153   native_view_ = static_cast<Evas_Object*>(web_contents_->GetNativeView());
2154   evas_object_smart_member_add(native_view_, evas_object_);
2155 }
2156
2157 #if defined(OS_TIZEN) && !defined(EWK_BRINGUP)
2158 void EWebView::cameraResultCb(service_h request,
2159                               service_h reply,
2160                               service_result_e result,
2161                               void* data) {
2162   if (!IsMobileProfile() && !IsWearableProfile())
2163     return;
2164
2165   EWebView* webview = static_cast<EWebView*>(data);
2166   RenderViewHost* render_view_host =
2167       webview->web_contents_->GetRenderViewHost();
2168   if (result == SERVICE_RESULT_SUCCEEDED) {
2169     int ret = -1;
2170     char** filesarray;
2171     int number;
2172     ret = service_get_extra_data_array(reply, SERVICE_DATA_SELECTED,
2173                                        &filesarray, &number);
2174     if (filesarray) {
2175       for (int i = 0; i < number; i++) {
2176         std::vector<ui::SelectedFileInfo> files;
2177         if (!render_view_host) {
2178           return;
2179         }
2180         if (filesarray[i]) {
2181           GURL url(filesarray[i]);
2182           if (!url.is_valid()) {
2183             base::FilePath path(url.SchemeIsFile() ? url.path()
2184                                                    : filesarray[i]);
2185             files.push_back(ui::SelectedFileInfo(path, base::FilePath()));
2186           }
2187         }
2188         render_view_host->FilesSelectedInChooser(files,
2189                                                  webview->filechooser_mode_);
2190       }
2191     }
2192   } else {
2193     std::vector<ui::SelectedFileInfo> files;
2194     if (render_view_host) {
2195       render_view_host->FilesSelectedInChooser(files,
2196                                                webview->filechooser_mode_);
2197     }
2198   }
2199 }
2200
2201 bool EWebView::LaunchCamera(base::string16 mimetype) {
2202   service_h svcHandle = 0;
2203   if (service_create(&svcHandle) < 0 || !svcHandle) {
2204     LOG(ERROR) << __FUNCTION__ << " Service Creation Failed ";
2205     return false;
2206   }
2207   service_set_operation(svcHandle, SERVICE_OPERATION_CREATE_CONTENT);
2208   service_set_mime(svcHandle, UTF16ToUTF8(mimetype).c_str());
2209   service_add_extra_data(svcHandle, "CALLER", "Browser");
2210
2211   int ret = service_send_launch_request(svcHandle, cameraResultCb, this);
2212   if (ret != SERVICE_ERROR_NONE) {
2213     LOG(ERROR) << __FUNCTION__ << " Service Launch Failed ";
2214     service_destroy(svcHandle);
2215     return false;
2216   }
2217   service_destroy(svcHandle);
2218   return true;
2219 }
2220 #endif
2221
2222 void EWebView::UrlRequestSet(
2223     const char* url,
2224     content::NavigationController::LoadURLType loadtype,
2225     Eina_Hash* headers,
2226     const char* body) {
2227   GURL gurl(url);
2228   content::NavigationController::LoadURLParams params(gurl);
2229   params.load_type = loadtype;
2230   params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
2231
2232   if (body) {
2233     std::string s(body);
2234     params.post_data =
2235         network::ResourceRequestBody::CreateFromBytes(s.data(), s.size());
2236   }
2237
2238   net::HttpRequestHeaders header;
2239   if (headers) {
2240     Eina_Iterator* it = eina_hash_iterator_tuple_new(headers);
2241     Eina_Hash_Tuple* t;
2242     while (eina_iterator_next(it, reinterpret_cast<void**>(&t))) {
2243       if (t->key) {
2244         const char* value_str =
2245             t->data ? static_cast<const char*>(t->data) : "";
2246         base::StringPiece name = static_cast<const char*>(t->key);
2247         base::StringPiece value = value_str;
2248         header.SetHeader(name, value);
2249         // net::HttpRequestHeaders.ToString() returns string with newline
2250         params.extra_headers += header.ToString();
2251       }
2252     }
2253     eina_iterator_free(it);
2254   }
2255
2256   web_contents_->GetController().LoadURLWithParams(params);
2257 }
2258
2259 bool EWebView::HandleShow() {
2260   if (!native_view_)
2261     return false;
2262
2263   Show();
2264   return true;
2265 }
2266
2267 bool EWebView::HandleHide() {
2268   if (!native_view_)
2269     return false;
2270
2271   Hide();
2272   return true;
2273 }
2274
2275 bool EWebView::HandleMove(int x, int y) {
2276   if (!native_view_)
2277     return false;
2278   evas_object_move(native_view_, x, y);
2279   return true;
2280 }
2281
2282 bool EWebView::HandleResize(int width, int height) {
2283   if (!native_view_)
2284     return false;
2285   evas_object_resize(native_view_, width, height);
2286   return true;
2287 }
2288
2289 bool EWebView::HandleTextSelectionDown(int x, int y) {
2290   if (!GetSelectionController())
2291     return false;
2292   return GetSelectionController()->TextSelectionDown(x, y);
2293 }
2294
2295 bool EWebView::HandleTextSelectionUp(int x, int y) {
2296   if (!GetSelectionController())
2297     return false;
2298   return GetSelectionController()->TextSelectionUp(x, y);
2299 }
2300
2301 void EWebView::HandleTapGestureForSelection(bool is_content_editable) {
2302   if (!GetSelectionController())
2303     return;
2304
2305   GetSelectionController()->PostHandleTapGesture(is_content_editable);
2306 }
2307
2308 void EWebView::HandleZoomGesture(blink::WebGestureEvent& event) {
2309   blink::WebInputEvent::Type event_type = event.GetType();
2310   if (event_type == blink::WebInputEvent::kGestureDoubleTap ||
2311       event_type == blink::WebInputEvent::kGesturePinchBegin) {
2312     SmartCallback<EWebViewCallbacks::ZoomStarted>().call();
2313   }
2314   if (event_type == blink::WebInputEvent::kGestureDoubleTap ||
2315       event_type == blink::WebInputEvent::kGesturePinchEnd) {
2316     SmartCallback<EWebViewCallbacks::ZoomFinished>().call();
2317   }
2318 }
2319
2320 void EWebView::SendDelayedMessages(RenderViewHost* render_view_host) {
2321   DCHECK(render_view_host);
2322
2323   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
2324     BrowserThread::PostTask(
2325         BrowserThread::UI, FROM_HERE,
2326         base::Bind(&EWebView::SendDelayedMessages, base::Unretained(this),
2327                    render_view_host));
2328     return;
2329   }
2330
2331   for (auto iter = delayed_messages_.begin(); iter != delayed_messages_.end();
2332        ++iter) {
2333     IPC::Message* message = *iter;
2334     message->set_routing_id(render_view_host->GetRoutingID());
2335     render_view_host->Send(message);
2336   }
2337
2338   delayed_messages_.clear();
2339 }