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