tab_impl.cc 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462
  1. // Copyright 2019 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. #include "weblayer/browser/tab_impl.h"
  5. #include <cmath>
  6. #include "base/auto_reset.h"
  7. #include "base/bind.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/feature_list.h"
  10. #include "base/guid.h"
  11. #include "base/logging.h"
  12. #include "base/no_destructor.h"
  13. #include "base/task/thread_pool.h"
  14. #include "base/time/default_tick_clock.h"
  15. #include "build/build_config.h"
  16. #include "cc/layers/layer.h"
  17. #include "components/autofill/content/browser/content_autofill_driver_factory.h"
  18. #include "components/autofill/core/common/autofill_features.h"
  19. #include "components/blocked_content/popup_blocker.h"
  20. #include "components/blocked_content/popup_blocker_tab_helper.h"
  21. #include "components/blocked_content/popup_opener_tab_helper.h"
  22. #include "components/blocked_content/popup_tracker.h"
  23. #include "components/captive_portal/core/buildflags.h"
  24. #include "components/content_settings/browser/page_specific_content_settings.h"
  25. #include "components/embedder_support/user_agent_utils.h"
  26. #include "components/find_in_page/find_tab_helper.h"
  27. #include "components/find_in_page/find_types.h"
  28. #include "components/infobars/content/content_infobar_manager.h"
  29. #include "components/js_injection/browser/js_communication_host.h"
  30. #include "components/js_injection/browser/web_message_host.h"
  31. #include "components/js_injection/browser/web_message_host_factory.h"
  32. #include "components/permissions/permission_manager.h"
  33. #include "components/permissions/permission_request_manager.h"
  34. #include "components/permissions/permission_result.h"
  35. #include "components/prefs/pref_service.h"
  36. #include "components/safe_browsing/core/browser/db/database_manager.h"
  37. #include "components/sessions/content/session_tab_helper.h"
  38. #include "components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.h"
  39. #include "components/subresource_filter/content/browser/ruleset_service.h"
  40. #include "components/translate/core/browser/translate_manager.h"
  41. #include "components/ukm/content/source_url_recorder.h"
  42. #include "components/webapps/browser/installable/installable_manager.h"
  43. #include "components/webrtc/media_stream_devices_controller.h"
  44. #include "content/public/browser/browser_task_traits.h"
  45. #include "content/public/browser/browser_thread.h"
  46. #include "content/public/browser/context_menu_params.h"
  47. #include "content/public/browser/file_select_listener.h"
  48. #include "content/public/browser/navigation_controller.h"
  49. #include "content/public/browser/navigation_entry.h"
  50. #include "content/public/browser/navigation_handle.h"
  51. #include "content/public/browser/permission_controller.h"
  52. #include "content/public/browser/render_frame_host.h"
  53. #include "content/public/browser/render_view_host.h"
  54. #include "content/public/browser/render_widget_host_view.h"
  55. #include "content/public/browser/renderer_preferences_util.h"
  56. #include "content/public/browser/web_contents.h"
  57. #include "third_party/blink/public/common/permissions/permission_utils.h"
  58. #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
  59. #include "third_party/blink/public/common/web_preferences/web_preferences.h"
  60. #include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
  61. #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
  62. #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
  63. #include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
  64. #include "ui/base/window_open_disposition.h"
  65. #include "weblayer/browser/autofill_client_impl.h"
  66. #include "weblayer/browser/browser_context_impl.h"
  67. #include "weblayer/browser/browser_impl.h"
  68. #include "weblayer/browser/browser_process.h"
  69. #include "weblayer/browser/content_browser_client_impl.h"
  70. #include "weblayer/browser/favicon/favicon_fetcher_impl.h"
  71. #include "weblayer/browser/favicon/favicon_tab_helper.h"
  72. #include "weblayer/browser/file_select_helper.h"
  73. #include "weblayer/browser/host_content_settings_map_factory.h"
  74. #include "weblayer/browser/i18n_util.h"
  75. #include "weblayer/browser/js_communication/web_message_host_factory_wrapper.h"
  76. #include "weblayer/browser/navigation_controller_impl.h"
  77. #include "weblayer/browser/navigation_entry_data.h"
  78. #include "weblayer/browser/no_state_prefetch/prerender_tab_helper.h"
  79. #include "weblayer/browser/page_load_metrics_initialize.h"
  80. #include "weblayer/browser/page_specific_content_settings_delegate.h"
  81. #include "weblayer/browser/password_manager_driver_factory.h"
  82. #include "weblayer/browser/persistence/browser_persister.h"
  83. #include "weblayer/browser/popup_navigation_delegate_impl.h"
  84. #include "weblayer/browser/profile_impl.h"
  85. #include "weblayer/browser/safe_browsing/safe_browsing_service.h"
  86. #include "weblayer/browser/subresource_filter_profile_context_factory.h"
  87. #include "weblayer/browser/translate_client_impl.h"
  88. #include "weblayer/browser/weblayer_features.h"
  89. #include "weblayer/common/isolated_world_ids.h"
  90. #include "weblayer/public/fullscreen_delegate.h"
  91. #include "weblayer/public/js_communication/web_message.h"
  92. #include "weblayer/public/js_communication/web_message_host_factory.h"
  93. #include "weblayer/public/new_tab_delegate.h"
  94. #include "weblayer/public/tab_observer.h"
  95. #if !BUILDFLAG(IS_ANDROID)
  96. #include "ui/views/controls/webview/webview.h"
  97. #endif
  98. #if BUILDFLAG(IS_ANDROID)
  99. #include "base/android/callback_android.h"
  100. #include "base/android/jni_array.h"
  101. #include "base/android/jni_string.h"
  102. #include "base/json/json_writer.h"
  103. #include "base/trace_event/trace_event.h"
  104. #include "components/android_autofill/browser/android_autofill_manager.h"
  105. #include "components/android_autofill/browser/autofill_provider.h"
  106. #include "components/android_autofill/browser/autofill_provider_android.h"
  107. #include "components/browser_ui/sms/android/sms_infobar.h"
  108. #include "components/download/content/public/context_menu_download.h"
  109. #include "components/embedder_support/android/contextmenu/context_menu_builder.h"
  110. #include "components/embedder_support/android/delegate/color_chooser_android.h"
  111. #include "components/javascript_dialogs/tab_modal_dialog_manager.h" // nogncheck
  112. #include "components/safe_browsing/android/remote_database_manager.h"
  113. #include "components/safe_browsing/content/browser/safe_browsing_navigation_observer.h"
  114. #include "components/safe_browsing/content/browser/safe_browsing_tab_observer.h"
  115. #include "components/site_engagement/content/site_engagement_helper.h"
  116. #include "components/site_engagement/content/site_engagement_service.h"
  117. #include "components/translate/core/browser/translate_manager.h"
  118. #include "ui/android/view_android.h"
  119. #include "ui/gfx/android/java_bitmap.h"
  120. #include "weblayer/browser/browser_controls_container_view.h"
  121. #include "weblayer/browser/browser_controls_navigation_state_handler.h"
  122. #include "weblayer/browser/controls_visibility_reason.h"
  123. #include "weblayer/browser/java/jni/TabImpl_jni.h"
  124. #include "weblayer/browser/javascript_tab_modal_dialog_manager_delegate_android.h"
  125. #include "weblayer/browser/js_communication/web_message_host_factory_proxy.h"
  126. #include "weblayer/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h"
  127. #include "weblayer/browser/safe_browsing/weblayer_safe_browsing_tab_observer_delegate.h"
  128. #include "weblayer/browser/translate_client_impl.h"
  129. #include "weblayer/browser/url_bar/trusted_cdn_observer.h"
  130. #include "weblayer/browser/webapps/weblayer_app_banner_manager_android.h"
  131. #include "weblayer/browser/weblayer_factory_impl_android.h"
  132. #include "weblayer/browser/webrtc/media_stream_manager.h"
  133. #include "weblayer/common/features.h"
  134. #endif
  135. #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
  136. #include "components/captive_portal/content/captive_portal_tab_helper.h"
  137. #include "weblayer/browser/captive_portal_service_factory.h"
  138. #endif
  139. #if BUILDFLAG(IS_ANDROID)
  140. using base::android::AttachCurrentThread;
  141. using base::android::JavaParamRef;
  142. using base::android::ScopedJavaGlobalRef;
  143. using base::android::ScopedJavaLocalRef;
  144. #endif
  145. namespace weblayer {
  146. namespace {
  147. // Maximum size of data when calling SetData().
  148. constexpr int kMaxDataSize = 4096;
  149. #if BUILDFLAG(IS_ANDROID)
  150. bool g_system_autofill_disabled_for_testing = false;
  151. #endif
  152. NewTabType NewTabTypeFromWindowDisposition(WindowOpenDisposition disposition) {
  153. // WindowOpenDisposition has a *ton* of types, but the following are really
  154. // the only ones that should be hit for this code path.
  155. switch (disposition) {
  156. case WindowOpenDisposition::NEW_FOREGROUND_TAB:
  157. return NewTabType::kForeground;
  158. case WindowOpenDisposition::NEW_BACKGROUND_TAB:
  159. return NewTabType::kBackground;
  160. case WindowOpenDisposition::NEW_POPUP:
  161. return NewTabType::kNewPopup;
  162. case WindowOpenDisposition::NEW_WINDOW:
  163. return NewTabType::kNewWindow;
  164. default:
  165. // The set of allowed types are in
  166. // ContentTabClientImpl::CanCreateWindow().
  167. NOTREACHED();
  168. return NewTabType::kForeground;
  169. }
  170. }
  171. #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
  172. // Opens a captive portal login page in |web_contents|.
  173. void OpenCaptivePortalLoginTabInWebContents(
  174. content::WebContents* web_contents) {
  175. content::OpenURLParams params(
  176. CaptivePortalServiceFactory::GetForBrowserContext(
  177. web_contents->GetBrowserContext())
  178. ->test_url(),
  179. content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
  180. ui::PAGE_TRANSITION_LINK, false);
  181. web_contents->OpenURL(params);
  182. }
  183. #endif
  184. // Pointer value of this is used as a key in base::SupportsUserData for
  185. // WebContents. Value of the key is an instance of |UserData|.
  186. constexpr int kWebContentsUserDataKey = 0;
  187. struct UserData : public base::SupportsUserData::Data {
  188. TabImpl* tab = nullptr;
  189. };
  190. #if BUILDFLAG(IS_ANDROID)
  191. void HandleJavaScriptResult(const ScopedJavaGlobalRef<jobject>& callback,
  192. base::Value result) {
  193. std::string json;
  194. base::JSONWriter::Write(result, &json);
  195. base::android::RunStringCallbackAndroid(callback, json);
  196. }
  197. void OnConvertedToJavaBitmap(const ScopedJavaGlobalRef<jobject>& value_callback,
  198. const ScopedJavaGlobalRef<jobject>& java_bitmap) {
  199. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  200. TabImpl::ScreenShotErrors error =
  201. java_bitmap ? TabImpl::ScreenShotErrors::kNone
  202. : TabImpl::ScreenShotErrors::kBitmapAllocationFailed;
  203. Java_TabImpl_runCaptureScreenShotCallback(AttachCurrentThread(),
  204. value_callback, java_bitmap,
  205. static_cast<int>(error));
  206. }
  207. // Convert SkBitmap to java Bitmap on a background thread since it involves a
  208. // memcpy.
  209. void ConvertToJavaBitmapBackgroundThread(
  210. const SkBitmap& bitmap,
  211. base::OnceCallback<void(const ScopedJavaGlobalRef<jobject>&)> callback) {
  212. // Make sure to only pass ScopedJavaGlobalRef between threads.
  213. ScopedJavaGlobalRef<jobject> java_bitmap = ScopedJavaGlobalRef<jobject>(
  214. gfx::ConvertToJavaBitmap(bitmap, gfx::OomBehavior::kReturnNullOnOom));
  215. content::GetUIThreadTaskRunner({})->PostTask(
  216. FROM_HERE, base::BindOnce(std::move(callback), std::move(java_bitmap)));
  217. }
  218. void OnScreenShotCaptured(const ScopedJavaGlobalRef<jobject>& value_callback,
  219. const SkBitmap& bitmap) {
  220. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  221. if (bitmap.isNull() || bitmap.drawsNothing()) {
  222. Java_TabImpl_runCaptureScreenShotCallback(
  223. AttachCurrentThread(), value_callback, nullptr,
  224. static_cast<int>(TabImpl::ScreenShotErrors::kCaptureFailed));
  225. return;
  226. }
  227. // Not using PostTaskAndReplyWithResult to ensure ScopedJavaLocalRef is not
  228. // passed between threads.
  229. base::ThreadPool::PostTask(
  230. FROM_HERE,
  231. {base::TaskPriority::BEST_EFFORT,
  232. base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
  233. base::BindOnce(&ConvertToJavaBitmapBackgroundThread, bitmap,
  234. base::BindOnce(&OnConvertedToJavaBitmap, value_callback)));
  235. }
  236. #endif // BUILDFLAG(IS_ANDROID)
  237. std::set<TabImpl*>& GetTabs() {
  238. static base::NoDestructor<std::set<TabImpl*>> s_all_tab_impl;
  239. return *s_all_tab_impl;
  240. }
  241. // Returns a scoped refptr to the SafeBrowsingService's database manager, if
  242. // available. Otherwise returns nullptr.
  243. const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
  244. GetDatabaseManagerFromSafeBrowsingService() {
  245. #if BUILDFLAG(IS_ANDROID)
  246. SafeBrowsingService* safe_browsing_service =
  247. BrowserProcess::GetInstance()->GetSafeBrowsingService();
  248. return scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>(
  249. safe_browsing_service->GetSafeBrowsingDBManager());
  250. #else
  251. return nullptr;
  252. #endif
  253. }
  254. // Creates a ContentSubresourceFilterWebContentsHelper for |web_contents|,
  255. // passing it the needed embedder-level state.
  256. void CreateContentSubresourceFilterWebContentsHelper(
  257. content::WebContents* web_contents) {
  258. subresource_filter::RulesetService* ruleset_service =
  259. BrowserProcess::GetInstance()->subresource_filter_ruleset_service();
  260. subresource_filter::VerifiedRulesetDealer::Handle* dealer =
  261. ruleset_service ? ruleset_service->GetRulesetDealer() : nullptr;
  262. subresource_filter::ContentSubresourceFilterWebContentsHelper::
  263. CreateForWebContents(
  264. web_contents,
  265. SubresourceFilterProfileContextFactory::GetForBrowserContext(
  266. web_contents->GetBrowserContext()),
  267. GetDatabaseManagerFromSafeBrowsingService(), dealer);
  268. }
  269. } // namespace
  270. #if BUILDFLAG(IS_ANDROID)
  271. static ScopedJavaLocalRef<jobject> JNI_TabImpl_FromWebContents(
  272. JNIEnv* env,
  273. const base::android::JavaParamRef<jobject>& j_web_contents) {
  274. content::WebContents* web_contents =
  275. content::WebContents::FromJavaWebContents(j_web_contents);
  276. TabImpl* tab = TabImpl::FromWebContents(web_contents);
  277. if (tab)
  278. return ScopedJavaLocalRef<jobject>(tab->GetJavaTab());
  279. return nullptr;
  280. }
  281. static void JNI_TabImpl_DestroyContextMenuParams(
  282. JNIEnv* env,
  283. jlong native_context_menu_params) {
  284. // Note: this runs on the finalizer thread which isn't the UI thread.
  285. auto* context_menu_params =
  286. reinterpret_cast<content::ContextMenuParams*>(native_context_menu_params);
  287. delete context_menu_params;
  288. }
  289. TabImpl::TabImpl(ProfileImpl* profile,
  290. const JavaParamRef<jobject>& java_impl,
  291. std::unique_ptr<content::WebContents> web_contents)
  292. : TabImpl(profile, std::move(web_contents)) {
  293. java_impl_ = java_impl;
  294. }
  295. #endif
  296. TabImpl::TabImpl(ProfileImpl* profile,
  297. std::unique_ptr<content::WebContents> web_contents,
  298. const std::string& guid)
  299. : profile_(profile),
  300. web_contents_(std::move(web_contents)),
  301. guid_(guid.empty() ? base::GenerateGUID() : guid) {
  302. GetTabs().insert(this);
  303. DCHECK(web_contents_);
  304. // This code path is hit when the page requests a new tab, which should
  305. // only be possible from the same profile.
  306. DCHECK_EQ(profile_->GetBrowserContext(), web_contents_->GetBrowserContext());
  307. // FaviconTabHelper adds a WebContentsObserver. Create FaviconTabHelper
  308. // before |this| observes the WebContents to ensure favicons are reset before
  309. // notifying weblayer observers of changes.
  310. FaviconTabHelper::CreateForWebContents(web_contents_.get());
  311. UpdateRendererPrefs(false);
  312. locale_change_subscription_ =
  313. i18n::RegisterLocaleChangeCallback(base::BindRepeating(
  314. &TabImpl::UpdateRendererPrefs, base::Unretained(this), true));
  315. std::unique_ptr<UserData> user_data = std::make_unique<UserData>();
  316. user_data->tab = this;
  317. web_contents_->SetUserData(&kWebContentsUserDataKey, std::move(user_data));
  318. web_contents_->SetDelegate(this);
  319. Observe(web_contents_.get());
  320. navigation_controller_ = std::make_unique<NavigationControllerImpl>(this);
  321. find_in_page::FindTabHelper::CreateForWebContents(web_contents_.get());
  322. GetFindTabHelper()->AddObserver(this);
  323. TranslateClientImpl::CreateForWebContents(web_contents_.get());
  324. #if BUILDFLAG(IS_ANDROID)
  325. // infobars::ContentInfoBarManager must be created before
  326. // SubresourceFilterClientImpl as the latter depends on it.
  327. infobars::ContentInfoBarManager::CreateForWebContents(web_contents_.get());
  328. #endif
  329. CreateContentSubresourceFilterWebContentsHelper(web_contents_.get());
  330. sessions::SessionTabHelper::CreateForWebContents(
  331. web_contents_.get(),
  332. base::BindRepeating(&TabImpl::GetSessionServiceTabHelperDelegate));
  333. permissions::PermissionRequestManager::CreateForWebContents(
  334. web_contents_.get());
  335. content_settings::PageSpecificContentSettings::CreateForWebContents(
  336. web_contents_.get(),
  337. std::make_unique<PageSpecificContentSettingsDelegate>(
  338. web_contents_.get()));
  339. blocked_content::PopupBlockerTabHelper::CreateForWebContents(
  340. web_contents_.get());
  341. blocked_content::PopupOpenerTabHelper::CreateForWebContents(
  342. web_contents_.get(), base::DefaultTickClock::GetInstance(),
  343. HostContentSettingsMapFactory::GetForBrowserContext(
  344. web_contents_->GetBrowserContext()));
  345. PasswordManagerDriverFactory::CreateForWebContents(web_contents_.get());
  346. InitializePageLoadMetricsForWebContents(web_contents_.get());
  347. ukm::InitializeSourceUrlRecorderForWebContents(web_contents_.get());
  348. #if BUILDFLAG(IS_ANDROID)
  349. javascript_dialogs::TabModalDialogManager::CreateForWebContents(
  350. web_contents_.get(),
  351. std::make_unique<JavaScriptTabModalDialogManagerDelegateAndroid>(
  352. web_contents_.get()));
  353. browser_controls_navigation_state_handler_ =
  354. std::make_unique<BrowserControlsNavigationStateHandler>(
  355. web_contents_.get(), this);
  356. TrustedCDNObserver::CreateForWebContents(web_contents_.get());
  357. if (base::FeatureList::IsEnabled(
  358. features::kWebLayerClientSidePhishingDetection)) {
  359. safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(
  360. web_contents_.get(),
  361. std::make_unique<WebLayerSafeBrowsingTabObserverDelegate>());
  362. }
  363. if (site_engagement::SiteEngagementService::IsEnabled()) {
  364. site_engagement::SiteEngagementService::Helper::CreateForWebContents(
  365. web_contents_.get());
  366. }
  367. auto* browser_context =
  368. static_cast<BrowserContextImpl*>(web_contents_->GetBrowserContext());
  369. safe_browsing::SafeBrowsingNavigationObserver::MaybeCreateForWebContents(
  370. web_contents_.get(),
  371. HostContentSettingsMapFactory::GetForBrowserContext(browser_context),
  372. SafeBrowsingNavigationObserverManagerFactory::GetForBrowserContext(
  373. browser_context),
  374. browser_context->pref_service(),
  375. BrowserProcess::GetInstance()->GetSafeBrowsingService());
  376. #endif
  377. #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
  378. captive_portal::CaptivePortalTabHelper::CreateForWebContents(
  379. web_contents_.get(),
  380. CaptivePortalServiceFactory::GetForBrowserContext(
  381. web_contents_->GetBrowserContext()),
  382. base::BindRepeating(&OpenCaptivePortalLoginTabInWebContents,
  383. web_contents_.get()));
  384. #endif
  385. // PrerenderTabHelper adds a WebContentsObserver.
  386. PrerenderTabHelper::CreateForWebContents(web_contents_.get());
  387. webapps::InstallableManager::CreateForWebContents(web_contents_.get());
  388. #if BUILDFLAG(IS_ANDROID)
  389. // Must be created after InstallableManager.
  390. WebLayerAppBannerManagerAndroid::CreateForWebContents(web_contents_.get());
  391. #endif
  392. }
  393. TabImpl::~TabImpl() {
  394. DCHECK(!browser_);
  395. GetFindTabHelper()->RemoveObserver(this);
  396. // Delete the WebContents and related objects that may be observing
  397. // the WebContents now to avoid calling back when this object is partially
  398. // deleted. DidFinishNavigation() may be called while deleting WebContents,
  399. // so stop observing first. Similarly WebContents destructor can callback to
  400. // delegate such as NavigationStateChanged, so clear its Delegate as well.
  401. #if BUILDFLAG(IS_ANDROID)
  402. browser_controls_navigation_state_handler_.reset();
  403. #endif
  404. Observe(nullptr);
  405. web_contents_->SetDelegate(nullptr);
  406. if (navigation_controller_->should_delay_web_contents_deletion()) {
  407. // Some user-data on WebContents directly or indirectly references this.
  408. // Remove that linkage to avoid use-after-free.
  409. web_contents_->RemoveUserData(&kWebContentsUserDataKey);
  410. web_contents_->RemoveUserData(
  411. autofill::ContentAutofillDriverFactory::
  412. kContentAutofillDriverFactoryWebContentsUserDataKey);
  413. // Have Profile handle the task posting to ensure the WebContents is
  414. // deleted before Profile. To do otherwise means it would be possible for
  415. // the Profile to outlive the WebContents, which is problematic (crash).
  416. profile_->DeleteWebContentsSoon(std::move(web_contents_));
  417. }
  418. web_contents_.reset();
  419. GetTabs().erase(this);
  420. }
  421. // static
  422. TabImpl* TabImpl::FromWebContents(content::WebContents* web_contents) {
  423. if (!web_contents)
  424. return nullptr;
  425. UserData* user_data = reinterpret_cast<UserData*>(
  426. web_contents->GetUserData(&kWebContentsUserDataKey));
  427. return user_data ? user_data->tab : nullptr;
  428. }
  429. // static
  430. std::set<TabImpl*> TabImpl::GetAllTabImpl() {
  431. return GetTabs();
  432. }
  433. void TabImpl::AddDataObserver(DataObserver* observer) {
  434. data_observers_.AddObserver(observer);
  435. }
  436. void TabImpl::RemoveDataObserver(DataObserver* observer) {
  437. data_observers_.RemoveObserver(observer);
  438. }
  439. Browser* TabImpl::GetBrowser() {
  440. return browser_;
  441. }
  442. void TabImpl::SetErrorPageDelegate(ErrorPageDelegate* delegate) {
  443. error_page_delegate_ = delegate;
  444. }
  445. void TabImpl::SetFullscreenDelegate(FullscreenDelegate* delegate) {
  446. if (delegate == fullscreen_delegate_)
  447. return;
  448. const bool had_delegate = (fullscreen_delegate_ != nullptr);
  449. const bool has_delegate = (delegate != nullptr);
  450. // If currently fullscreen, and the delegate is being set to null, force an
  451. // exit now (otherwise the delegate can't take us out of fullscreen).
  452. if (is_fullscreen_ && fullscreen_delegate_ && had_delegate != has_delegate)
  453. OnExitFullscreen();
  454. fullscreen_delegate_ = delegate;
  455. // Whether fullscreen is enabled depends upon whether there is a delegate. If
  456. // having a delegate changed, then update the renderer (which is where
  457. // fullscreen enabled is tracked).
  458. if (had_delegate != has_delegate)
  459. web_contents_->OnWebPreferencesChanged();
  460. }
  461. void TabImpl::SetNewTabDelegate(NewTabDelegate* delegate) {
  462. new_tab_delegate_ = delegate;
  463. }
  464. void TabImpl::SetGoogleAccountsDelegate(GoogleAccountsDelegate* delegate) {
  465. google_accounts_delegate_ = delegate;
  466. }
  467. void TabImpl::AddObserver(TabObserver* observer) {
  468. observers_.AddObserver(observer);
  469. }
  470. void TabImpl::RemoveObserver(TabObserver* observer) {
  471. observers_.RemoveObserver(observer);
  472. }
  473. NavigationController* TabImpl::GetNavigationController() {
  474. return navigation_controller_.get();
  475. }
  476. void TabImpl::ExecuteScript(const std::u16string& script,
  477. bool use_separate_isolate,
  478. JavaScriptResultCallback callback) {
  479. if (use_separate_isolate) {
  480. web_contents_->GetPrimaryMainFrame()->ExecuteJavaScriptInIsolatedWorld(
  481. script, std::move(callback), ISOLATED_WORLD_ID_WEBLAYER);
  482. } else {
  483. content::RenderFrameHost::AllowInjectingJavaScript();
  484. web_contents_->GetPrimaryMainFrame()->ExecuteJavaScript(
  485. script, std::move(callback));
  486. }
  487. }
  488. const std::string& TabImpl::GetGuid() {
  489. return guid_;
  490. }
  491. void TabImpl::SetData(const std::map<std::string, std::string>& data) {
  492. bool result = SetDataInternal(data);
  493. DCHECK(result) << "Data given to SetData() was too large.";
  494. }
  495. const std::map<std::string, std::string>& TabImpl::GetData() {
  496. return data_;
  497. }
  498. std::u16string TabImpl::AddWebMessageHostFactory(
  499. std::unique_ptr<WebMessageHostFactory> factory,
  500. const std::u16string& js_object_name,
  501. const std::vector<std::string>& allowed_origin_rules) {
  502. if (!js_communication_host_) {
  503. js_communication_host_ =
  504. std::make_unique<js_injection::JsCommunicationHost>(
  505. web_contents_.get());
  506. }
  507. return js_communication_host_->AddWebMessageHostFactory(
  508. std::make_unique<WebMessageHostFactoryWrapper>(std::move(factory)),
  509. js_object_name, allowed_origin_rules);
  510. }
  511. void TabImpl::RemoveWebMessageHostFactory(
  512. const std::u16string& js_object_name) {
  513. if (js_communication_host_)
  514. js_communication_host_->RemoveWebMessageHostFactory(js_object_name);
  515. }
  516. void TabImpl::ExecuteScriptWithUserGestureForTests(
  517. const std::u16string& script) {
  518. web_contents_->GetPrimaryMainFrame()
  519. ->ExecuteJavaScriptWithUserGestureForTests(script, base::NullCallback());
  520. }
  521. std::unique_ptr<FaviconFetcher> TabImpl::CreateFaviconFetcher(
  522. FaviconFetcherDelegate* delegate) {
  523. return std::make_unique<FaviconFetcherImpl>(web_contents_.get(), delegate);
  524. }
  525. void TabImpl::SetTranslateTargetLanguage(
  526. const std::string& translate_target_lang) {
  527. translate::TranslateManager* translate_manager =
  528. TranslateClientImpl::FromWebContents(web_contents())
  529. ->GetTranslateManager();
  530. translate_manager->SetPredefinedTargetLanguage(
  531. translate_target_lang,
  532. /*should_auto_translate=*/true);
  533. }
  534. #if !BUILDFLAG(IS_ANDROID)
  535. void TabImpl::AttachToView(views::WebView* web_view) {
  536. web_view->SetWebContents(web_contents_.get());
  537. web_contents_->Focus();
  538. }
  539. #endif
  540. void TabImpl::WebPreferencesChanged() {
  541. web_contents_->OnWebPreferencesChanged();
  542. }
  543. void TabImpl::SetWebPreferences(blink::web_pref::WebPreferences* prefs) {
  544. prefs->fullscreen_supported = !!fullscreen_delegate_;
  545. if (!browser_)
  546. return;
  547. browser_->SetWebPreferences(prefs);
  548. }
  549. void TabImpl::OnGainedActive() {
  550. web_contents()->GetController().LoadIfNecessary();
  551. if (enter_fullscreen_on_gained_active_)
  552. EnterFullscreenImpl();
  553. }
  554. void TabImpl::OnLosingActive() {
  555. if (is_fullscreen_)
  556. web_contents_->ExitFullscreen(/* will_cause_resize */ false);
  557. }
  558. bool TabImpl::IsActive() {
  559. return browser_->GetActiveTab() == this;
  560. }
  561. void TabImpl::ShowContextMenu(const content::ContextMenuParams& params) {
  562. #if BUILDFLAG(IS_ANDROID)
  563. Java_TabImpl_showContextMenu(
  564. base::android::AttachCurrentThread(), java_impl_,
  565. context_menu::BuildJavaContextMenuParams(params),
  566. reinterpret_cast<jlong>(new content::ContextMenuParams(params)));
  567. #endif
  568. }
  569. #if BUILDFLAG(IS_ANDROID)
  570. // static
  571. void TabImpl::DisableAutofillSystemIntegrationForTesting() {
  572. g_system_autofill_disabled_for_testing = true;
  573. }
  574. static jlong JNI_TabImpl_CreateTab(JNIEnv* env,
  575. jlong profile,
  576. const JavaParamRef<jobject>& java_impl) {
  577. ProfileImpl* profile_impl = reinterpret_cast<ProfileImpl*>(profile);
  578. content::WebContents::CreateParams create_params(
  579. profile_impl->GetBrowserContext());
  580. create_params.initially_hidden = true;
  581. return reinterpret_cast<intptr_t>(new TabImpl(
  582. profile_impl, java_impl, content::WebContents::Create(create_params)));
  583. }
  584. static void JNI_TabImpl_DeleteTab(JNIEnv* env, jlong tab) {
  585. TabImpl* tab_impl = reinterpret_cast<TabImpl*>(tab);
  586. DCHECK(tab_impl);
  587. // RemoveTabBeforeDestroyingFromJava() should have been called before this,
  588. // which sets browser to null.
  589. DCHECK(!tab_impl->browser());
  590. delete tab_impl;
  591. }
  592. ScopedJavaLocalRef<jobject> TabImpl::GetWebContents(JNIEnv* env) {
  593. return web_contents_->GetJavaWebContents();
  594. }
  595. void TabImpl::SetBrowserControlsContainerViews(
  596. JNIEnv* env,
  597. jlong native_top_controls_container_view,
  598. jlong native_bottom_controls_container_view) {
  599. top_controls_container_view_ =
  600. reinterpret_cast<BrowserControlsContainerView*>(
  601. native_top_controls_container_view);
  602. bottom_controls_container_view_ =
  603. reinterpret_cast<BrowserControlsContainerView*>(
  604. native_bottom_controls_container_view);
  605. }
  606. void TabImpl::ExecuteScript(JNIEnv* env,
  607. const JavaParamRef<jstring>& script,
  608. bool use_separate_isolate,
  609. const JavaParamRef<jobject>& callback) {
  610. ScopedJavaGlobalRef<jobject> jcallback(env, callback);
  611. ExecuteScript(base::android::ConvertJavaStringToUTF16(script),
  612. use_separate_isolate,
  613. base::BindOnce(&HandleJavaScriptResult, jcallback));
  614. }
  615. void TabImpl::SetJavaImpl(JNIEnv* env, const JavaParamRef<jobject>& impl) {
  616. // This should only be called early on and only once.
  617. DCHECK(!java_impl_);
  618. java_impl_ = impl;
  619. }
  620. void TabImpl::InitializeAutofillIfNecessary(JNIEnv* env) {
  621. if (g_system_autofill_disabled_for_testing)
  622. return;
  623. if (!autofill::ContentAutofillDriverFactory::FromWebContents(
  624. web_contents_.get())) {
  625. InitializeAutofillDriver();
  626. }
  627. }
  628. void TabImpl::UpdateBrowserControlsConstraint(JNIEnv* env,
  629. jint constraint,
  630. jboolean animate) {
  631. current_browser_controls_visibility_constraint_ =
  632. static_cast<cc::BrowserControlsState>(constraint);
  633. // Passing BOTH here means that it doesn't matter what state the controls are
  634. // currently in; don't change the current state unless it's incompatible with
  635. // the new constraint.
  636. UpdateBrowserControlsState(cc::BrowserControlsState::kBoth, animate);
  637. }
  638. ScopedJavaLocalRef<jstring> TabImpl::GetGuid(JNIEnv* env) {
  639. return base::android::ConvertUTF8ToJavaString(AttachCurrentThread(),
  640. GetGuid());
  641. }
  642. TabImpl::ScreenShotErrors TabImpl::PrepareForCaptureScreenShot(
  643. float scale,
  644. content::RenderWidgetHostView** rwhv,
  645. gfx::Rect* src_rect,
  646. gfx::Size* output_size) {
  647. if (scale <= 0.f || scale > 1.f)
  648. return ScreenShotErrors::kScaleOutOfRange;
  649. if (!IsActive())
  650. return ScreenShotErrors::kTabNotActive;
  651. if (web_contents_->GetVisibility() != content::Visibility::VISIBLE)
  652. return ScreenShotErrors::kWebContentsNotVisible;
  653. if (!browser_ || !browser_->CompositorHasSurface())
  654. return ScreenShotErrors::kNoSurface;
  655. *rwhv = web_contents_->GetTopLevelRenderWidgetHostView();
  656. if (!*rwhv)
  657. return ScreenShotErrors::kNoRenderWidgetHostView;
  658. if (!(*rwhv)->GetNativeView()->GetWindowAndroid())
  659. return ScreenShotErrors::kNoWindowAndroid;
  660. *src_rect =
  661. gfx::Rect(web_contents_->GetNativeView()->GetPhysicalBackingSize());
  662. if (src_rect->IsEmpty())
  663. return ScreenShotErrors::kEmptyViewport;
  664. const int reduced_height =
  665. src_rect->height() -
  666. top_controls_container_view_->GetContentHeightDelta() -
  667. bottom_controls_container_view_->GetContentHeightDelta();
  668. if (reduced_height <= 0)
  669. return ScreenShotErrors::kHiddenByControls;
  670. src_rect->set_height(reduced_height);
  671. *output_size = gfx::ScaleToCeiledSize(src_rect->size(), scale, scale);
  672. if (output_size->IsEmpty())
  673. return ScreenShotErrors::kScaledToEmpty;
  674. return ScreenShotErrors::kNone;
  675. }
  676. void TabImpl::UpdateBrowserControlsState(cc::BrowserControlsState new_state,
  677. bool animate) {
  678. if (base::FeatureList::IsEnabled(kImmediatelyHideBrowserControlsForTest))
  679. animate = false;
  680. // The constraint is managed by Java code, so re-use the existing constraint
  681. // and only update the desired state.
  682. web_contents_->UpdateBrowserControlsState(
  683. current_browser_controls_visibility_constraint_, new_state, animate);
  684. }
  685. void TabImpl::CaptureScreenShot(
  686. JNIEnv* env,
  687. jfloat scale,
  688. const base::android::JavaParamRef<jobject>& value_callback) {
  689. content::RenderWidgetHostView* rwhv = nullptr;
  690. gfx::Rect src_rect;
  691. gfx::Size output_size;
  692. ScreenShotErrors error =
  693. PrepareForCaptureScreenShot(scale, &rwhv, &src_rect, &output_size);
  694. if (error != ScreenShotErrors::kNone) {
  695. Java_TabImpl_runCaptureScreenShotCallback(
  696. env, ScopedJavaLocalRef<jobject>(value_callback),
  697. ScopedJavaLocalRef<jobject>(), static_cast<int>(error));
  698. return;
  699. }
  700. rwhv->CopyFromSurface(
  701. src_rect, output_size,
  702. base::BindOnce(&OnScreenShotCaptured,
  703. ScopedJavaGlobalRef<jobject>(value_callback)));
  704. }
  705. jboolean TabImpl::SetData(
  706. JNIEnv* env,
  707. const base::android::JavaParamRef<jobjectArray>& data) {
  708. std::vector<std::string> flattened_map;
  709. base::android::AppendJavaStringArrayToStringVector(env, data, &flattened_map);
  710. std::map<std::string, std::string> data_map;
  711. for (size_t i = 0; i < flattened_map.size(); i += 2) {
  712. data_map.insert({flattened_map[i], flattened_map[i + 1]});
  713. }
  714. return SetDataInternal(data_map);
  715. }
  716. base::android::ScopedJavaLocalRef<jobjectArray> TabImpl::GetData(JNIEnv* env) {
  717. std::vector<std::string> flattened_map;
  718. for (const auto& kv : data_) {
  719. flattened_map.push_back(kv.first);
  720. flattened_map.push_back(kv.second);
  721. }
  722. return base::android::ToJavaArrayOfStrings(env, flattened_map);
  723. }
  724. jboolean TabImpl::IsRendererControllingBrowserControlsOffsets(JNIEnv* env) {
  725. return browser_controls_navigation_state_handler_
  726. ->IsRendererControllingOffsets();
  727. }
  728. base::android::ScopedJavaLocalRef<jstring> TabImpl::RegisterWebMessageCallback(
  729. JNIEnv* env,
  730. const base::android::JavaParamRef<jstring>& js_object_name,
  731. const base::android::JavaParamRef<jobjectArray>& js_origins,
  732. const base::android::JavaParamRef<jobject>& client) {
  733. auto proxy = std::make_unique<WebMessageHostFactoryProxy>(client);
  734. std::vector<std::string> origins;
  735. base::android::AppendJavaStringArrayToStringVector(env, js_origins, &origins);
  736. std::u16string result = AddWebMessageHostFactory(
  737. std::move(proxy),
  738. base::android::ConvertJavaStringToUTF16(env, js_object_name), origins);
  739. return base::android::ConvertUTF16ToJavaString(env, result);
  740. }
  741. void TabImpl::UnregisterWebMessageCallback(
  742. JNIEnv* env,
  743. const base::android::JavaParamRef<jstring>& js_object_name) {
  744. std::u16string name;
  745. base::android::ConvertJavaStringToUTF16(env, js_object_name, &name);
  746. RemoveWebMessageHostFactory(name);
  747. }
  748. jboolean TabImpl::CanTranslate(JNIEnv* env) {
  749. return TranslateClientImpl::FromWebContents(web_contents())
  750. ->GetTranslateManager()
  751. ->CanManuallyTranslate();
  752. }
  753. void TabImpl::ShowTranslateUi(JNIEnv* env) {
  754. TranslateClientImpl::FromWebContents(web_contents())
  755. ->ShowTranslateUiWhenReady();
  756. }
  757. void TabImpl::RemoveTabFromBrowserBeforeDestroying(JNIEnv* env) {
  758. DCHECK(browser_);
  759. browser_->RemoveTabBeforeDestroyingFromJava(this);
  760. }
  761. void TabImpl::SetTranslateTargetLanguage(
  762. JNIEnv* env,
  763. const base::android::JavaParamRef<jstring>& translate_target_lang) {
  764. SetTranslateTargetLanguage(
  765. base::android::ConvertJavaStringToUTF8(env, translate_target_lang));
  766. }
  767. void TabImpl::SetDesktopUserAgentEnabled(JNIEnv* env, jboolean enable) {
  768. if (desktop_user_agent_enabled_ == enable)
  769. return;
  770. desktop_user_agent_enabled_ = enable;
  771. // Reset state that an earlier call to Navigation::SetUserAgentString()
  772. // could have modified.
  773. embedder_support::SetDesktopUserAgentOverride(
  774. web_contents_.get(), embedder_support::GetUserAgentMetadata(),
  775. /* override_in_new_tabs= */ false);
  776. web_contents_->SetRendererInitiatedUserAgentOverrideOption(
  777. content::NavigationController::UA_OVERRIDE_INHERIT);
  778. content::NavigationEntry* entry =
  779. web_contents_->GetController().GetLastCommittedEntry();
  780. if (!entry)
  781. return;
  782. entry->SetIsOverridingUserAgent(enable);
  783. web_contents_->NotifyPreferencesChanged();
  784. web_contents_->GetController().Reload(
  785. content::ReloadType::ORIGINAL_REQUEST_URL, true);
  786. }
  787. jboolean TabImpl::IsDesktopUserAgentEnabled(JNIEnv* env) {
  788. auto* entry = web_contents_->GetController().GetLastCommittedEntry();
  789. if (!entry)
  790. return false;
  791. // The same user agent override mechanism is used for per-navigation user
  792. // agent and desktop mode. Make sure not to return desktop mode for
  793. // navigation entries which used a per-navigation user agent.
  794. auto* entry_data = NavigationEntryData::Get(entry);
  795. if (entry_data && entry_data->per_navigation_user_agent_override())
  796. return false;
  797. return entry->GetIsOverridingUserAgent();
  798. }
  799. void TabImpl::Download(JNIEnv* env, jlong native_context_menu_params) {
  800. auto* context_menu_params =
  801. reinterpret_cast<content::ContextMenuParams*>(native_context_menu_params);
  802. bool is_link = context_menu_params->media_type !=
  803. blink::mojom::ContextMenuDataMediaType::kImage &&
  804. context_menu_params->media_type !=
  805. blink::mojom::ContextMenuDataMediaType::kVideo;
  806. download::CreateContextMenuDownload(web_contents_.get(), *context_menu_params,
  807. std::string(), is_link);
  808. }
  809. #endif // BUILDFLAG(IS_ANDROID)
  810. content::WebContents* TabImpl::OpenURLFromTab(
  811. content::WebContents* source,
  812. const content::OpenURLParams& params) {
  813. if (blocked_content::ConsiderForPopupBlocking(params.disposition)) {
  814. bool blocked = blocked_content::MaybeBlockPopup(
  815. source, nullptr,
  816. std::make_unique<PopupNavigationDelegateImpl>(
  817. params, source, nullptr),
  818. &params, blink::mojom::WindowFeatures(),
  819. HostContentSettingsMapFactory::GetForBrowserContext(
  820. source->GetBrowserContext())) == nullptr;
  821. if (blocked)
  822. return nullptr;
  823. }
  824. if (params.disposition == WindowOpenDisposition::CURRENT_TAB) {
  825. source->GetController().LoadURLWithParams(
  826. content::NavigationController::LoadURLParams(params));
  827. return source;
  828. }
  829. // All URLs not opening in the current tab will get a new tab.
  830. std::unique_ptr<content::WebContents> new_tab_contents =
  831. content::WebContents::Create(content::WebContents::CreateParams(
  832. web_contents()->GetBrowserContext()));
  833. base::WeakPtr<content::WebContents> new_tab_contents_weak_ptr(
  834. new_tab_contents->GetWeakPtr());
  835. bool was_blocked = false;
  836. AddNewContents(web_contents(), std::move(new_tab_contents), params.url,
  837. params.disposition, {}, params.user_gesture, &was_blocked);
  838. if (was_blocked || !new_tab_contents_weak_ptr)
  839. return nullptr;
  840. new_tab_contents_weak_ptr->GetController().LoadURLWithParams(
  841. content::NavigationController::LoadURLParams(params));
  842. return new_tab_contents_weak_ptr.get();
  843. }
  844. void TabImpl::ShowRepostFormWarningDialog(content::WebContents* source) {
  845. #if BUILDFLAG(IS_ANDROID)
  846. Java_TabImpl_showRepostFormWarningDialog(base::android::AttachCurrentThread(),
  847. java_impl_);
  848. #else
  849. source->GetController().CancelPendingReload();
  850. #endif
  851. }
  852. void TabImpl::NavigationStateChanged(content::WebContents* source,
  853. content::InvalidateTypes changed_flags) {
  854. DCHECK_EQ(web_contents_.get(), source);
  855. if (changed_flags & content::INVALIDATE_TYPE_URL) {
  856. for (auto& observer : observers_)
  857. observer.DisplayedUrlChanged(source->GetVisibleURL());
  858. UpdateBrowserVisibleSecurityStateIfNecessary();
  859. }
  860. // TODO(crbug.com/1064582): INVALIDATE_TYPE_TITLE is called only when a title
  861. // is set on the active navigation entry, but not when the active entry
  862. // changes, so check INVALIDATE_TYPE_LOAD here as well. However this should
  863. // be fixed and INVALIDATE_TYPE_LOAD should be removed.
  864. if (changed_flags &
  865. (content::INVALIDATE_TYPE_TITLE | content::INVALIDATE_TYPE_LOAD)) {
  866. std::u16string title = web_contents_->GetTitle();
  867. if (title_ != title) {
  868. title_ = title;
  869. for (auto& observer : observers_)
  870. observer.OnTitleUpdated(title);
  871. }
  872. }
  873. }
  874. content::JavaScriptDialogManager* TabImpl::GetJavaScriptDialogManager(
  875. content::WebContents* web_contents) {
  876. #if BUILDFLAG(IS_ANDROID)
  877. return javascript_dialogs::TabModalDialogManager::FromWebContents(
  878. web_contents);
  879. #else
  880. return nullptr;
  881. #endif
  882. }
  883. #if BUILDFLAG(IS_ANDROID)
  884. std::unique_ptr<content::ColorChooser> TabImpl::OpenColorChooser(
  885. content::WebContents* web_contents,
  886. SkColor color,
  887. const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) {
  888. return std::make_unique<web_contents_delegate_android::ColorChooserAndroid>(
  889. web_contents, color, suggestions);
  890. }
  891. #endif
  892. void TabImpl::CreateSmsPrompt(content::RenderFrameHost* render_frame_host,
  893. const std::vector<url::Origin>& origin_list,
  894. const std::string& one_time_code,
  895. base::OnceClosure on_confirm,
  896. base::OnceClosure on_cancel) {
  897. #if BUILDFLAG(IS_ANDROID)
  898. auto* web_contents =
  899. content::WebContents::FromRenderFrameHost(render_frame_host);
  900. sms::SmsInfoBar::Create(
  901. web_contents,
  902. infobars::ContentInfoBarManager::FromWebContents(web_contents),
  903. origin_list, one_time_code, std::move(on_confirm), std::move(on_cancel));
  904. #else
  905. NOTREACHED();
  906. #endif
  907. }
  908. void TabImpl::RunFileChooser(
  909. content::RenderFrameHost* render_frame_host,
  910. scoped_refptr<content::FileSelectListener> listener,
  911. const blink::mojom::FileChooserParams& params) {
  912. FileSelectHelper::RunFileChooser(render_frame_host, std::move(listener),
  913. params);
  914. }
  915. int TabImpl::GetTopControlsHeight() {
  916. #if BUILDFLAG(IS_ANDROID)
  917. return top_controls_container_view_
  918. ? top_controls_container_view_->GetControlsHeight()
  919. : 0;
  920. #else
  921. return 0;
  922. #endif
  923. }
  924. int TabImpl::GetTopControlsMinHeight() {
  925. #if BUILDFLAG(IS_ANDROID)
  926. return top_controls_container_view_
  927. ? top_controls_container_view_->GetMinHeight()
  928. : 0;
  929. #else
  930. return 0;
  931. #endif
  932. }
  933. int TabImpl::GetBottomControlsHeight() {
  934. #if BUILDFLAG(IS_ANDROID)
  935. return bottom_controls_container_view_
  936. ? bottom_controls_container_view_->GetControlsHeight()
  937. : 0;
  938. #else
  939. return 0;
  940. #endif
  941. }
  942. bool TabImpl::DoBrowserControlsShrinkRendererSize(
  943. content::WebContents* web_contents) {
  944. #if BUILDFLAG(IS_ANDROID)
  945. TRACE_EVENT0("weblayer", "Java_TabImpl_doBrowserControlsShrinkRendererSize");
  946. return Java_TabImpl_doBrowserControlsShrinkRendererSize(AttachCurrentThread(),
  947. java_impl_);
  948. #else
  949. return false;
  950. #endif
  951. }
  952. bool TabImpl::ShouldAnimateBrowserControlsHeightChanges() {
  953. #if BUILDFLAG(IS_ANDROID)
  954. return top_controls_container_view_
  955. ? top_controls_container_view_
  956. ->ShouldAnimateBrowserControlsHeightChanges()
  957. : false;
  958. #else
  959. return false;
  960. #endif
  961. }
  962. bool TabImpl::OnlyExpandTopControlsAtPageTop() {
  963. #if BUILDFLAG(IS_ANDROID)
  964. return top_controls_container_view_
  965. ? top_controls_container_view_->OnlyExpandControlsAtPageTop()
  966. : false;
  967. #else
  968. return false;
  969. #endif
  970. }
  971. bool TabImpl::IsBackForwardCacheSupported() {
  972. return true;
  973. }
  974. void TabImpl::RequestMediaAccessPermission(
  975. content::WebContents* web_contents,
  976. const content::MediaStreamRequest& request,
  977. content::MediaResponseCallback callback) {
  978. #if BUILDFLAG(IS_ANDROID)
  979. MediaStreamManager::FromWebContents(web_contents)
  980. ->RequestMediaAccessPermission(request, std::move(callback));
  981. #else
  982. std::move(callback).Run(blink::mojom::StreamDevicesSet(),
  983. blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
  984. nullptr);
  985. #endif
  986. }
  987. bool TabImpl::CheckMediaAccessPermission(
  988. content::RenderFrameHost* render_frame_host,
  989. const GURL& security_origin,
  990. blink::mojom::MediaStreamType type) {
  991. DCHECK(type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE ||
  992. type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
  993. blink::PermissionType permission_type =
  994. type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE
  995. ? blink::PermissionType::AUDIO_CAPTURE
  996. : blink::PermissionType::VIDEO_CAPTURE;
  997. // TODO(crbug.com/1321100): Remove `security_origin`.
  998. if (render_frame_host->GetLastCommittedOrigin().GetURL() != security_origin) {
  999. return false;
  1000. }
  1001. // It is OK to ignore `security_origin` because it will be calculated from
  1002. // `render_frame_host` and we always ignore `requesting_origin` for
  1003. // `AUDIO_CAPTURE` and `VIDEO_CAPTURE`.
  1004. // `render_frame_host->GetMainFrame()->GetLastCommittedOrigin()` will be used
  1005. // instead.
  1006. return render_frame_host->GetBrowserContext()
  1007. ->GetPermissionController()
  1008. ->GetPermissionStatusForCurrentDocument(permission_type,
  1009. render_frame_host) ==
  1010. blink::mojom::PermissionStatus::GRANTED;
  1011. }
  1012. void TabImpl::EnterFullscreenModeForTab(
  1013. content::RenderFrameHost* requesting_frame,
  1014. const blink::mojom::FullscreenOptions& options) {
  1015. // TODO(crbug.com/1232147): support |options|.
  1016. if (is_fullscreen_) {
  1017. // Typically EnterFullscreenModeForTab() should not be called consecutively,
  1018. // but there may be corner cases with oopif that lead to multiple
  1019. // consecutive calls. Avoid notifying the delegate in this case.
  1020. return;
  1021. }
  1022. is_fullscreen_ = true;
  1023. if (!IsActive()) {
  1024. // Process the request the tab is made active.
  1025. enter_fullscreen_on_gained_active_ = true;
  1026. return;
  1027. }
  1028. EnterFullscreenImpl();
  1029. }
  1030. void TabImpl::ExitFullscreenModeForTab(content::WebContents* web_contents) {
  1031. weak_ptr_factory_for_fullscreen_exit_.InvalidateWeakPtrs();
  1032. is_fullscreen_ = false;
  1033. if (enter_fullscreen_on_gained_active_)
  1034. enter_fullscreen_on_gained_active_ = false;
  1035. else
  1036. fullscreen_delegate_->ExitFullscreen();
  1037. #if BUILDFLAG(IS_ANDROID)
  1038. // Attempt to show browser controls when exiting fullscreen.
  1039. SetBrowserControlsConstraint(ControlsVisibilityReason::kFullscreen,
  1040. cc::BrowserControlsState::kBoth);
  1041. #endif
  1042. }
  1043. bool TabImpl::IsFullscreenForTabOrPending(
  1044. const content::WebContents* web_contents) {
  1045. return is_fullscreen_;
  1046. }
  1047. blink::mojom::DisplayMode TabImpl::GetDisplayMode(
  1048. const content::WebContents* web_contents) {
  1049. return is_fullscreen_ ? blink::mojom::DisplayMode::kFullscreen
  1050. : blink::mojom::DisplayMode::kBrowser;
  1051. }
  1052. void TabImpl::AddNewContents(content::WebContents* source,
  1053. std::unique_ptr<content::WebContents> new_contents,
  1054. const GURL& target_url,
  1055. WindowOpenDisposition disposition,
  1056. const gfx::Rect& initial_rect,
  1057. bool user_gesture,
  1058. bool* was_blocked) {
  1059. if (!new_tab_delegate_) {
  1060. *was_blocked = true;
  1061. return;
  1062. }
  1063. // At this point the |new_contents| is beyond the popup blocker, but we use
  1064. // the same logic for determining if the popup tracker needs to be attached.
  1065. if (source && blocked_content::ConsiderForPopupBlocking(disposition)) {
  1066. blocked_content::PopupTracker::CreateForWebContents(new_contents.get(),
  1067. source, disposition);
  1068. }
  1069. new_tab_delegate_->OnNewTab(browser_->CreateTab(std::move(new_contents)),
  1070. NewTabTypeFromWindowDisposition(disposition));
  1071. }
  1072. void TabImpl::CloseContents(content::WebContents* source) {
  1073. // The only time that |browser_| is null is during shutdown, and this callback
  1074. // shouldn't come in at that time.
  1075. DCHECK(browser_);
  1076. #if BUILDFLAG(IS_ANDROID)
  1077. JNIEnv* env = AttachCurrentThread();
  1078. Java_TabImpl_handleCloseFromWebContents(env, java_impl_);
  1079. // The above call resulted in the destruction of this; nothing to do but
  1080. // return.
  1081. #else
  1082. browser_->DestroyTab(this);
  1083. #endif
  1084. }
  1085. void TabImpl::FindReply(content::WebContents* web_contents,
  1086. int request_id,
  1087. int number_of_matches,
  1088. const gfx::Rect& selection_rect,
  1089. int active_match_ordinal,
  1090. bool final_update) {
  1091. GetFindTabHelper()->HandleFindReply(request_id, number_of_matches,
  1092. selection_rect, active_match_ordinal,
  1093. final_update);
  1094. }
  1095. #if BUILDFLAG(IS_ANDROID)
  1096. // FindMatchRectsReply and OnFindResultAvailable forward find-related results to
  1097. // the Java TabImpl. The find actions themselves are initiated directly from
  1098. // Java via FindInPageBridge.
  1099. void TabImpl::FindMatchRectsReply(content::WebContents* web_contents,
  1100. int version,
  1101. const std::vector<gfx::RectF>& rects,
  1102. const gfx::RectF& active_rect) {
  1103. JNIEnv* env = AttachCurrentThread();
  1104. // Create the details object.
  1105. ScopedJavaLocalRef<jobject> details_object =
  1106. Java_TabImpl_createFindMatchRectsDetails(
  1107. env, version, rects.size(),
  1108. ScopedJavaLocalRef<jobject>(Java_TabImpl_createRectF(
  1109. env, active_rect.x(), active_rect.y(), active_rect.right(),
  1110. active_rect.bottom())));
  1111. // Add the rects.
  1112. for (size_t i = 0; i < rects.size(); ++i) {
  1113. const gfx::RectF& rect = rects[i];
  1114. Java_TabImpl_setMatchRectByIndex(
  1115. env, details_object, i,
  1116. ScopedJavaLocalRef<jobject>(Java_TabImpl_createRectF(
  1117. env, rect.x(), rect.y(), rect.right(), rect.bottom())));
  1118. }
  1119. Java_TabImpl_onFindMatchRectsAvailable(env, java_impl_, details_object);
  1120. }
  1121. #endif
  1122. void TabImpl::PrimaryMainFrameRenderProcessGone(
  1123. base::TerminationStatus status) {
  1124. #if BUILDFLAG(IS_ANDROID)
  1125. // If a renderer process is lost when the tab is not visible, indicate to the
  1126. // WebContents that it should automatically reload the next time it becomes
  1127. // visible.
  1128. JNIEnv* env = AttachCurrentThread();
  1129. if (Java_TabImpl_willAutomaticallyReloadAfterCrashImpl(env, java_impl_))
  1130. web_contents()->GetController().SetNeedsReload();
  1131. #endif
  1132. for (auto& observer : observers_)
  1133. observer.OnRenderProcessGone();
  1134. }
  1135. void TabImpl::OnFindResultAvailable(content::WebContents* web_contents) {
  1136. #if BUILDFLAG(IS_ANDROID)
  1137. const find_in_page::FindNotificationDetails& find_result =
  1138. GetFindTabHelper()->find_result();
  1139. JNIEnv* env = AttachCurrentThread();
  1140. Java_TabImpl_onFindResultAvailable(
  1141. env, java_impl_, find_result.number_of_matches(),
  1142. find_result.active_match_ordinal(), find_result.final_update());
  1143. #endif
  1144. }
  1145. #if BUILDFLAG(IS_ANDROID)
  1146. void TabImpl::OnBrowserControlsStateStateChanged(
  1147. ControlsVisibilityReason reason,
  1148. cc::BrowserControlsState state) {
  1149. SetBrowserControlsConstraint(reason, state);
  1150. }
  1151. void TabImpl::OnUpdateBrowserControlsStateBecauseOfProcessSwitch(
  1152. bool did_commit) {
  1153. // This matches the logic of updateAfterRendererProcessSwitch() and
  1154. // updateEnabledState() in Chrome's TabBrowserControlsConstraintsHelper.
  1155. if (did_commit &&
  1156. current_browser_controls_visibility_constraint_ ==
  1157. cc::BrowserControlsState::kShown &&
  1158. top_controls_container_view_ &&
  1159. top_controls_container_view_->IsFullyVisible()) {
  1160. // The top-control is fully visible, don't animate this else the controls
  1161. // bounce around.
  1162. UpdateBrowserControlsState(cc::BrowserControlsState::kShown, false);
  1163. } else {
  1164. if (did_commit && current_browser_controls_visibility_constraint_ ==
  1165. cc::BrowserControlsState::kBoth) {
  1166. // If the current state is kBoth, then
  1167. // TabImpl::UpdateBrowserControlsState() is going to call
  1168. // WebContents::UpdateBrowserControlsState() with both current and
  1169. // constraints set to kBoth. cc does
  1170. // nothing in this case. During a navigation the top-view needs to be
  1171. // shown. To force the top-view to show, supply
  1172. // kShown. This path is only hit if top-view
  1173. // is configured to only-expand-at-top, as in this case the top-view isn't
  1174. // forced shown during a page load.
  1175. //
  1176. // It's entirely possible the scroll offset is changed as part of the
  1177. // loading process (such as happens with back/forward navigation or
  1178. // links part way down a page). Trying to detect this and compensate
  1179. // here is likely to be racy, so the top-view is always shown.
  1180. const bool animate =
  1181. !base::FeatureList::IsEnabled(kImmediatelyHideBrowserControlsForTest);
  1182. web_contents_->UpdateBrowserControlsState(
  1183. cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown,
  1184. animate);
  1185. // This falls through to call UpdateBrowserControlsState() again to
  1186. // ensure the constraint is set back to BOTH.
  1187. }
  1188. UpdateBrowserControlsState(
  1189. cc::BrowserControlsState::kBoth,
  1190. current_browser_controls_visibility_constraint_ !=
  1191. cc::BrowserControlsState::kHidden);
  1192. }
  1193. }
  1194. #endif
  1195. void TabImpl::DidChangeVisibleSecurityState() {
  1196. UpdateBrowserVisibleSecurityStateIfNecessary();
  1197. }
  1198. void TabImpl::UpdateBrowserVisibleSecurityStateIfNecessary() {
  1199. if (browser_ && browser_->GetActiveTab() == this)
  1200. browser_->VisibleSecurityStateOfActiveTabChanged();
  1201. }
  1202. void TabImpl::OnExitFullscreen() {
  1203. // If |processing_enter_fullscreen_| is true, it means the callback is being
  1204. // called while processing EnterFullscreenModeForTab(). WebContents doesn't
  1205. // deal well with this. FATAL as Android generally doesn't run with DCHECKs.
  1206. LOG_IF(FATAL, processing_enter_fullscreen_)
  1207. << "exiting fullscreen while entering fullscreen is not supported";
  1208. web_contents_->ExitFullscreen(/* will_cause_resize */ false);
  1209. }
  1210. void TabImpl::UpdateRendererPrefs(bool should_sync_prefs) {
  1211. blink::RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
  1212. content::UpdateFontRendererPreferencesFromSystemSettings(prefs);
  1213. prefs->accept_languages = i18n::GetAcceptLangs();
  1214. if (should_sync_prefs)
  1215. web_contents_->SyncRendererPrefs();
  1216. }
  1217. #if BUILDFLAG(IS_ANDROID)
  1218. void TabImpl::SetBrowserControlsConstraint(
  1219. ControlsVisibilityReason reason,
  1220. cc::BrowserControlsState constraint) {
  1221. Java_TabImpl_setBrowserControlsVisibilityConstraint(
  1222. base::android::AttachCurrentThread(), java_impl_,
  1223. static_cast<int>(reason), static_cast<int>(constraint));
  1224. }
  1225. void TabImpl::InitializeAutofillForTests() {
  1226. InitializeAutofillDriver();
  1227. }
  1228. void TabImpl::InitializeAutofillDriver() {
  1229. content::WebContents* web_contents = web_contents_.get();
  1230. DCHECK(
  1231. !autofill::ContentAutofillDriverFactory::FromWebContents(web_contents));
  1232. DCHECK(autofill::AutofillProvider::FromWebContents(web_contents));
  1233. AutofillClientImpl::CreateForWebContents(web_contents);
  1234. autofill::ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
  1235. web_contents, AutofillClientImpl::FromWebContents(web_contents),
  1236. base::BindRepeating(&autofill::AndroidDriverInitHook,
  1237. AutofillClientImpl::FromWebContents(web_contents),
  1238. autofill::AutofillManager::EnableDownloadManager(
  1239. !autofill::AutofillProvider::
  1240. is_download_manager_disabled_for_testing())));
  1241. }
  1242. #endif // BUILDFLAG(IS_ANDROID)
  1243. find_in_page::FindTabHelper* TabImpl::GetFindTabHelper() {
  1244. return find_in_page::FindTabHelper::FromWebContents(web_contents_.get());
  1245. }
  1246. // static
  1247. sessions::SessionTabHelperDelegate* TabImpl::GetSessionServiceTabHelperDelegate(
  1248. content::WebContents* web_contents) {
  1249. TabImpl* tab = FromWebContents(web_contents);
  1250. return (tab && tab->browser_) ? tab->browser_->browser_persister() : nullptr;
  1251. }
  1252. bool TabImpl::SetDataInternal(const std::map<std::string, std::string>& data) {
  1253. int total_size = 0;
  1254. for (const auto& kv : data)
  1255. total_size += kv.first.size() + kv.second.size();
  1256. if (total_size > kMaxDataSize)
  1257. return false;
  1258. data_ = data;
  1259. for (auto& observer : data_observers_)
  1260. observer.OnDataChanged(this, data_);
  1261. return true;
  1262. }
  1263. void TabImpl::EnterFullscreenImpl() {
  1264. // This ensures the existing callback is ignored.
  1265. weak_ptr_factory_for_fullscreen_exit_.InvalidateWeakPtrs();
  1266. auto exit_fullscreen_closure =
  1267. base::BindOnce(&TabImpl::OnExitFullscreen,
  1268. weak_ptr_factory_for_fullscreen_exit_.GetWeakPtr());
  1269. base::AutoReset<bool> reset(&processing_enter_fullscreen_, true);
  1270. fullscreen_delegate_->EnterFullscreen(std::move(exit_fullscreen_closure));
  1271. #if BUILDFLAG(IS_ANDROID)
  1272. // Make sure browser controls cannot show when the tab is fullscreen.
  1273. SetBrowserControlsConstraint(ControlsVisibilityReason::kFullscreen,
  1274. cc::BrowserControlsState::kHidden);
  1275. #endif
  1276. }
  1277. } // namespace weblayer