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.
5 #include "web_contents_delegate_efl.h"
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"
44 #include "web_contents_observer_efl.h"
46 #if BUILDFLAG(IS_TIZEN)
47 #include <app_control.h>
48 #include <app_manager.h>
51 #if BUILDFLAG(IS_TIZEN_TV)
52 #include "browser/mixed_content_observer.h"
53 #include "devtools_port_manager.h"
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"
62 #if defined(TIZEN_AUTOFILL_FW)
63 #include "browser/autofill/autofill_request_manager.h"
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"
76 using autofill::AutofillManager;
77 using autofill::AutofillClientEfl;
78 using autofill::ContentAutofillDriverFactory;
79 using password_manager::PasswordManagerClientEfl;
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())
93 if (device_id.length() == 0)
94 return &(*audio_devices.begin());
96 for (blink::MediaStreamDevices::const_iterator i = audio_devices.begin();
97 i != audio_devices.end(); i++) {
98 if (i->id.compare(device_id) == 0)
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())
113 if (device_id.length() == 0)
114 return &(*video_devices.begin());
116 for (blink::MediaStreamDevices::const_iterator i = video_devices.begin();
117 i != video_devices.end(); i++) {
118 if (i->id.compare(device_id) == 0)
128 WebContentsDelegateEfl::WebContentsDelegateEfl(EWebView* 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_);
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()));
149 #if defined(TIZEN_AUTOFILL_FW)
150 LOG(INFO) << "[Autofill] " << __FUNCTION__ << " Create AutofillRequest";
151 autofill::AutofillRequestManager::GetInstance()->CreateAutofillRequest(
152 view->evas_object());
157 WebContentsDelegateEfl::~WebContentsDelegateEfl() {
158 // It's important to delete web_contents_ before dialog_manager_
159 // destructor of web contents uses dialog_manager_
161 delete dialog_manager_;
164 static bool IsMainFrame(RenderFrameHost* render_frame_host) {
165 return !render_frame_host->GetParent();
168 WebContents* WebContentsDelegateEfl::OpenURLFromTab(
170 const OpenURLParams& params) {
171 const GURL& url = params.url;
172 WindowOpenDisposition disposition = params.disposition;
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)) {
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>()
191 web_view_->SmartCallback<EWebViewCallbacks::CreateNewWindow>().call(
198 if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB)
199 ActivateContents(source);
202 WebViewDelegateEwk::GetInstance().GetWebViewFromEvasObject(new_object);
208 ui::PageTransition transition(ui::PageTransitionFromInt(params.transition));
209 source->GetController().LoadURL(url, params.referrer, transition,
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());
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();
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());
237 auto selection_controller =
238 rwhva->offscreen_helper()->GetSelectionController();
239 if (selection_controller)
240 selection_controller->ClearSelection();
245 void WebContentsDelegateEfl::AddNewContents(
247 std::unique_ptr<WebContents> new_contents,
248 const GURL& target_url,
249 WindowOpenDisposition disposition,
250 const blink::mojom::WindowFeatures& window_features,
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);
260 // EWebView takes the ownership of new WebContents in
261 // EWebView::InitializeContent(). So, we can release the ownership of new
263 std::ignore = new_contents.release();
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.
282 void WebContentsDelegateEfl::CloseContents(WebContents* source) {
283 web_view_->SmartCallback<EWebViewCallbacks::WindowClosed>().call();
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();
293 void WebContentsDelegateEfl::ExitFullscreenModeForTab(
294 WebContents* web_contents) {
295 is_fullscreen_ = false;
296 web_view_->SmartCallback<EWebViewCallbacks::ExitFullscreen>().call();
299 bool WebContentsDelegateEfl::IsFullscreenForTabOrPending(
300 const WebContents* web_contents) {
301 return is_fullscreen_;
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];
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);
320 stream_devices.audio_device = *audio_device;
322 std::move(callback).Run(
323 blink::mojom::StreamDevicesSet(),
324 blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
325 std::unique_ptr<MediaStreamUI>());
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);
335 stream_devices.video_device = *video_device;
337 std::move(callback).Run(
338 blink::mojom::StreamDevicesSet(),
339 blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
340 std::unique_ptr<MediaStreamUI>());
345 std::move(callback).Run(stream_devices_set,
346 blink::mojom::MediaStreamRequestResult::OK,
347 std::unique_ptr<MediaStreamUI>());
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>());
359 bool WebContentsDelegateEfl::CheckMediaAccessPermission(
360 RenderFrameHost* render_frame_host,
361 const GURL& security_origin,
362 blink::mojom::MediaStreamType type) {
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)));
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());
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);
393 void WebContentsDelegateEfl::OnAuthRequired(const std::string& realm,
395 LoginDelegateEfl* login_delegate) {
396 web_view_->InvokeAuthCallback(login_delegate, url, realm);
399 void WebContentsDelegateEfl::RequestCertificateConfirm(
400 WebContents* /*web_contents*/,
402 const net::SSLInfo& ssl_info,
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(),
410 LOG(INFO) << "Certificate for URL: " << url.spec()
411 << " could not be opened";
412 std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
415 certificate_policy_decision_.reset(new _Ewk_Certificate_Policy_Decision(
416 url, pem_certificate, is_main_frame_request, cert_error,
417 std::move(callback)));
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;
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
437 std::move(certificate_policy_decision_->Callback())
438 .Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
440 // By default chromium-efl allows page to be opened with certificate
442 certificate_policy_decision_->SetDecision(true);
443 LOG(WARNING) << "Certificate for " << url.spec() << " was compromised";
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;
455 LOG(ERROR) << "Unable to get certificate!";
456 certificate_info.reset(new _Ewk_Certificate_Info(nullptr, false));
458 if (!net::X509Certificate::GetPEMEncoded(cert->cert_buffer(),
460 LOG(ERROR) << "Unable to get encoded PEM!";
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);
471 certificate_info.reset(
472 new _Ewk_Certificate_Info(pem_certificate.c_str(), is_context_secure));
474 web_view_->SmartCallback<EWebViewCallbacks::SSLCertificateChanged>().call(
475 certificate_info.get());
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;
487 std::unique_ptr<std::remove_pointer<app_control_h>::type,
488 decltype(app_control_destroy)*>
489 auto_release{app_control, app_control_destroy};
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;
498 ret = app_control_set_app_id(app_control, app_id);
501 if (ret != APP_CONTROL_ERROR_NONE) {
502 LOG(ERROR) << "app_control_set_app_id is failed with err " << ret;
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;
514 void WebContentsDelegateEfl::SetContentSecurityPolicy(
515 const std::string& policy,
516 Ewk_CSP_Header_Type header_type) {
517 contents_observer_->SetContentSecurityPolicy(policy, header_type);
520 #if defined(TIZEN_AUTOFILL)
521 void WebContentsDelegateEfl::UpdateAutofillIfRequired() {
522 if (AutofillClientEfl* autofill_client =
523 AutofillClientEfl::FromWebContents(&web_contents_)) {
524 autofill_client->UpdateAutofillIfRequired();
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);
539 #if defined(TIZEN_AUTOFILL_FW)
540 void WebContentsDelegateEfl::ResetLastInteractedElements() {
541 if (AutofillClientEfl* autofill_client =
542 AutofillClientEfl::FromWebContents(&web_contents_)) {
543 autofill_client->ResetLastInteractedElements();
548 void WebContentsDelegateEfl::FindReply(WebContents* web_contents,
550 int number_of_matches,
551 const gfx::Rect& selection_rect,
552 int active_match_ordinal,
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);
562 #if defined(TIZEN_TBM_SUPPORT)
563 void WebContentsDelegateEfl::DidRenderOffscreenFrame(void* buffer) {
564 web_view_->SmartCallback<EWebViewCallbacks::OffscreenFrameRendered>().call(
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";
578 // "frame,rendered" message is triggered as soon as rendering of a frame
580 web_view_->SmartCallback<EWebViewCallbacks::FrameRendered>().call(0);
584 void WebContentsDelegateEfl::DidChangeInputType(bool is_password_input) {
585 web_view_->UpdateContextMenu(is_password_input);
588 JavaScriptDialogManager* WebContentsDelegateEfl::GetJavaScriptDialogManager(
589 WebContents* source) {
590 if (!dialog_manager_)
591 dialog_manager_ = new JavaScriptDialogManagerEfl();
592 return dialog_manager_;
595 void WebContentsDelegateEfl::OnUpdateSettings(const Ewk_Settings* settings) {
596 #if defined(TIZEN_AUTOFILL)
597 PasswordManagerClientEfl* client =
598 PasswordManagerClientEfl::FromWebContents(&web_contents_);
600 PrefService* prefs = client->GetPrefs();
601 prefs->SetBoolean(password_manager::prefs::kCredentialsEnableService,
602 settings->autofillPasswordForm());
607 void WebContentsDelegateEfl::DidFirstVisuallyNonEmptyPaint() {
608 did_first_visually_non_empty_paint_ = true;
609 web_view_->SmartCallback<EWebViewCallbacks::LoadNonEmptyLayoutFinished>()
613 void WebContentsDelegateEfl::DidStartLoading() {
614 did_render_frame_ = false;
617 bool WebContentsDelegateEfl::DidAddMessageToConsole(
619 blink::mojom::ConsoleMessageLevel level,
620 const std::u16string& message,
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());
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);
639 std::unique_ptr<ColorChooser> WebContentsDelegateEfl::OpenColorChooser(
640 WebContents* web_contents,
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);
648 bool WebContentsDelegateEfl::PreHandleGestureEvent(
650 const blink::WebGestureEvent& event) {
651 blink::WebInputEvent::Type event_type = event.GetType();
652 switch (event_type) {
653 case blink::WebInputEvent::Type::kGestureDoubleTap:
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()))
670 void WebContentsDelegateEfl::BackgroundColorReceived(int callback_id,
672 web_view_->OnGetBackgroundColor(callback_id, bg_color);
675 void WebContentsDelegateEfl::RequestManifestInfo(
676 Ewk_View_Request_Manifest_Callback callback,
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);
686 manifest_manager_host->GetManifest(
687 base::BindOnce(&WebContentsDelegateEfl::OnDidGetManifest,
688 base::Unretained(this), callback, user_data));
691 void WebContentsDelegateEfl::OnDidGetManifest(
692 Ewk_View_Request_Manifest_Callback callback,
694 const GURL& manifest_url,
695 blink::mojom::ManifestPtr manifest) {
696 if (blink::IsEmptyManifest(*manifest)) {
697 web_view_->DidRespondRequestManifest(nullptr, callback, user_data);
699 _Ewk_View_Request_Manifest ewk_manifest(std::move(manifest));
700 web_view_->DidRespondRequestManifest(&ewk_manifest, callback, user_data);
704 #if BUILDFLAG(IS_TIZEN_TV)
705 void WebContentsDelegateEfl::ShowInspectorPortInfo() {
706 std::string mappingInfo;
707 devtools_http_handler::DevToolsPortManager::GetInstance()->GetMappingInfo(
709 if (web_view_->UseEarlyRWI()) {
711 "\r\nFast RWI is used, [about:blank] is loaded fist instead of \r\n[");
712 mappingInfo.append(web_view_->RWIURL().spec());
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.");
720 LOG(INFO) << "[RWI] WebContentsDelegateEfl::ShowPortInfo mappingInfo = "
721 << mappingInfo.c_str();
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) {},
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));
738 #if BUILDFLAG(IS_TIZEN_TV)
739 void WebContentsDelegateEfl::UpdateTargetURL(WebContents* /*source*/,
741 std::string absolute_link_url(url.spec());
742 if (absolute_link_url == last_hovered_url_)
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());
751 web_view_->SmartCallback<EWebViewCallbacks::HoverOverLink>().call(
752 absolute_link_url.c_str());
755 // Update latest hovered url.
756 last_hovered_url_ = absolute_link_url;
760 void WebContentsDelegateEfl::OnGetMainFrameScrollbarVisible(int callback_id,
762 web_view_->InvokeMainFrameScrollbarVisibleCallback(callback_id, visible);
764 } // namespace content