1 // Copyright 2012 The Chromium Authors. 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 "chrome/browser/android/tab_web_contents_delegate_android.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "base/android/jni_android.h"
15 #include "base/android/jni_string.h"
16 #include "base/bind.h"
17 #include "base/command_line.h"
18 #include "base/metrics/histogram_macros.h"
19 #include "base/optional.h"
20 #include "base/rand_util.h"
21 #include "chrome/android/chrome_jni_headers/TabWebContentsDelegateAndroidImpl_jni.h"
22 #include "chrome/browser/android/hung_renderer_infobar_delegate.h"
23 #include "chrome/browser/android/tab_android.h"
24 #include "chrome/browser/banners/app_banner_manager_android.h"
25 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
27 #include "chrome/browser/content_settings/sound_content_setting_observer.h"
28 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_tab_helper.h"
29 #include "chrome/browser/file_select_helper.h"
30 #include "chrome/browser/flags/android/cached_feature_flags.h"
31 #include "chrome/browser/flags/android/chrome_feature_list.h"
32 #include "chrome/browser/history/history_tab_helper.h"
33 #include "chrome/browser/infobars/infobar_service.h"
34 #include "chrome/browser/installable/installed_webapp_bridge.h"
35 #include "chrome/browser/installable/installed_webapp_geolocation_context.h"
36 #include "chrome/browser/media/protected_media_identifier_permission_context.h"
37 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
38 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
39 #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
40 #include "chrome/browser/prefetch/no_state_prefetch/prerender_manager_factory.h"
41 #include "chrome/browser/profiles/profile.h"
42 #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer.h"
43 #include "chrome/browser/ssl/security_state_tab_helper.h"
44 #include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
45 #include "chrome/browser/ui/android/infobars/framebust_block_infobar.h"
46 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
47 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
48 #include "chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.h"
49 #include "chrome/browser/ui/browser_navigator_params.h"
50 #include "chrome/browser/ui/interventions/framebust_block_message_delegate.h"
51 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
52 #include "chrome/browser/ui/tab_helpers.h"
53 #include "chrome/browser/vr/vr_tab_helper.h"
54 #include "chrome/common/chrome_switches.h"
55 #include "chrome/common/url_constants.h"
56 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
57 #include "components/blocked_content/popup_blocker.h"
58 #include "components/blocked_content/popup_tracker.h"
59 #include "components/browser_ui/sms/android/sms_infobar.h"
60 #include "components/browser_ui/util/android/url_constants.h"
61 #include "components/find_in_page/find_notification_details.h"
62 #include "components/find_in_page/find_tab_helper.h"
63 #include "components/infobars/core/infobar.h"
64 #include "components/javascript_dialogs/app_modal_dialog_manager.h"
65 #include "components/javascript_dialogs/tab_modal_dialog_manager.h"
66 #include "components/navigation_interception/intercept_navigation_delegate.h"
67 #include "components/no_state_prefetch/browser/prerender_manager.h"
68 #include "components/paint_preview/buildflags/buildflags.h"
69 #include "components/security_state/content/content_utils.h"
70 #include "content/public/browser/file_select_listener.h"
71 #include "content/public/browser/navigation_entry.h"
72 #include "content/public/browser/render_frame_host.h"
73 #include "content/public/browser/render_process_host.h"
74 #include "content/public/browser/render_view_host.h"
75 #include "content/public/browser/security_style_explanations.h"
76 #include "content/public/browser/web_contents.h"
77 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
78 #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h"
79 #include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
80 #include "ui/gfx/geometry/rect.h"
81 #include "ui/gfx/geometry/rect_f.h"
82 #include "url/origin.h"
83
84 #if BUILDFLAG(ENABLE_PRINTING)
85 #include "components/printing/browser/print_composite_client.h"
86 #endif
87
88 #if BUILDFLAG(ENABLE_PAINT_PREVIEW)
89 #include "components/paint_preview/browser/paint_preview_client.h"
90 #endif
91
92 using base::android::AttachCurrentThread;
93 using base::android::JavaParamRef;
94 using base::android::JavaRef;
95 using base::android::ScopedJavaLocalRef;
96 using blink::mojom::FileChooserParams;
97 using content::WebContents;
98
99 namespace {
100
101 ScopedJavaLocalRef<jobject>
JNI_TabWebContentsDelegateAndroidImpl_CreateJavaRectF(JNIEnv * env,const gfx::RectF & rect)102 JNI_TabWebContentsDelegateAndroidImpl_CreateJavaRectF(JNIEnv* env,
103 const gfx::RectF& rect) {
104 return ScopedJavaLocalRef<jobject>(
105 Java_TabWebContentsDelegateAndroidImpl_createRectF(
106 env, rect.x(), rect.y(), rect.right(), rect.bottom()));
107 }
108
109 ScopedJavaLocalRef<jobject>
JNI_TabWebContentsDelegateAndroidImpl_CreateJavaRect(JNIEnv * env,const gfx::Rect & rect)110 JNI_TabWebContentsDelegateAndroidImpl_CreateJavaRect(JNIEnv* env,
111 const gfx::Rect& rect) {
112 return ScopedJavaLocalRef<jobject>(
113 Java_TabWebContentsDelegateAndroidImpl_createRect(
114 env, static_cast<int>(rect.x()), static_cast<int>(rect.y()),
115 static_cast<int>(rect.right()), static_cast<int>(rect.bottom())));
116 }
117
FindHungRendererInfoBar(InfoBarService * infobar_service)118 infobars::InfoBar* FindHungRendererInfoBar(InfoBarService* infobar_service) {
119 DCHECK(infobar_service);
120 for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
121 infobars::InfoBar* infobar = infobar_service->infobar_at(i);
122 if (infobar->delegate()->AsHungRendererInfoBarDelegate())
123 return infobar;
124 }
125 return nullptr;
126 }
127
ShowFramebustBlockInfobarInternal(content::WebContents * web_contents,const GURL & url)128 void ShowFramebustBlockInfobarInternal(content::WebContents* web_contents,
129 const GURL& url) {
130 auto intervention_outcome =
131 [](FramebustBlockMessageDelegate::InterventionOutcome outcome) {
132 UMA_HISTOGRAM_ENUMERATION("WebCore.Framebust.InterventionOutcome",
133 outcome);
134 };
135 FramebustBlockInfoBar::Show(
136 web_contents,
137 std::make_unique<FramebustBlockMessageDelegate>(
138 web_contents, url, base::BindOnce(intervention_outcome)));
139 }
140
141 } // anonymous namespace
142
143 namespace android {
144
TabWebContentsDelegateAndroid(JNIEnv * env,jobject obj)145 TabWebContentsDelegateAndroid::TabWebContentsDelegateAndroid(JNIEnv* env,
146 jobject obj)
147 : WebContentsDelegateAndroid(env, obj) {
148 }
149
150 TabWebContentsDelegateAndroid::~TabWebContentsDelegateAndroid() = default;
151
PortalWebContentsCreated(content::WebContents * portal_contents)152 void TabWebContentsDelegateAndroid::PortalWebContentsCreated(
153 content::WebContents* portal_contents) {
154 WebContentsDelegateAndroid::PortalWebContentsCreated(portal_contents);
155
156 // This is a subset of the tab helpers that would be attached by
157 // TabAndroid::AttachTabHelpers.
158 //
159 // TODO(jbroman): This doesn't adequately handle all of the tab helpers that
160 // might be wanted here, and there are also likely to be issues with tab
161 // helpers that are unprepared for portal activation to transition them.
162 // See https://crbug.com/1042323
163 autofill::ChromeAutofillClient::CreateForWebContents(portal_contents);
164 autofill::ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
165 portal_contents,
166 autofill::ChromeAutofillClient::FromWebContents(portal_contents),
167 g_browser_process->GetApplicationLocale(),
168 autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
169 ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
170 portal_contents,
171 autofill::ChromeAutofillClient::FromWebContents(portal_contents));
172 HistoryTabHelper::CreateForWebContents(portal_contents);
173 InfoBarService::CreateForWebContents(portal_contents);
174 PrefsTabHelper::CreateForWebContents(portal_contents);
175 DataReductionProxyTabHelper::CreateForWebContents(portal_contents);
176 safe_browsing::SafeBrowsingNavigationObserver::MaybeCreateForWebContents(
177 portal_contents);
178 }
179
RunFileChooser(content::RenderFrameHost * render_frame_host,scoped_refptr<content::FileSelectListener> listener,const FileChooserParams & params)180 void TabWebContentsDelegateAndroid::RunFileChooser(
181 content::RenderFrameHost* render_frame_host,
182 scoped_refptr<content::FileSelectListener> listener,
183 const FileChooserParams& params) {
184 if (vr::VrTabHelper::IsUiSuppressedInVr(
185 WebContents::FromRenderFrameHost(render_frame_host),
186 vr::UiSuppressedElement::kFileChooser)) {
187 listener->FileSelectionCanceled();
188 return;
189 }
190 FileSelectHelper::RunFileChooser(render_frame_host, std::move(listener),
191 params);
192 }
193
CreateSmsPrompt(content::RenderFrameHost * host,const url::Origin & origin,const std::string & one_time_code,base::OnceClosure on_confirm,base::OnceClosure on_cancel)194 void TabWebContentsDelegateAndroid::CreateSmsPrompt(
195 content::RenderFrameHost* host,
196 const url::Origin& origin,
197 const std::string& one_time_code,
198 base::OnceClosure on_confirm,
199 base::OnceClosure on_cancel) {
200 auto* web_contents = content::WebContents::FromRenderFrameHost(host);
201 sms::SmsInfoBar::Create(
202 web_contents, InfoBarService::FromWebContents(web_contents),
203 ChromeConfirmInfoBar::GetResourceIdMapper(), origin, one_time_code,
204 std::move(on_confirm), std::move(on_cancel));
205 }
206
ShouldFocusLocationBarByDefault(WebContents * source)207 bool TabWebContentsDelegateAndroid::ShouldFocusLocationBarByDefault(
208 WebContents* source) {
209 content::NavigationEntry* entry = source->GetController().GetActiveEntry();
210 if (entry) {
211 GURL url = entry->GetURL();
212 GURL virtual_url = entry->GetVirtualURL();
213 if ((url.SchemeIs(browser_ui::kChromeUINativeScheme) &&
214 url.host_piece() == chrome::kChromeUINewTabHost) ||
215 (virtual_url.SchemeIs(browser_ui::kChromeUINativeScheme) &&
216 virtual_url.host_piece() == chrome::kChromeUINewTabHost)) {
217 return true;
218 }
219 }
220 return false;
221 }
222
GetDisplayMode(const WebContents * web_contents)223 blink::mojom::DisplayMode TabWebContentsDelegateAndroid::GetDisplayMode(
224 const WebContents* web_contents) {
225 JNIEnv* env = base::android::AttachCurrentThread();
226
227 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
228 if (obj.is_null())
229 return blink::mojom::DisplayMode::kUndefined;
230
231 return static_cast<blink::mojom::DisplayMode>(
232 Java_TabWebContentsDelegateAndroidImpl_getDisplayMode(env, obj));
233 }
234
FindReply(WebContents * web_contents,int request_id,int number_of_matches,const gfx::Rect & selection_rect,int active_match_ordinal,bool final_update)235 void TabWebContentsDelegateAndroid::FindReply(
236 WebContents* web_contents,
237 int request_id,
238 int number_of_matches,
239 const gfx::Rect& selection_rect,
240 int active_match_ordinal,
241 bool final_update) {
242 find_in_page::FindTabHelper* find_tab_helper =
243 find_in_page::FindTabHelper::FromWebContents(web_contents);
244 if (!find_result_observer_.IsObserving(find_tab_helper))
245 find_result_observer_.Add(find_tab_helper);
246
247 find_tab_helper->HandleFindReply(request_id,
248 number_of_matches,
249 selection_rect,
250 active_match_ordinal,
251 final_update);
252 }
253
FindMatchRectsReply(WebContents * web_contents,int version,const std::vector<gfx::RectF> & rects,const gfx::RectF & active_rect)254 void TabWebContentsDelegateAndroid::FindMatchRectsReply(
255 WebContents* web_contents,
256 int version,
257 const std::vector<gfx::RectF>& rects,
258 const gfx::RectF& active_rect) {
259 JNIEnv* env = base::android::AttachCurrentThread();
260 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
261 if (obj.is_null())
262 return;
263
264 // Create the details object.
265 ScopedJavaLocalRef<jobject> details_object =
266 Java_TabWebContentsDelegateAndroidImpl_createFindMatchRectsDetails(
267 env, version, rects.size(),
268 JNI_TabWebContentsDelegateAndroidImpl_CreateJavaRectF(env,
269 active_rect));
270
271 // Add the rects
272 for (size_t i = 0; i < rects.size(); ++i) {
273 Java_TabWebContentsDelegateAndroidImpl_setMatchRectByIndex(
274 env, details_object, i,
275 JNI_TabWebContentsDelegateAndroidImpl_CreateJavaRectF(env, rects[i]));
276 }
277
278 Java_TabWebContentsDelegateAndroidImpl_onFindMatchRectsAvailable(
279 env, obj, details_object);
280 }
281
282 content::JavaScriptDialogManager*
GetJavaScriptDialogManager(WebContents * source)283 TabWebContentsDelegateAndroid::GetJavaScriptDialogManager(
284 WebContents* source) {
285 // For VR, we use app modal since the dialog view will cover the location bar.
286 if (!vr::VrTabHelper::IsInVr(source)) {
287 return javascript_dialogs::TabModalDialogManager::FromWebContents(source);
288 }
289 return javascript_dialogs::AppModalDialogManager::GetInstance();
290 }
291
AdjustPreviewsStateForNavigation(content::WebContents * web_contents,blink::PreviewsState * previews_state)292 void TabWebContentsDelegateAndroid::AdjustPreviewsStateForNavigation(
293 content::WebContents* web_contents,
294 blink::PreviewsState* previews_state) {
295 if (GetDisplayMode(web_contents) != blink::mojom::DisplayMode::kBrowser) {
296 *previews_state = blink::PreviewsTypes::PREVIEWS_OFF;
297 }
298 }
299
RequestMediaAccessPermission(content::WebContents * web_contents,const content::MediaStreamRequest & request,content::MediaResponseCallback callback)300 void TabWebContentsDelegateAndroid::RequestMediaAccessPermission(
301 content::WebContents* web_contents,
302 const content::MediaStreamRequest& request,
303 content::MediaResponseCallback callback) {
304 MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
305 web_contents, request, std::move(callback), nullptr);
306 }
307
CheckMediaAccessPermission(content::RenderFrameHost * render_frame_host,const GURL & security_origin,blink::mojom::MediaStreamType type)308 bool TabWebContentsDelegateAndroid::CheckMediaAccessPermission(
309 content::RenderFrameHost* render_frame_host,
310 const GURL& security_origin,
311 blink::mojom::MediaStreamType type) {
312 return MediaCaptureDevicesDispatcher::GetInstance()
313 ->CheckMediaAccessPermission(render_frame_host, security_origin, type);
314 }
315
SetOverlayMode(bool use_overlay_mode)316 void TabWebContentsDelegateAndroid::SetOverlayMode(bool use_overlay_mode) {
317 JNIEnv* env = base::android::AttachCurrentThread();
318 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
319 if (obj.is_null())
320 return;
321
322 Java_TabWebContentsDelegateAndroidImpl_setOverlayMode(env, obj,
323 use_overlay_mode);
324 }
325
RequestPpapiBrokerPermission(WebContents * web_contents,const GURL & url,const base::FilePath & plugin_path,base::OnceCallback<void (bool)> callback)326 void TabWebContentsDelegateAndroid::RequestPpapiBrokerPermission(
327 WebContents* web_contents,
328 const GURL& url,
329 const base::FilePath& plugin_path,
330 base::OnceCallback<void(bool)> callback) {
331 std::move(callback).Run(false);
332 }
333
OpenURLFromTab(WebContents * source,const content::OpenURLParams & params)334 WebContents* TabWebContentsDelegateAndroid::OpenURLFromTab(
335 WebContents* source,
336 const content::OpenURLParams& params) {
337 WindowOpenDisposition disposition = params.disposition;
338 if (!source || (disposition != WindowOpenDisposition::CURRENT_TAB &&
339 disposition != WindowOpenDisposition::NEW_FOREGROUND_TAB &&
340 disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB &&
341 disposition != WindowOpenDisposition::OFF_THE_RECORD &&
342 disposition != WindowOpenDisposition::NEW_POPUP &&
343 disposition != WindowOpenDisposition::NEW_WINDOW)) {
344 // We can't handle this here. Give the parent a chance.
345 return WebContentsDelegateAndroid::OpenURLFromTab(source, params);
346 }
347
348 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
349 NavigateParams nav_params(profile, params.url, params.transition);
350 nav_params.FillNavigateParamsFromOpenURLParams(params);
351 nav_params.source_contents = source;
352 nav_params.window_action = NavigateParams::SHOW_WINDOW;
353 auto popup_delegate =
354 std::make_unique<ChromePopupNavigationDelegate>(std::move(nav_params));
355 if (blocked_content::ConsiderForPopupBlocking(params.disposition)) {
356 popup_delegate.reset(static_cast<ChromePopupNavigationDelegate*>(
357 blocked_content::MaybeBlockPopup(
358 source, nullptr, std::move(popup_delegate), ¶ms,
359 blink::mojom::WindowFeatures(),
360 HostContentSettingsMapFactory::GetForProfile(
361 source->GetBrowserContext()))
362 .release()));
363 if (!popup_delegate)
364 return nullptr;
365 }
366
367 if (disposition == WindowOpenDisposition::CURRENT_TAB) {
368 // Ask the parent to handle in-place opening.
369 return WebContentsDelegateAndroid::OpenURLFromTab(source, params);
370 }
371
372 popup_delegate->nav_params()->created_with_opener = true;
373 TabModelList::HandlePopupNavigation(popup_delegate->nav_params());
374 return nullptr;
375 }
376
ShouldResumeRequestsForCreatedWindow()377 bool TabWebContentsDelegateAndroid::ShouldResumeRequestsForCreatedWindow() {
378 JNIEnv* env = base::android::AttachCurrentThread();
379 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
380 if (obj.is_null())
381 return true;
382
383 return Java_TabWebContentsDelegateAndroidImpl_shouldResumeRequestsForCreatedWindow(
384 env, obj);
385 }
386
AddNewContents(WebContents * source,std::unique_ptr<WebContents> new_contents,const GURL & target_url,WindowOpenDisposition disposition,const gfx::Rect & initial_rect,bool user_gesture,bool * was_blocked)387 void TabWebContentsDelegateAndroid::AddNewContents(
388 WebContents* source,
389 std::unique_ptr<WebContents> new_contents,
390 const GURL& target_url,
391 WindowOpenDisposition disposition,
392 const gfx::Rect& initial_rect,
393 bool user_gesture,
394 bool* was_blocked) {
395 // No code for this yet.
396 DCHECK_NE(disposition, WindowOpenDisposition::SAVE_TO_DISK);
397 // Can't create a new contents for the current tab - invalid case.
398 DCHECK_NE(disposition, WindowOpenDisposition::CURRENT_TAB);
399
400 // At this point the |new_contents| is beyond the popup blocker, but we use
401 // the same logic for determining if the popup tracker needs to be attached.
402 if (source && blocked_content::ConsiderForPopupBlocking(disposition)) {
403 blocked_content::PopupTracker::CreateForWebContents(new_contents.get(),
404 source, disposition);
405 }
406
407 TabHelpers::AttachTabHelpers(new_contents.get());
408
409 JNIEnv* env = AttachCurrentThread();
410 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
411 bool handled = false;
412 if (!obj.is_null()) {
413 ScopedJavaLocalRef<jobject> jsource;
414 if (source)
415 jsource = source->GetJavaWebContents();
416 ScopedJavaLocalRef<jobject> jnew_contents;
417 if (new_contents)
418 jnew_contents = new_contents->GetJavaWebContents();
419
420 handled = Java_TabWebContentsDelegateAndroidImpl_addNewContents(
421 env, obj, jsource, jnew_contents, static_cast<jint>(disposition),
422 nullptr, user_gesture);
423 }
424
425 if (was_blocked)
426 *was_blocked = !handled;
427
428 // When handled is |true|, ownership has been passed to java, which in turn
429 // creates a new TabAndroid instance to own the WebContents.
430 if (handled)
431 new_contents.release();
432 }
433
GetSecurityStyle(WebContents * web_contents,content::SecurityStyleExplanations * security_style_explanations)434 blink::SecurityStyle TabWebContentsDelegateAndroid::GetSecurityStyle(
435 WebContents* web_contents,
436 content::SecurityStyleExplanations* security_style_explanations) {
437 SecurityStateTabHelper* helper =
438 SecurityStateTabHelper::FromWebContents(web_contents);
439 DCHECK(helper);
440 return security_state::GetSecurityStyle(helper->GetSecurityLevel(),
441 *helper->GetVisibleSecurityState(),
442 security_style_explanations);
443 }
444
OnDidBlockNavigation(content::WebContents * web_contents,const GURL & blocked_url,const GURL & initiator_url,blink::mojom::NavigationBlockedReason reason)445 void TabWebContentsDelegateAndroid::OnDidBlockNavigation(
446 content::WebContents* web_contents,
447 const GURL& blocked_url,
448 const GURL& initiator_url,
449 blink::mojom::NavigationBlockedReason reason) {
450 ShowFramebustBlockInfobarInternal(web_contents, blocked_url);
451 }
452
UpdateUserGestureCarryoverInfo(content::WebContents * web_contents)453 void TabWebContentsDelegateAndroid::UpdateUserGestureCarryoverInfo(
454 content::WebContents* web_contents) {
455 auto* intercept_navigation_delegate =
456 navigation_interception::InterceptNavigationDelegate::Get(web_contents);
457 if (intercept_navigation_delegate)
458 intercept_navigation_delegate->UpdateLastUserGestureCarryoverTimestamp();
459 }
460
461 content::PictureInPictureResult
EnterPictureInPicture(content::WebContents * web_contents,const viz::SurfaceId & surface_id,const gfx::Size & natural_size)462 TabWebContentsDelegateAndroid::EnterPictureInPicture(
463 content::WebContents* web_contents,
464 const viz::SurfaceId& surface_id,
465 const gfx::Size& natural_size) {
466 return PictureInPictureWindowManager::GetInstance()->EnterPictureInPicture(
467 web_contents, surface_id, natural_size);
468 }
469
ExitPictureInPicture()470 void TabWebContentsDelegateAndroid::ExitPictureInPicture() {
471 PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
472 }
473
474 std::unique_ptr<content::WebContents>
ActivatePortalWebContents(content::WebContents * predecessor_contents,std::unique_ptr<content::WebContents> portal_contents)475 TabWebContentsDelegateAndroid::ActivatePortalWebContents(
476 content::WebContents* predecessor_contents,
477 std::unique_ptr<content::WebContents> portal_contents) {
478 const bool is_loading = portal_contents->IsLoading();
479 return TabAndroid::FromWebContents(predecessor_contents)
480 ->SwapWebContents(std::move(portal_contents),
481 /* did_start_load */ true,
482 /* did_finish_load */ !is_loading);
483 }
484
485 device::mojom::GeolocationContext*
GetInstalledWebappGeolocationContext()486 TabWebContentsDelegateAndroid::GetInstalledWebappGeolocationContext() {
487 if (!IsInstalledWebappDelegateGeolocation())
488 return nullptr;
489
490 if (!installed_webapp_geolocation_context_) {
491 installed_webapp_geolocation_context_ =
492 std::make_unique<InstalledWebappGeolocationContext>();
493 }
494 return installed_webapp_geolocation_context_.get();
495 }
496
497 #if BUILDFLAG(ENABLE_PRINTING)
PrintCrossProcessSubframe(content::WebContents * web_contents,const gfx::Rect & rect,int document_cookie,content::RenderFrameHost * subframe_host) const498 void TabWebContentsDelegateAndroid::PrintCrossProcessSubframe(
499 content::WebContents* web_contents,
500 const gfx::Rect& rect,
501 int document_cookie,
502 content::RenderFrameHost* subframe_host) const {
503 auto* client = printing::PrintCompositeClient::FromWebContents(web_contents);
504 if (client)
505 client->PrintCrossProcessSubframe(rect, document_cookie, subframe_host);
506 }
507 #endif
508
509 #if BUILDFLAG(ENABLE_PAINT_PREVIEW)
CapturePaintPreviewOfSubframe(content::WebContents * web_contents,const gfx::Rect & rect,const base::UnguessableToken & guid,content::RenderFrameHost * render_frame_host)510 void TabWebContentsDelegateAndroid::CapturePaintPreviewOfSubframe(
511 content::WebContents* web_contents,
512 const gfx::Rect& rect,
513 const base::UnguessableToken& guid,
514 content::RenderFrameHost* render_frame_host) {
515 auto* client =
516 paint_preview::PaintPreviewClient::FromWebContents(web_contents);
517 if (client)
518 client->CaptureSubframePaintPreview(guid, rect, render_frame_host);
519 }
520 #endif
521
OnFindResultAvailable(WebContents * web_contents)522 void TabWebContentsDelegateAndroid::OnFindResultAvailable(
523 WebContents* web_contents) {
524 JNIEnv* env = base::android::AttachCurrentThread();
525 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
526 if (obj.is_null())
527 return;
528
529 const find_in_page::FindNotificationDetails& find_result =
530 find_in_page::FindTabHelper::FromWebContents(web_contents)->find_result();
531
532 ScopedJavaLocalRef<jobject> selection_rect =
533 JNI_TabWebContentsDelegateAndroidImpl_CreateJavaRect(
534 env, find_result.selection_rect());
535
536 // Create the details object.
537 ScopedJavaLocalRef<jobject> details_object =
538 Java_TabWebContentsDelegateAndroidImpl_createFindNotificationDetails(
539 env, find_result.number_of_matches(), selection_rect,
540 find_result.active_match_ordinal(), find_result.final_update());
541
542 Java_TabWebContentsDelegateAndroidImpl_onFindResultAvailable(env, obj,
543 details_object);
544 }
545
OnFindTabHelperDestroyed(find_in_page::FindTabHelper * helper)546 void TabWebContentsDelegateAndroid::OnFindTabHelperDestroyed(
547 find_in_page::FindTabHelper* helper) {
548 find_result_observer_.Remove(helper);
549 }
550
ShouldEnableEmbeddedMediaExperience() const551 bool TabWebContentsDelegateAndroid::ShouldEnableEmbeddedMediaExperience()
552 const {
553 JNIEnv* env = base::android::AttachCurrentThread();
554 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
555 if (obj.is_null())
556 return false;
557 return Java_TabWebContentsDelegateAndroidImpl_shouldEnableEmbeddedMediaExperience(
558 env, obj);
559 }
560
IsPictureInPictureEnabled() const561 bool TabWebContentsDelegateAndroid::IsPictureInPictureEnabled() const {
562 JNIEnv* env = base::android::AttachCurrentThread();
563 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
564 if (obj.is_null())
565 return false;
566 return Java_TabWebContentsDelegateAndroidImpl_isPictureInPictureEnabled(env,
567 obj);
568 }
569
IsNightModeEnabled() const570 bool TabWebContentsDelegateAndroid::IsNightModeEnabled() const {
571 JNIEnv* env = base::android::AttachCurrentThread();
572 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
573 if (obj.is_null())
574 return false;
575 return Java_TabWebContentsDelegateAndroidImpl_isNightModeEnabled(env, obj);
576 }
577
CanShowAppBanners() const578 bool TabWebContentsDelegateAndroid::CanShowAppBanners() const {
579 JNIEnv* env = base::android::AttachCurrentThread();
580 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
581 if (obj.is_null())
582 return false;
583 return Java_TabWebContentsDelegateAndroidImpl_canShowAppBanners(env, obj);
584 }
585
GetManifestScope() const586 const GURL TabWebContentsDelegateAndroid::GetManifestScope() const {
587 JNIEnv* env = base::android::AttachCurrentThread();
588 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
589 if (obj.is_null())
590 return GURL();
591 const JavaRef<jstring>& scope =
592 Java_TabWebContentsDelegateAndroidImpl_getManifestScope(env, obj);
593 return scope.is_null() ? GURL()
594 : GURL(base::android::ConvertJavaStringToUTF8(scope));
595 }
596
IsCustomTab() const597 bool TabWebContentsDelegateAndroid::IsCustomTab() const {
598 JNIEnv* env = base::android::AttachCurrentThread();
599 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
600 if (obj.is_null())
601 return false;
602 return Java_TabWebContentsDelegateAndroidImpl_isCustomTab(env, obj);
603 }
604
IsInstalledWebappDelegateGeolocation() const605 bool TabWebContentsDelegateAndroid::IsInstalledWebappDelegateGeolocation()
606 const {
607 if (!base::FeatureList::IsEnabled(
608 chrome::android::kTrustedWebActivityLocationDelegation)) {
609 return false;
610 }
611
612 JNIEnv* env = base::android::AttachCurrentThread();
613 ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
614 if (obj.is_null())
615 return false;
616 return Java_TabWebContentsDelegateAndroidImpl_isInstalledWebappDelegateGeolocation(
617 env, obj);
618 }
619
620 } // namespace android
621
JNI_TabWebContentsDelegateAndroidImpl_OnRendererUnresponsive(JNIEnv * env,const JavaParamRef<jobject> & java_web_contents)622 void JNI_TabWebContentsDelegateAndroidImpl_OnRendererUnresponsive(
623 JNIEnv* env,
624 const JavaParamRef<jobject>& java_web_contents) {
625 // Rate limit the number of stack dumps so we don't overwhelm our crash
626 // reports.
627 content::WebContents* web_contents =
628 content::WebContents::FromJavaWebContents(java_web_contents);
629 if (base::RandDouble() < 0.01)
630 web_contents->GetMainFrame()->GetProcess()->DumpProcessStack();
631
632 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
633 switches::kEnableHungRendererInfoBar)) {
634 return;
635 }
636
637 InfoBarService* infobar_service =
638 InfoBarService::FromWebContents(web_contents);
639 DCHECK(!FindHungRendererInfoBar(infobar_service));
640 HungRendererInfoBarDelegate::Create(
641 infobar_service, web_contents->GetMainFrame()->GetProcess());
642 }
643
JNI_TabWebContentsDelegateAndroidImpl_OnRendererResponsive(JNIEnv * env,const JavaParamRef<jobject> & java_web_contents)644 void JNI_TabWebContentsDelegateAndroidImpl_OnRendererResponsive(
645 JNIEnv* env,
646 const JavaParamRef<jobject>& java_web_contents) {
647 content::WebContents* web_contents =
648 content::WebContents::FromJavaWebContents(java_web_contents);
649 InfoBarService* infobar_service =
650 InfoBarService::FromWebContents(web_contents);
651 infobars::InfoBar* hung_renderer_infobar =
652 FindHungRendererInfoBar(infobar_service);
653 if (!hung_renderer_infobar)
654 return;
655
656 hung_renderer_infobar->delegate()
657 ->AsHungRendererInfoBarDelegate()
658 ->OnRendererResponsive();
659 infobar_service->RemoveInfoBar(hung_renderer_infobar);
660 }
661
JNI_TabWebContentsDelegateAndroidImpl_ShowFramebustBlockInfoBar(JNIEnv * env,const JavaParamRef<jobject> & java_web_contents,const JavaParamRef<jstring> & java_url)662 void JNI_TabWebContentsDelegateAndroidImpl_ShowFramebustBlockInfoBar(
663 JNIEnv* env,
664 const JavaParamRef<jobject>& java_web_contents,
665 const JavaParamRef<jstring>& java_url) {
666 GURL url(base::android::ConvertJavaStringToUTF16(env, java_url));
667 content::WebContents* web_contents =
668 content::WebContents::FromJavaWebContents(java_web_contents);
669 ShowFramebustBlockInfobarInternal(web_contents, url);
670 }
671