Use BUILDFLAG(IS_XXX) for OS checking.
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / web_contents_delegate_efl.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 "web_contents_delegate_efl.h"
6
7 #include <tuple>
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/trace_event/ttrace.h"
11 #include "browser/input_picker/color_chooser_efl.h"
12 #include "browser/javascript_dialog_manager_efl.h"
13 #include "browser/policy_response_delegate_efl.h"
14 #include "browser_context_efl.h"
15 #include "common/render_messages_ewk.h"
16 #include "components/password_manager/core/common/password_manager_pref_names.h"
17 #include "components/prefs/pref_service.h"
18 #include "content/browser/manifest/manifest_manager_host.h"
19 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
20 #include "content/browser/web_contents/web_contents_impl.h"
21 #include "content/common/content_switches_internal.h"
22 #include "content/common/render_messages_efl.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/file_select_listener.h"
25 #include "content/public/browser/invalidate_type.h"
26 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/navigation_handle.h"
28 #include "content/public/browser/render_view_host.h"
29 #include "eweb_view.h"
30 #include "eweb_view_callbacks.h"
31 #include "net/base/load_states.h"
32 #include "net/cert/x509_certificate.h"
33 #include "net/http/http_response_headers.h"
34 #include "private/ewk_certificate_private.h"
35 #include "private/ewk_console_message_private.h"
36 #include "private/ewk_error_private.h"
37 #include "private/ewk_policy_decision_private.h"
38 #include "private/ewk_user_media_private.h"
39 #include "private/webview_delegate_ewk.h"
40 #include "third_party/blink/public/common/input/web_input_event.h"
41 #include "third_party/blink/public/common/manifest/manifest_util.h"
42 #include "tizen/system_info.h"
43 #include "url/gurl.h"
44 #include "web_contents_observer_efl.h"
45
46 #if BUILDFLAG(IS_TIZEN)
47 #include <app_control.h>
48 #include <app_manager.h>
49 #endif
50
51 #if BUILDFLAG(IS_TIZEN_TV)
52 #include "browser/mixed_content_observer.h"
53 #include "devtools_port_manager.h"
54 #endif
55
56 #if defined(TIZEN_MULTIMEDIA)
57 #include "base/functional/callback.h"
58 #include "content/public/browser/media_capture_devices.h"
59 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
60 #endif
61
62 #if defined(TIZEN_AUTOFILL_FW)
63 #include "browser/autofill/autofill_request_manager.h"
64 #endif
65
66 #if defined(TIZEN_AUTOFILL)
67 #include "base/command_line.h"
68 #include "browser/autofill/autofill_client_efl.h"
69 #include "browser/password_manager/password_manager_client_efl.h"
70 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
71 #include "components/autofill/core/browser/autofill_client.h"
72 #include "components/autofill/core/browser/autofill_manager.h"
73 #include "components/autofill/core/common/autofill_switches.h"
74 #include "components/web_modal/web_contents_modal_dialog_manager.h"
75
76 using autofill::AutofillManager;
77 using autofill::AutofillClientEfl;
78 using autofill::ContentAutofillDriverFactory;
79 using password_manager::PasswordManagerClientEfl;
80 #endif
81 using std::u16string;
82 using namespace ui;
83
84 namespace content {
85
86 #if BUILDFLAG(IS_TIZEN) && defined(TIZEN_MULTIMEDIA)
87 static const blink::MediaStreamDevice* GetRequestedAudioDevice(
88     const std::string& device_id) {
89   const blink::MediaStreamDevices& audio_devices =
90       MediaCaptureDevices::GetInstance()->GetAudioCaptureDevices();
91   if (audio_devices.empty())
92     return NULL;
93   if (device_id.length() == 0)
94     return &(*audio_devices.begin());
95
96   for (blink::MediaStreamDevices::const_iterator i = audio_devices.begin();
97        i != audio_devices.end(); i++) {
98     if (i->id.compare(device_id) == 0)
99       return &(*i);
100   }
101
102   NOTREACHED();
103   return nullptr;
104 }
105
106 /* LCOV_EXCL_START */
107 static const blink::MediaStreamDevice* GetRequestedVideoDevice(
108     const std::string& device_id) {
109   const blink::MediaStreamDevices& video_devices =
110       MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices();
111   if (video_devices.empty())
112     return nullptr;
113   if (device_id.length() == 0)
114     return &(*video_devices.begin());
115
116   for (blink::MediaStreamDevices::const_iterator i = video_devices.begin();
117        i != video_devices.end(); i++) {
118     if (i->id.compare(device_id) == 0)
119       return &(*i);
120   }
121
122   NOTREACHED();
123   return nullptr;
124 }
125 /* LCOV_EXCL_STOP */
126 #endif
127
128 WebContentsDelegateEfl::WebContentsDelegateEfl(EWebView* view)
129     : web_view_(view),
130       web_contents_(view->web_contents()),
131       contents_observer_(std::make_unique<WebContentsObserverEfl>(view, this)) {
132 #if BUILDFLAG(IS_TIZEN_TV)
133   MixedContentObserver::CreateForWebContents(&web_contents_);
134 #endif
135 #if defined(TIZEN_AUTOFILL)
136   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
137           autofill::switches::kDisableAutofill)) {
138     AutofillClientEfl::CreateForWebContents(&web_contents_);
139     AutofillClientEfl* autofill_client =
140         AutofillClientEfl::FromWebContents(&web_contents_);
141     autofill_client->SetEWebView(view);
142     PasswordManagerClientEfl::CreateForWebContentsWithAutofillClient(
143         &web_contents_, autofill_client);
144     ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
145         &web_contents_, autofill_client,
146         base::BindRepeating(&autofill::BrowserDriverInitHook, autofill_client,
147                             EWebView::GetPlatformLocale()));
148   }
149 #if defined(TIZEN_AUTOFILL_FW)
150   LOG(INFO) << "[Autofill] " << __FUNCTION__ << " Create AutofillRequest";
151   autofill::AutofillRequestManager::GetInstance()->CreateAutofillRequest(
152       view->evas_object());
153 #endif
154 #endif
155 }
156
157 WebContentsDelegateEfl::~WebContentsDelegateEfl() {
158   // It's important to delete web_contents_ before dialog_manager_
159   // destructor of web contents uses dialog_manager_
160   if (dialog_manager_)
161     delete dialog_manager_;
162 }
163
164 static bool IsMainFrame(RenderFrameHost* render_frame_host) {
165   return !render_frame_host->GetParent();
166 }
167
168 WebContents* WebContentsDelegateEfl::OpenURLFromTab(
169     WebContents* source,
170     const OpenURLParams& params) {
171   const GURL& url = params.url;
172   WindowOpenDisposition disposition = params.disposition;
173
174   if (!source || (disposition != WindowOpenDisposition::CURRENT_TAB &&
175                   disposition != WindowOpenDisposition::NEW_FOREGROUND_TAB &&
176                   disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB &&
177                   disposition != WindowOpenDisposition::OFF_THE_RECORD)) {
178     NOTIMPLEMENTED();
179     return NULL;
180   }
181
182   if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
183       disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB ||
184       disposition == WindowOpenDisposition::OFF_THE_RECORD) {
185     Evas_Object* new_object = NULL;
186     if (IsMobileProfile() &&
187         disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) {
188       web_view_->SmartCallback<EWebViewCallbacks::CreateNewBackgroundWindow>()
189           .call(&new_object);
190     } else {
191       web_view_->SmartCallback<EWebViewCallbacks::CreateNewWindow>().call(
192           &new_object);
193     }
194
195     if (!new_object)
196       return NULL;
197
198     if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB)
199       ActivateContents(source);
200
201     EWebView* wv =
202         WebViewDelegateEwk::GetInstance().GetWebViewFromEvasObject(new_object);
203     DCHECK(wv);
204     wv->SetURL(url);
205     return NULL;
206   }
207
208   ui::PageTransition transition(ui::PageTransitionFromInt(params.transition));
209   source->GetController().LoadURL(url, params.referrer, transition,
210                                   std::string());
211   return source;
212 }
213
214 void WebContentsDelegateEfl::NavigationStateChanged(
215     WebContents* source, InvalidateTypes changed_flags) {
216   // We always notfiy clients about title invalidation, even if its text
217   // didn't actually change. This is to maintain EWK API consistency.
218   if (changed_flags & INVALIDATE_TYPE_TITLE) {
219     web_view_->SmartCallback<EWebViewCallbacks::TitleChange>().call(
220         base::UTF16ToUTF8(source->GetTitle()).c_str());
221   }
222
223   // We only notify clients if visible url actually changed, because on some
224   // pages we would get notifications with flag INVALIDATE_TYPE_URL even when
225   // visible url did not change.
226   if ((changed_flags & INVALIDATE_TYPE_URL) &&
227        last_visible_url_ != source->GetVisibleURL()) {
228     last_visible_url_ = source->GetVisibleURL();
229     const char* url = last_visible_url_.spec().c_str();
230
231     web_view_->SmartCallback<EWebViewCallbacks::URLChanged>().call(url);
232     web_view_->SmartCallback<EWebViewCallbacks::URIChanged>().call(url);
233     web_view_->ResetContextMenuController();
234     auto rwhva = static_cast<RenderWidgetHostViewAura*>(
235         web_contents_.GetRenderWidgetHostView());
236     if (rwhva) {
237       auto selection_controller =
238           rwhva->offscreen_helper()->GetSelectionController();
239       if (selection_controller)
240         selection_controller->ClearSelection();
241     }
242   }
243 }
244
245 void WebContentsDelegateEfl::AddNewContents(
246     WebContents* source,
247     std::unique_ptr<WebContents> new_contents,
248     const GURL& target_url,
249     WindowOpenDisposition disposition,
250     const blink::mojom::WindowFeatures& window_features,
251     bool user_gesture,
252     bool* was_blocked) {
253   // Initialize the delegate for the new contents here using source's delegate
254   // as it will be needed to create a new window with the pre-created
255   // new contents in case the opener is suppressed. Otherwise, the delegate
256   // had already been initialized in EWebView::InitializeContent()
257   if (!new_contents->GetDelegate())
258     new_contents->SetDelegate(this);
259
260   // EWebView takes the ownership of new WebContents in
261   // EWebView::InitializeContent(). So, we can release the ownership of new
262   // WebContents here.
263   std::ignore = new_contents.release();
264 }
265
266 bool WebContentsDelegateEfl::ShouldCreateWebContents(
267     WebContents* web_contents,
268     RenderFrameHost* opener,
269     SiteInstance* source_site_instance,
270     mojom::WindowContainerType window_container_type,
271     const GURL& opener_url,
272     const std::string& frame_name,
273     const GURL& target_url,
274     const std::string& partition_id,
275     SessionStorageNamespace* session_storage_namespace) {
276   // We implement the asynchronous version of the function, this
277   // one should never be invoked.
278   NOTREACHED();
279   return false;
280 }
281
282 void WebContentsDelegateEfl::CloseContents(WebContents* source) {
283   web_view_->SmartCallback<EWebViewCallbacks::WindowClosed>().call();
284 }
285
286 void WebContentsDelegateEfl::EnterFullscreenModeForTab(
287     RenderFrameHost* requesting_frame,
288     const blink::mojom::FullscreenOptions& options) {
289   is_fullscreen_ = true;
290   web_view_->SmartCallback<EWebViewCallbacks::EnterFullscreen>().call();
291 }
292
293 void WebContentsDelegateEfl::ExitFullscreenModeForTab(
294     WebContents* web_contents) {
295   is_fullscreen_ = false;
296   web_view_->SmartCallback<EWebViewCallbacks::ExitFullscreen>().call();
297 }
298
299 bool WebContentsDelegateEfl::IsFullscreenForTabOrPending(
300     const WebContents* web_contents) {
301   return is_fullscreen_;
302 }
303
304 #if defined(TIZEN_MULTIMEDIA)
305 /* LCOV_EXCL_START */
306 void WebContentsDelegateEfl::RequestMediaAccessAllow(
307     const MediaStreamRequest& request,
308     MediaResponseCallback callback) {
309   blink::mojom::StreamDevicesSet stream_devices_set;
310   stream_devices_set.stream_devices.emplace_back(
311       blink::mojom::StreamDevices::New());
312   blink::mojom::StreamDevices& stream_devices =
313       *stream_devices_set.stream_devices[0];
314
315   if (request.audio_type ==
316       blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
317     const blink::MediaStreamDevice* audio_device =
318         GetRequestedAudioDevice(request.requested_audio_device_id);
319     if (audio_device) {
320       stream_devices.audio_device = *audio_device;
321     } else {
322       std::move(callback).Run(
323           blink::mojom::StreamDevicesSet(),
324           blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
325           std::unique_ptr<MediaStreamUI>());
326       return;
327     }
328   }
329
330   if (request.video_type ==
331       blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) {
332     const blink::MediaStreamDevice* video_device =
333         GetRequestedVideoDevice(request.requested_video_device_id);
334     if (video_device) {
335       stream_devices.video_device = *video_device;
336     } else {
337       std::move(callback).Run(
338           blink::mojom::StreamDevicesSet(),
339           blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
340           std::unique_ptr<MediaStreamUI>());
341       return;
342     }
343   }
344
345   std::move(callback).Run(stream_devices_set,
346                           blink::mojom::MediaStreamRequestResult::OK,
347                           std::unique_ptr<MediaStreamUI>());
348 }
349 /* LCOV_EXCL_STOP */
350
351 void WebContentsDelegateEfl::RequestMediaAccessDeny(
352     const MediaStreamRequest& request,
353     MediaResponseCallback callback) {
354   std::move(callback).Run(blink::mojom::StreamDevicesSet(),
355                           blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
356                           std::unique_ptr<MediaStreamUI>());
357 }
358
359 bool WebContentsDelegateEfl::CheckMediaAccessPermission(
360     RenderFrameHost* render_frame_host,
361     const GURL& security_origin,
362     blink::mojom::MediaStreamType type) {
363   return true;
364 }
365
366 void WebContentsDelegateEfl::RequestMediaAccessPermission(
367     WebContents* web_contents,
368     const MediaStreamRequest& request,
369     MediaResponseCallback callback) {
370   std::unique_ptr<_Ewk_User_Media_Permission_Request> media_permission_request(
371       new _Ewk_User_Media_Permission_Request(this, request,
372                                              std::move(callback)));
373
374   Eina_Bool callback_result = EINA_FALSE;
375   if (!web_view_->InvokeViewUserMediaPermissionCallback(
376           media_permission_request.get(), &callback_result)) {
377     web_view_->SmartCallback<EWebViewCallbacks::UserMediaPermission>()
378         .call(  // LCOV_EXCL_LINE
379             media_permission_request.get());
380   }
381
382   // if policy is suspended, the API takes over the policy object lifetime
383   // and policy will be deleted after decision is made
384   if (media_permission_request->IsSuspended())
385     std::ignore = media_permission_request.release();
386   /* LCOV_EXCL_START */
387   else if (!media_permission_request->IsDecided())
388     media_permission_request->ProceedPermissionCallback(false);
389   /* LCOV_EXCL_STOP */
390 }
391 #endif
392
393 void WebContentsDelegateEfl::OnAuthRequired(const std::string& realm,
394                                             const GURL& url,
395                                             LoginDelegateEfl* login_delegate) {
396   web_view_->InvokeAuthCallback(login_delegate, url, realm);
397 }
398
399 void WebContentsDelegateEfl::RequestCertificateConfirm(
400     WebContents* /*web_contents*/,
401     int cert_error,
402     const net::SSLInfo& ssl_info,
403     const GURL& url,
404     bool is_main_frame_request,
405     bool /*strict_enforcement*/,
406     base::OnceCallback<void(CertificateRequestResultType)> callback) {
407   std::string pem_certificate;
408   if (!net::X509Certificate::GetPEMEncoded(ssl_info.cert->cert_buffer(),
409                                            &pem_certificate)) {
410     LOG(INFO) << "Certificate for URL: " << url.spec()
411               << " could not be opened";
412     std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
413     return;
414   }
415   certificate_policy_decision_.reset(new _Ewk_Certificate_Policy_Decision(
416       url, pem_certificate, is_main_frame_request, cert_error,
417       std::move(callback)));
418
419   web_view_->SmartCallback<EWebViewCallbacks::RequestCertificateConfirm>().call(
420       certificate_policy_decision_.get());
421   LOG(INFO) << "Certificate policy decision called for URL: " << url.spec()
422             << " with cert_error: " << cert_error;
423
424   // if policy is suspended, the API takes over the policy object lifetime
425   // and policy will be deleted after decision is made
426   if (certificate_policy_decision_->IsSuspended()) {
427     std::ignore = certificate_policy_decision_.release();
428   } else if (!certificate_policy_decision_->IsDecided()) {
429     // When the embeder neither suspended certificate decision nor handled it
430     // inside the smart callback by calling
431     // ewk_certificate_policy_decision_allowed_set
432     // this means the embeder let chromium decide what to do.
433     if (!is_main_frame_request) {
434       // A sub-resource has a certificate error. The user doesn't really
435       // have a context for making the right decision, so block the
436       // request hard.
437       std::move(certificate_policy_decision_->Callback())
438           .Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
439     } else {
440       // By default chromium-efl allows page to be opened with certificate
441       // compromise.
442       certificate_policy_decision_->SetDecision(true);
443       LOG(WARNING) << "Certificate for " << url.spec() << " was compromised";
444     }
445   }
446 }
447
448 void WebContentsDelegateEfl::VisibleSecurityStateChanged(WebContents* source) {
449   std::unique_ptr<_Ewk_Certificate_Info> certificate_info;
450   std::string pem_certificate;
451   SSLStatus ssl_status = source->GetController().GetVisibleEntry()->GetSSL();
452   scoped_refptr<net::X509Certificate> cert = ssl_status.certificate;
453
454   if (!cert) {
455     LOG(ERROR) << "Unable to get certificate!";
456     certificate_info.reset(new _Ewk_Certificate_Info(nullptr, false));
457   } else {
458     if (!net::X509Certificate::GetPEMEncoded(cert->cert_buffer(),
459                                              &pem_certificate)) {
460       LOG(ERROR) << "Unable to get encoded PEM!";
461       return;
462     }
463     // Note: The implementation below is a copy of the one in
464     // ChromeAutofillClient::IsContextSecure, and should be kept in sync
465     // until crbug.com/505388 gets implemented.
466     bool is_context_secure =
467         ssl_status.certificate &&
468         !net::IsCertStatusError(ssl_status.cert_status) &&
469         !(ssl_status.content_status & content::SSLStatus::RAN_INSECURE_CONTENT);
470
471     certificate_info.reset(
472         new _Ewk_Certificate_Info(pem_certificate.c_str(), is_context_secure));
473   }
474   web_view_->SmartCallback<EWebViewCallbacks::SSLCertificateChanged>().call(
475       certificate_info.get());
476 }
477
478 void WebContentsDelegateEfl::ActivateContents(WebContents* contents) {
479 #if BUILDFLAG(IS_TIZEN)
480   app_control_h app_control = nullptr;
481   int ret = app_control_create(&app_control);
482   if (ret != APP_CONTROL_ERROR_NONE) {
483     LOG(ERROR) << "app_control_create is failed with err " << ret;
484     return;
485   }
486
487   std::unique_ptr<std::remove_pointer<app_control_h>::type,
488                   decltype(app_control_destroy)*>
489       auto_release{app_control, app_control_destroy};
490
491   char* app_id = nullptr;
492   ret = app_manager_get_app_id(getpid(), &app_id);
493   if (ret != APP_MANAGER_ERROR_NONE) {
494     LOG(ERROR) << "app_manager_get_app_id is failed with err " << ret;
495     return;
496   }
497
498   ret = app_control_set_app_id(app_control, app_id);
499   if (app_id)
500     free(app_id);
501   if (ret != APP_CONTROL_ERROR_NONE) {
502     LOG(ERROR) << "app_control_set_app_id is failed with err " << ret;
503     return;
504   }
505
506   ret = app_control_send_launch_request(app_control, nullptr, nullptr);
507   if (ret != APP_CONTROL_ERROR_NONE) {
508     LOG(ERROR) << "app_control_send_launch_request is failed with err " << ret;
509     return;
510   }
511 #endif
512 }
513
514 void WebContentsDelegateEfl::SetContentSecurityPolicy(
515     const std::string& policy,
516     Ewk_CSP_Header_Type header_type) {
517   contents_observer_->SetContentSecurityPolicy(policy, header_type);
518 }
519
520 #if defined(TIZEN_AUTOFILL)
521 void WebContentsDelegateEfl::UpdateAutofillIfRequired() {
522   if (AutofillClientEfl* autofill_client =
523           AutofillClientEfl::FromWebContents(&web_contents_)) {
524     autofill_client->UpdateAutofillIfRequired();
525   }
526 }
527 #endif
528
529 void WebContentsDelegateEfl::OnDidChangeFocusedNodeBounds(
530     const gfx::RectF& focused_node_bounds) {
531 #if defined(TIZEN_AUTOFILL)
532   if (AutofillClientEfl* autofill_client =
533           AutofillClientEfl::FromWebContents(&web_contents_)) {
534     autofill_client->DidChangeFocusedNodeBounds(focused_node_bounds);
535   }
536 #endif
537 }
538
539 #if defined(TIZEN_AUTOFILL_FW)
540 void WebContentsDelegateEfl::ResetLastInteractedElements() {
541   if (AutofillClientEfl* autofill_client =
542           AutofillClientEfl::FromWebContents(&web_contents_)) {
543     autofill_client->ResetLastInteractedElements();
544   }
545 }
546 #endif
547
548 void WebContentsDelegateEfl::FindReply(WebContents* web_contents,
549                                        int request_id,
550                                        int number_of_matches,
551                                        const gfx::Rect& selection_rect,
552                                        int active_match_ordinal,
553                                        bool final_update) {
554   if (final_update && request_id == web_view_->current_find_request_id()) {
555     unsigned int uint_number_of_matches =
556         static_cast<unsigned int>(number_of_matches);
557     web_view_->SmartCallback<EWebViewCallbacks::TextFound>().call(
558         &uint_number_of_matches);
559   }
560 }
561
562 #if defined(TIZEN_TBM_SUPPORT)
563 void WebContentsDelegateEfl::DidRenderOffscreenFrame(void* buffer) {
564   web_view_->SmartCallback<EWebViewCallbacks::OffscreenFrameRendered>().call(
565       buffer);
566 }
567 #endif
568
569 void WebContentsDelegateEfl::DidRenderFrame() {
570   // Call FrameRendered callback when loading and first layout is finished.
571   if (!did_render_frame_ && did_first_visually_non_empty_paint_ &&
572       (web_view_->GetProgressValue() > 0.1)) {
573     did_first_visually_non_empty_paint_ = false;
574     did_render_frame_ = true;
575     TTRACE_WEB("WebContentsDelegateEfl::DidRenderFrame");
576     LOG(INFO) << "WebContentsDelegateEfl::DidRenderFrame";
577
578     // "frame,rendered" message is triggered as soon as rendering of a frame
579     // is completed.
580     web_view_->SmartCallback<EWebViewCallbacks::FrameRendered>().call(0);
581   }
582 }
583
584 void WebContentsDelegateEfl::DidChangeInputType(bool is_password_input) {
585   web_view_->UpdateContextMenu(is_password_input);
586 }
587
588 JavaScriptDialogManager* WebContentsDelegateEfl::GetJavaScriptDialogManager(
589     WebContents* source) {
590   if (!dialog_manager_)
591     dialog_manager_ = new JavaScriptDialogManagerEfl();
592   return dialog_manager_;
593 }
594
595 void WebContentsDelegateEfl::OnUpdateSettings(const Ewk_Settings* settings) {
596 #if defined(TIZEN_AUTOFILL)
597   PasswordManagerClientEfl* client =
598       PasswordManagerClientEfl::FromWebContents(&web_contents_);
599   if (client) {
600     PrefService* prefs = client->GetPrefs();
601     prefs->SetBoolean(password_manager::prefs::kCredentialsEnableService,
602                       settings->autofillPasswordForm());
603   }
604 #endif
605 }
606
607 void WebContentsDelegateEfl::DidFirstVisuallyNonEmptyPaint() {
608   did_first_visually_non_empty_paint_ = true;
609   web_view_->SmartCallback<EWebViewCallbacks::LoadNonEmptyLayoutFinished>()
610       .call();
611 }
612
613 void WebContentsDelegateEfl::DidStartLoading() {
614   did_render_frame_ = false;
615 }
616
617 bool WebContentsDelegateEfl::DidAddMessageToConsole(
618     WebContents* source,
619     blink::mojom::ConsoleMessageLevel level,
620     const std::u16string& message,
621     int32_t line_no,
622     const std::u16string& source_id) {
623   std::unique_ptr<_Ewk_Console_Message> console_message(
624       new _Ewk_Console_Message(static_cast<unsigned>(level),
625                                base::UTF16ToUTF8(message).c_str(), line_no,
626                                base::UTF16ToUTF8(source_id).c_str()));
627   web_view_->SmartCallback<EWebViewCallbacks::ConsoleMessage>().call(
628       console_message.get());
629   return true;
630 }
631
632 void WebContentsDelegateEfl::RunFileChooser(
633     RenderFrameHost* render_frame_host,
634     scoped_refptr<FileSelectListener> listener,
635     const blink::mojom::FileChooserParams& params) {
636   web_view_->ShowFileChooser(render_frame_host, params);
637 }
638
639 std::unique_ptr<ColorChooser> WebContentsDelegateEfl::OpenColorChooser(
640     WebContents* web_contents,
641     SkColor color,
642     const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) {
643   web_view_->RequestColorPicker(SkColorGetR(color), SkColorGetG(color),
644                                 SkColorGetB(color), SkColorGetA(color));
645   return std::make_unique<ColorChooserEfl>(*web_contents);
646 }
647
648 bool WebContentsDelegateEfl::PreHandleGestureEvent(
649     WebContents* source,
650     const blink::WebGestureEvent& event) {
651   blink::WebInputEvent::Type event_type = event.GetType();
652   switch (event_type) {
653     case blink::WebInputEvent::Type::kGestureDoubleTap:
654       if (is_fullscreen_)
655         return true;
656       break;
657     case blink::WebInputEvent::Type::kGesturePinchBegin:
658     case blink::WebInputEvent::Type::kGesturePinchUpdate:
659     case blink::WebInputEvent::Type::kGesturePinchEnd:
660       if (!IsPinchToZoomEnabled() ||
661           IsFullscreenForTabOrPending(&web_contents()))
662         return true;
663       break;
664     default:
665       break;
666   }
667   return false;
668 }
669
670 void WebContentsDelegateEfl::BackgroundColorReceived(int callback_id,
671                                                      SkColor bg_color) {
672   web_view_->OnGetBackgroundColor(callback_id, bg_color);
673 }
674
675 void WebContentsDelegateEfl::RequestManifestInfo(
676     Ewk_View_Request_Manifest_Callback callback,
677     void* user_data) {
678   WebContentsImpl* wci = static_cast<WebContentsImpl*>(&web_contents_);
679   ManifestManagerHost* manifest_manager_host =
680       ManifestManagerHost::GetOrCreateForPage(wci->GetPrimaryPage());
681   if (!manifest_manager_host) {
682     web_view_->DidRespondRequestManifest(nullptr, callback, user_data);
683     return;
684   }
685
686   manifest_manager_host->GetManifest(
687       base::BindOnce(&WebContentsDelegateEfl::OnDidGetManifest,
688                      base::Unretained(this), callback, user_data));
689 }
690
691 void WebContentsDelegateEfl::OnDidGetManifest(
692     Ewk_View_Request_Manifest_Callback callback,
693     void* user_data,
694     const GURL& manifest_url,
695     blink::mojom::ManifestPtr manifest) {
696   if (blink::IsEmptyManifest(*manifest)) {
697     web_view_->DidRespondRequestManifest(nullptr, callback, user_data);
698   } else {
699     _Ewk_View_Request_Manifest ewk_manifest(std::move(manifest));
700     web_view_->DidRespondRequestManifest(&ewk_manifest, callback, user_data);
701   }
702 }
703
704 #if BUILDFLAG(IS_TIZEN_TV)
705 void WebContentsDelegateEfl::ShowInspectorPortInfo() {
706   std::string mappingInfo;
707   devtools_http_handler::DevToolsPortManager::GetInstance()->GetMappingInfo(
708       mappingInfo);
709   if (web_view_->UseEarlyRWI()) {
710     mappingInfo.append(
711         "\r\nFast RWI is used, [about:blank] is loaded fist instead of \r\n[");
712     mappingInfo.append(web_view_->RWIURL().spec());
713     mappingInfo.append(
714         "]\r\nClick OK button will start the real loading.\r\nNotes:\r\nPlease "
715         "connect to RWI in PC before click OK button.\r\nThen you can get "
716         "network log from the initial loading.\r\nPlease click Record button "
717         "in Timeline panel in PC before click OK button,\r\nThen you can get "
718         "profile log from the initial loading.");
719   }
720   LOG(INFO) << "[RWI] WebContentsDelegateEfl::ShowPortInfo mappingInfo = "
721             << mappingInfo.c_str();
722
723   if (!mappingInfo.empty()) {
724     const GURL kGURL("");
725     WebContentsImpl* wci = static_cast<WebContentsImpl*>(&web_contents_);
726     auto dialog_closed_callback =
727         base::BindOnce([](JavaScriptDialogManager* manager, bool success,
728                           const std::u16string& response) {},
729                        dialog_manager_);
730     wci->RunJavaScriptDialog(
731         wci->GetPrimaryMainFrame(), base::ASCIIToUTF16(mappingInfo),
732         base::ASCIIToUTF16(base::StringPiece("OK")),
733         JAVASCRIPT_DIALOG_TYPE_ALERT, false, std::move(dialog_closed_callback));
734   }
735 }
736 #endif
737
738 #if BUILDFLAG(IS_TIZEN_TV)
739 void WebContentsDelegateEfl::UpdateTargetURL(WebContents* /*source*/,
740                                              const GURL& url) {
741   std::string absolute_link_url(url.spec());
742   if (absolute_link_url == last_hovered_url_)
743     return;
744
745   if (absolute_link_url.empty()) {
746     // If length is 0, it is not link. send "hover,out,link" callback with the
747     // original hovered URL.
748     web_view_->SmartCallback<EWebViewCallbacks::HoverOutLink>().call(
749         last_hovered_url_.c_str());
750   } else {
751     web_view_->SmartCallback<EWebViewCallbacks::HoverOverLink>().call(
752         absolute_link_url.c_str());
753   }
754
755   // Update latest hovered url.
756   last_hovered_url_ = absolute_link_url;
757 }
758 #endif
759
760 void WebContentsDelegateEfl::OnGetMainFrameScrollbarVisible(int callback_id,
761                                                             bool visible) {
762   web_view_->InvokeMainFrameScrollbarVisibleCallback(callback_id, visible);
763 }
764 }  // namespace content