1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "weblayer/browser/tab_impl.h"
- #include <cmath>
- #include "base/auto_reset.h"
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/feature_list.h"
- #include "base/guid.h"
- #include "base/logging.h"
- #include "base/no_destructor.h"
- #include "base/task/thread_pool.h"
- #include "base/time/default_tick_clock.h"
- #include "build/build_config.h"
- #include "cc/layers/layer.h"
- #include "components/autofill/content/browser/content_autofill_driver_factory.h"
- #include "components/autofill/core/common/autofill_features.h"
- #include "components/blocked_content/popup_blocker.h"
- #include "components/blocked_content/popup_blocker_tab_helper.h"
- #include "components/blocked_content/popup_opener_tab_helper.h"
- #include "components/blocked_content/popup_tracker.h"
- #include "components/captive_portal/core/buildflags.h"
- #include "components/content_settings/browser/page_specific_content_settings.h"
- #include "components/embedder_support/user_agent_utils.h"
- #include "components/find_in_page/find_tab_helper.h"
- #include "components/find_in_page/find_types.h"
- #include "components/infobars/content/content_infobar_manager.h"
- #include "components/js_injection/browser/js_communication_host.h"
- #include "components/js_injection/browser/web_message_host.h"
- #include "components/js_injection/browser/web_message_host_factory.h"
- #include "components/permissions/permission_manager.h"
- #include "components/permissions/permission_request_manager.h"
- #include "components/permissions/permission_result.h"
- #include "components/prefs/pref_service.h"
- #include "components/safe_browsing/core/browser/db/database_manager.h"
- #include "components/sessions/content/session_tab_helper.h"
- #include "components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.h"
- #include "components/subresource_filter/content/browser/ruleset_service.h"
- #include "components/translate/core/browser/translate_manager.h"
- #include "components/ukm/content/source_url_recorder.h"
- #include "components/webapps/browser/installable/installable_manager.h"
- #include "components/webrtc/media_stream_devices_controller.h"
- #include "content/public/browser/browser_task_traits.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/browser/context_menu_params.h"
- #include "content/public/browser/file_select_listener.h"
- #include "content/public/browser/navigation_controller.h"
- #include "content/public/browser/navigation_entry.h"
- #include "content/public/browser/navigation_handle.h"
- #include "content/public/browser/permission_controller.h"
- #include "content/public/browser/render_frame_host.h"
- #include "content/public/browser/render_view_host.h"
- #include "content/public/browser/render_widget_host_view.h"
- #include "content/public/browser/renderer_preferences_util.h"
- #include "content/public/browser/web_contents.h"
- #include "third_party/blink/public/common/permissions/permission_utils.h"
- #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
- #include "third_party/blink/public/common/web_preferences/web_preferences.h"
- #include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
- #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
- #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
- #include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
- #include "ui/base/window_open_disposition.h"
- #include "weblayer/browser/autofill_client_impl.h"
- #include "weblayer/browser/browser_context_impl.h"
- #include "weblayer/browser/browser_impl.h"
- #include "weblayer/browser/browser_process.h"
- #include "weblayer/browser/content_browser_client_impl.h"
- #include "weblayer/browser/favicon/favicon_fetcher_impl.h"
- #include "weblayer/browser/favicon/favicon_tab_helper.h"
- #include "weblayer/browser/file_select_helper.h"
- #include "weblayer/browser/host_content_settings_map_factory.h"
- #include "weblayer/browser/i18n_util.h"
- #include "weblayer/browser/js_communication/web_message_host_factory_wrapper.h"
- #include "weblayer/browser/navigation_controller_impl.h"
- #include "weblayer/browser/navigation_entry_data.h"
- #include "weblayer/browser/no_state_prefetch/prerender_tab_helper.h"
- #include "weblayer/browser/page_load_metrics_initialize.h"
- #include "weblayer/browser/page_specific_content_settings_delegate.h"
- #include "weblayer/browser/password_manager_driver_factory.h"
- #include "weblayer/browser/persistence/browser_persister.h"
- #include "weblayer/browser/popup_navigation_delegate_impl.h"
- #include "weblayer/browser/profile_impl.h"
- #include "weblayer/browser/safe_browsing/safe_browsing_service.h"
- #include "weblayer/browser/subresource_filter_profile_context_factory.h"
- #include "weblayer/browser/translate_client_impl.h"
- #include "weblayer/browser/weblayer_features.h"
- #include "weblayer/common/isolated_world_ids.h"
- #include "weblayer/public/fullscreen_delegate.h"
- #include "weblayer/public/js_communication/web_message.h"
- #include "weblayer/public/js_communication/web_message_host_factory.h"
- #include "weblayer/public/new_tab_delegate.h"
- #include "weblayer/public/tab_observer.h"
- #if !BUILDFLAG(IS_ANDROID)
- #include "ui/views/controls/webview/webview.h"
- #endif
- #if BUILDFLAG(IS_ANDROID)
- #include "base/android/callback_android.h"
- #include "base/android/jni_array.h"
- #include "base/android/jni_string.h"
- #include "base/json/json_writer.h"
- #include "base/trace_event/trace_event.h"
- #include "components/android_autofill/browser/android_autofill_manager.h"
- #include "components/android_autofill/browser/autofill_provider.h"
- #include "components/android_autofill/browser/autofill_provider_android.h"
- #include "components/browser_ui/sms/android/sms_infobar.h"
- #include "components/download/content/public/context_menu_download.h"
- #include "components/embedder_support/android/contextmenu/context_menu_builder.h"
- #include "components/embedder_support/android/delegate/color_chooser_android.h"
- #include "components/javascript_dialogs/tab_modal_dialog_manager.h" // nogncheck
- #include "components/safe_browsing/android/remote_database_manager.h"
- #include "components/safe_browsing/content/browser/safe_browsing_navigation_observer.h"
- #include "components/safe_browsing/content/browser/safe_browsing_tab_observer.h"
- #include "components/site_engagement/content/site_engagement_helper.h"
- #include "components/site_engagement/content/site_engagement_service.h"
- #include "components/translate/core/browser/translate_manager.h"
- #include "ui/android/view_android.h"
- #include "ui/gfx/android/java_bitmap.h"
- #include "weblayer/browser/browser_controls_container_view.h"
- #include "weblayer/browser/browser_controls_navigation_state_handler.h"
- #include "weblayer/browser/controls_visibility_reason.h"
- #include "weblayer/browser/java/jni/TabImpl_jni.h"
- #include "weblayer/browser/javascript_tab_modal_dialog_manager_delegate_android.h"
- #include "weblayer/browser/js_communication/web_message_host_factory_proxy.h"
- #include "weblayer/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h"
- #include "weblayer/browser/safe_browsing/weblayer_safe_browsing_tab_observer_delegate.h"
- #include "weblayer/browser/translate_client_impl.h"
- #include "weblayer/browser/url_bar/trusted_cdn_observer.h"
- #include "weblayer/browser/webapps/weblayer_app_banner_manager_android.h"
- #include "weblayer/browser/weblayer_factory_impl_android.h"
- #include "weblayer/browser/webrtc/media_stream_manager.h"
- #include "weblayer/common/features.h"
- #endif
- #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
- #include "components/captive_portal/content/captive_portal_tab_helper.h"
- #include "weblayer/browser/captive_portal_service_factory.h"
- #endif
- #if BUILDFLAG(IS_ANDROID)
- using base::android::AttachCurrentThread;
- using base::android::JavaParamRef;
- using base::android::ScopedJavaGlobalRef;
- using base::android::ScopedJavaLocalRef;
- #endif
- namespace weblayer {
- namespace {
- // Maximum size of data when calling SetData().
- constexpr int kMaxDataSize = 4096;
- #if BUILDFLAG(IS_ANDROID)
- bool g_system_autofill_disabled_for_testing = false;
- #endif
- NewTabType NewTabTypeFromWindowDisposition(WindowOpenDisposition disposition) {
- // WindowOpenDisposition has a *ton* of types, but the following are really
- // the only ones that should be hit for this code path.
- switch (disposition) {
- case WindowOpenDisposition::NEW_FOREGROUND_TAB:
- return NewTabType::kForeground;
- case WindowOpenDisposition::NEW_BACKGROUND_TAB:
- return NewTabType::kBackground;
- case WindowOpenDisposition::NEW_POPUP:
- return NewTabType::kNewPopup;
- case WindowOpenDisposition::NEW_WINDOW:
- return NewTabType::kNewWindow;
- default:
- // The set of allowed types are in
- // ContentTabClientImpl::CanCreateWindow().
- NOTREACHED();
- return NewTabType::kForeground;
- }
- }
- #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
- // Opens a captive portal login page in |web_contents|.
- void OpenCaptivePortalLoginTabInWebContents(
- content::WebContents* web_contents) {
- content::OpenURLParams params(
- CaptivePortalServiceFactory::GetForBrowserContext(
- web_contents->GetBrowserContext())
- ->test_url(),
- content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui::PAGE_TRANSITION_LINK, false);
- web_contents->OpenURL(params);
- }
- #endif
- // Pointer value of this is used as a key in base::SupportsUserData for
- // WebContents. Value of the key is an instance of |UserData|.
- constexpr int kWebContentsUserDataKey = 0;
- struct UserData : public base::SupportsUserData::Data {
- TabImpl* tab = nullptr;
- };
- #if BUILDFLAG(IS_ANDROID)
- void HandleJavaScriptResult(const ScopedJavaGlobalRef<jobject>& callback,
- base::Value result) {
- std::string json;
- base::JSONWriter::Write(result, &json);
- base::android::RunStringCallbackAndroid(callback, json);
- }
- void OnConvertedToJavaBitmap(const ScopedJavaGlobalRef<jobject>& value_callback,
- const ScopedJavaGlobalRef<jobject>& java_bitmap) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- TabImpl::ScreenShotErrors error =
- java_bitmap ? TabImpl::ScreenShotErrors::kNone
- : TabImpl::ScreenShotErrors::kBitmapAllocationFailed;
- Java_TabImpl_runCaptureScreenShotCallback(AttachCurrentThread(),
- value_callback, java_bitmap,
- static_cast<int>(error));
- }
- // Convert SkBitmap to java Bitmap on a background thread since it involves a
- // memcpy.
- void ConvertToJavaBitmapBackgroundThread(
- const SkBitmap& bitmap,
- base::OnceCallback<void(const ScopedJavaGlobalRef<jobject>&)> callback) {
- // Make sure to only pass ScopedJavaGlobalRef between threads.
- ScopedJavaGlobalRef<jobject> java_bitmap = ScopedJavaGlobalRef<jobject>(
- gfx::ConvertToJavaBitmap(bitmap, gfx::OomBehavior::kReturnNullOnOom));
- content::GetUIThreadTaskRunner({})->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), std::move(java_bitmap)));
- }
- void OnScreenShotCaptured(const ScopedJavaGlobalRef<jobject>& value_callback,
- const SkBitmap& bitmap) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (bitmap.isNull() || bitmap.drawsNothing()) {
- Java_TabImpl_runCaptureScreenShotCallback(
- AttachCurrentThread(), value_callback, nullptr,
- static_cast<int>(TabImpl::ScreenShotErrors::kCaptureFailed));
- return;
- }
- // Not using PostTaskAndReplyWithResult to ensure ScopedJavaLocalRef is not
- // passed between threads.
- base::ThreadPool::PostTask(
- FROM_HERE,
- {base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
- base::BindOnce(&ConvertToJavaBitmapBackgroundThread, bitmap,
- base::BindOnce(&OnConvertedToJavaBitmap, value_callback)));
- }
- #endif // BUILDFLAG(IS_ANDROID)
- std::set<TabImpl*>& GetTabs() {
- static base::NoDestructor<std::set<TabImpl*>> s_all_tab_impl;
- return *s_all_tab_impl;
- }
- // Returns a scoped refptr to the SafeBrowsingService's database manager, if
- // available. Otherwise returns nullptr.
- const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
- GetDatabaseManagerFromSafeBrowsingService() {
- #if BUILDFLAG(IS_ANDROID)
- SafeBrowsingService* safe_browsing_service =
- BrowserProcess::GetInstance()->GetSafeBrowsingService();
- return scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>(
- safe_browsing_service->GetSafeBrowsingDBManager());
- #else
- return nullptr;
- #endif
- }
- // Creates a ContentSubresourceFilterWebContentsHelper for |web_contents|,
- // passing it the needed embedder-level state.
- void CreateContentSubresourceFilterWebContentsHelper(
- content::WebContents* web_contents) {
- subresource_filter::RulesetService* ruleset_service =
- BrowserProcess::GetInstance()->subresource_filter_ruleset_service();
- subresource_filter::VerifiedRulesetDealer::Handle* dealer =
- ruleset_service ? ruleset_service->GetRulesetDealer() : nullptr;
- subresource_filter::ContentSubresourceFilterWebContentsHelper::
- CreateForWebContents(
- web_contents,
- SubresourceFilterProfileContextFactory::GetForBrowserContext(
- web_contents->GetBrowserContext()),
- GetDatabaseManagerFromSafeBrowsingService(), dealer);
- }
- } // namespace
- #if BUILDFLAG(IS_ANDROID)
- static ScopedJavaLocalRef<jobject> JNI_TabImpl_FromWebContents(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& j_web_contents) {
- content::WebContents* web_contents =
- content::WebContents::FromJavaWebContents(j_web_contents);
- TabImpl* tab = TabImpl::FromWebContents(web_contents);
- if (tab)
- return ScopedJavaLocalRef<jobject>(tab->GetJavaTab());
- return nullptr;
- }
- static void JNI_TabImpl_DestroyContextMenuParams(
- JNIEnv* env,
- jlong native_context_menu_params) {
- // Note: this runs on the finalizer thread which isn't the UI thread.
- auto* context_menu_params =
- reinterpret_cast<content::ContextMenuParams*>(native_context_menu_params);
- delete context_menu_params;
- }
- TabImpl::TabImpl(ProfileImpl* profile,
- const JavaParamRef<jobject>& java_impl,
- std::unique_ptr<content::WebContents> web_contents)
- : TabImpl(profile, std::move(web_contents)) {
- java_impl_ = java_impl;
- }
- #endif
- TabImpl::TabImpl(ProfileImpl* profile,
- std::unique_ptr<content::WebContents> web_contents,
- const std::string& guid)
- : profile_(profile),
- web_contents_(std::move(web_contents)),
- guid_(guid.empty() ? base::GenerateGUID() : guid) {
- GetTabs().insert(this);
- DCHECK(web_contents_);
- // This code path is hit when the page requests a new tab, which should
- // only be possible from the same profile.
- DCHECK_EQ(profile_->GetBrowserContext(), web_contents_->GetBrowserContext());
- // FaviconTabHelper adds a WebContentsObserver. Create FaviconTabHelper
- // before |this| observes the WebContents to ensure favicons are reset before
- // notifying weblayer observers of changes.
- FaviconTabHelper::CreateForWebContents(web_contents_.get());
- UpdateRendererPrefs(false);
- locale_change_subscription_ =
- i18n::RegisterLocaleChangeCallback(base::BindRepeating(
- &TabImpl::UpdateRendererPrefs, base::Unretained(this), true));
- std::unique_ptr<UserData> user_data = std::make_unique<UserData>();
- user_data->tab = this;
- web_contents_->SetUserData(&kWebContentsUserDataKey, std::move(user_data));
- web_contents_->SetDelegate(this);
- Observe(web_contents_.get());
- navigation_controller_ = std::make_unique<NavigationControllerImpl>(this);
- find_in_page::FindTabHelper::CreateForWebContents(web_contents_.get());
- GetFindTabHelper()->AddObserver(this);
- TranslateClientImpl::CreateForWebContents(web_contents_.get());
- #if BUILDFLAG(IS_ANDROID)
- // infobars::ContentInfoBarManager must be created before
- // SubresourceFilterClientImpl as the latter depends on it.
- infobars::ContentInfoBarManager::CreateForWebContents(web_contents_.get());
- #endif
- CreateContentSubresourceFilterWebContentsHelper(web_contents_.get());
- sessions::SessionTabHelper::CreateForWebContents(
- web_contents_.get(),
- base::BindRepeating(&TabImpl::GetSessionServiceTabHelperDelegate));
- permissions::PermissionRequestManager::CreateForWebContents(
- web_contents_.get());
- content_settings::PageSpecificContentSettings::CreateForWebContents(
- web_contents_.get(),
- std::make_unique<PageSpecificContentSettingsDelegate>(
- web_contents_.get()));
- blocked_content::PopupBlockerTabHelper::CreateForWebContents(
- web_contents_.get());
- blocked_content::PopupOpenerTabHelper::CreateForWebContents(
- web_contents_.get(), base::DefaultTickClock::GetInstance(),
- HostContentSettingsMapFactory::GetForBrowserContext(
- web_contents_->GetBrowserContext()));
- PasswordManagerDriverFactory::CreateForWebContents(web_contents_.get());
- InitializePageLoadMetricsForWebContents(web_contents_.get());
- ukm::InitializeSourceUrlRecorderForWebContents(web_contents_.get());
- #if BUILDFLAG(IS_ANDROID)
- javascript_dialogs::TabModalDialogManager::CreateForWebContents(
- web_contents_.get(),
- std::make_unique<JavaScriptTabModalDialogManagerDelegateAndroid>(
- web_contents_.get()));
- browser_controls_navigation_state_handler_ =
- std::make_unique<BrowserControlsNavigationStateHandler>(
- web_contents_.get(), this);
- TrustedCDNObserver::CreateForWebContents(web_contents_.get());
- if (base::FeatureList::IsEnabled(
- features::kWebLayerClientSidePhishingDetection)) {
- safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(
- web_contents_.get(),
- std::make_unique<WebLayerSafeBrowsingTabObserverDelegate>());
- }
- if (site_engagement::SiteEngagementService::IsEnabled()) {
- site_engagement::SiteEngagementService::Helper::CreateForWebContents(
- web_contents_.get());
- }
- auto* browser_context =
- static_cast<BrowserContextImpl*>(web_contents_->GetBrowserContext());
- safe_browsing::SafeBrowsingNavigationObserver::MaybeCreateForWebContents(
- web_contents_.get(),
- HostContentSettingsMapFactory::GetForBrowserContext(browser_context),
- SafeBrowsingNavigationObserverManagerFactory::GetForBrowserContext(
- browser_context),
- browser_context->pref_service(),
- BrowserProcess::GetInstance()->GetSafeBrowsingService());
- #endif
- #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
- captive_portal::CaptivePortalTabHelper::CreateForWebContents(
- web_contents_.get(),
- CaptivePortalServiceFactory::GetForBrowserContext(
- web_contents_->GetBrowserContext()),
- base::BindRepeating(&OpenCaptivePortalLoginTabInWebContents,
- web_contents_.get()));
- #endif
- // PrerenderTabHelper adds a WebContentsObserver.
- PrerenderTabHelper::CreateForWebContents(web_contents_.get());
- webapps::InstallableManager::CreateForWebContents(web_contents_.get());
- #if BUILDFLAG(IS_ANDROID)
- // Must be created after InstallableManager.
- WebLayerAppBannerManagerAndroid::CreateForWebContents(web_contents_.get());
- #endif
- }
- TabImpl::~TabImpl() {
- DCHECK(!browser_);
- GetFindTabHelper()->RemoveObserver(this);
- // Delete the WebContents and related objects that may be observing
- // the WebContents now to avoid calling back when this object is partially
- // deleted. DidFinishNavigation() may be called while deleting WebContents,
- // so stop observing first. Similarly WebContents destructor can callback to
- // delegate such as NavigationStateChanged, so clear its Delegate as well.
- #if BUILDFLAG(IS_ANDROID)
- browser_controls_navigation_state_handler_.reset();
- #endif
- Observe(nullptr);
- web_contents_->SetDelegate(nullptr);
- if (navigation_controller_->should_delay_web_contents_deletion()) {
- // Some user-data on WebContents directly or indirectly references this.
- // Remove that linkage to avoid use-after-free.
- web_contents_->RemoveUserData(&kWebContentsUserDataKey);
- web_contents_->RemoveUserData(
- autofill::ContentAutofillDriverFactory::
- kContentAutofillDriverFactoryWebContentsUserDataKey);
- // Have Profile handle the task posting to ensure the WebContents is
- // deleted before Profile. To do otherwise means it would be possible for
- // the Profile to outlive the WebContents, which is problematic (crash).
- profile_->DeleteWebContentsSoon(std::move(web_contents_));
- }
- web_contents_.reset();
- GetTabs().erase(this);
- }
- // static
- TabImpl* TabImpl::FromWebContents(content::WebContents* web_contents) {
- if (!web_contents)
- return nullptr;
- UserData* user_data = reinterpret_cast<UserData*>(
- web_contents->GetUserData(&kWebContentsUserDataKey));
- return user_data ? user_data->tab : nullptr;
- }
- // static
- std::set<TabImpl*> TabImpl::GetAllTabImpl() {
- return GetTabs();
- }
- void TabImpl::AddDataObserver(DataObserver* observer) {
- data_observers_.AddObserver(observer);
- }
- void TabImpl::RemoveDataObserver(DataObserver* observer) {
- data_observers_.RemoveObserver(observer);
- }
- Browser* TabImpl::GetBrowser() {
- return browser_;
- }
- void TabImpl::SetErrorPageDelegate(ErrorPageDelegate* delegate) {
- error_page_delegate_ = delegate;
- }
- void TabImpl::SetFullscreenDelegate(FullscreenDelegate* delegate) {
- if (delegate == fullscreen_delegate_)
- return;
- const bool had_delegate = (fullscreen_delegate_ != nullptr);
- const bool has_delegate = (delegate != nullptr);
- // If currently fullscreen, and the delegate is being set to null, force an
- // exit now (otherwise the delegate can't take us out of fullscreen).
- if (is_fullscreen_ && fullscreen_delegate_ && had_delegate != has_delegate)
- OnExitFullscreen();
- fullscreen_delegate_ = delegate;
- // Whether fullscreen is enabled depends upon whether there is a delegate. If
- // having a delegate changed, then update the renderer (which is where
- // fullscreen enabled is tracked).
- if (had_delegate != has_delegate)
- web_contents_->OnWebPreferencesChanged();
- }
- void TabImpl::SetNewTabDelegate(NewTabDelegate* delegate) {
- new_tab_delegate_ = delegate;
- }
- void TabImpl::SetGoogleAccountsDelegate(GoogleAccountsDelegate* delegate) {
- google_accounts_delegate_ = delegate;
- }
- void TabImpl::AddObserver(TabObserver* observer) {
- observers_.AddObserver(observer);
- }
- void TabImpl::RemoveObserver(TabObserver* observer) {
- observers_.RemoveObserver(observer);
- }
- NavigationController* TabImpl::GetNavigationController() {
- return navigation_controller_.get();
- }
- void TabImpl::ExecuteScript(const std::u16string& script,
- bool use_separate_isolate,
- JavaScriptResultCallback callback) {
- if (use_separate_isolate) {
- web_contents_->GetPrimaryMainFrame()->ExecuteJavaScriptInIsolatedWorld(
- script, std::move(callback), ISOLATED_WORLD_ID_WEBLAYER);
- } else {
- content::RenderFrameHost::AllowInjectingJavaScript();
- web_contents_->GetPrimaryMainFrame()->ExecuteJavaScript(
- script, std::move(callback));
- }
- }
- const std::string& TabImpl::GetGuid() {
- return guid_;
- }
- void TabImpl::SetData(const std::map<std::string, std::string>& data) {
- bool result = SetDataInternal(data);
- DCHECK(result) << "Data given to SetData() was too large.";
- }
- const std::map<std::string, std::string>& TabImpl::GetData() {
- return data_;
- }
- std::u16string TabImpl::AddWebMessageHostFactory(
- std::unique_ptr<WebMessageHostFactory> factory,
- const std::u16string& js_object_name,
- const std::vector<std::string>& allowed_origin_rules) {
- if (!js_communication_host_) {
- js_communication_host_ =
- std::make_unique<js_injection::JsCommunicationHost>(
- web_contents_.get());
- }
- return js_communication_host_->AddWebMessageHostFactory(
- std::make_unique<WebMessageHostFactoryWrapper>(std::move(factory)),
- js_object_name, allowed_origin_rules);
- }
- void TabImpl::RemoveWebMessageHostFactory(
- const std::u16string& js_object_name) {
- if (js_communication_host_)
- js_communication_host_->RemoveWebMessageHostFactory(js_object_name);
- }
- void TabImpl::ExecuteScriptWithUserGestureForTests(
- const std::u16string& script) {
- web_contents_->GetPrimaryMainFrame()
- ->ExecuteJavaScriptWithUserGestureForTests(script, base::NullCallback());
- }
- std::unique_ptr<FaviconFetcher> TabImpl::CreateFaviconFetcher(
- FaviconFetcherDelegate* delegate) {
- return std::make_unique<FaviconFetcherImpl>(web_contents_.get(), delegate);
- }
- void TabImpl::SetTranslateTargetLanguage(
- const std::string& translate_target_lang) {
- translate::TranslateManager* translate_manager =
- TranslateClientImpl::FromWebContents(web_contents())
- ->GetTranslateManager();
- translate_manager->SetPredefinedTargetLanguage(
- translate_target_lang,
- /*should_auto_translate=*/true);
- }
- #if !BUILDFLAG(IS_ANDROID)
- void TabImpl::AttachToView(views::WebView* web_view) {
- web_view->SetWebContents(web_contents_.get());
- web_contents_->Focus();
- }
- #endif
- void TabImpl::WebPreferencesChanged() {
- web_contents_->OnWebPreferencesChanged();
- }
- void TabImpl::SetWebPreferences(blink::web_pref::WebPreferences* prefs) {
- prefs->fullscreen_supported = !!fullscreen_delegate_;
- if (!browser_)
- return;
- browser_->SetWebPreferences(prefs);
- }
- void TabImpl::OnGainedActive() {
- web_contents()->GetController().LoadIfNecessary();
- if (enter_fullscreen_on_gained_active_)
- EnterFullscreenImpl();
- }
- void TabImpl::OnLosingActive() {
- if (is_fullscreen_)
- web_contents_->ExitFullscreen(/* will_cause_resize */ false);
- }
- bool TabImpl::IsActive() {
- return browser_->GetActiveTab() == this;
- }
- void TabImpl::ShowContextMenu(const content::ContextMenuParams& params) {
- #if BUILDFLAG(IS_ANDROID)
- Java_TabImpl_showContextMenu(
- base::android::AttachCurrentThread(), java_impl_,
- context_menu::BuildJavaContextMenuParams(params),
- reinterpret_cast<jlong>(new content::ContextMenuParams(params)));
- #endif
- }
- #if BUILDFLAG(IS_ANDROID)
- // static
- void TabImpl::DisableAutofillSystemIntegrationForTesting() {
- g_system_autofill_disabled_for_testing = true;
- }
- static jlong JNI_TabImpl_CreateTab(JNIEnv* env,
- jlong profile,
- const JavaParamRef<jobject>& java_impl) {
- ProfileImpl* profile_impl = reinterpret_cast<ProfileImpl*>(profile);
- content::WebContents::CreateParams create_params(
- profile_impl->GetBrowserContext());
- create_params.initially_hidden = true;
- return reinterpret_cast<intptr_t>(new TabImpl(
- profile_impl, java_impl, content::WebContents::Create(create_params)));
- }
- static void JNI_TabImpl_DeleteTab(JNIEnv* env, jlong tab) {
- TabImpl* tab_impl = reinterpret_cast<TabImpl*>(tab);
- DCHECK(tab_impl);
- // RemoveTabBeforeDestroyingFromJava() should have been called before this,
- // which sets browser to null.
- DCHECK(!tab_impl->browser());
- delete tab_impl;
- }
- ScopedJavaLocalRef<jobject> TabImpl::GetWebContents(JNIEnv* env) {
- return web_contents_->GetJavaWebContents();
- }
- void TabImpl::SetBrowserControlsContainerViews(
- JNIEnv* env,
- jlong native_top_controls_container_view,
- jlong native_bottom_controls_container_view) {
- top_controls_container_view_ =
- reinterpret_cast<BrowserControlsContainerView*>(
- native_top_controls_container_view);
- bottom_controls_container_view_ =
- reinterpret_cast<BrowserControlsContainerView*>(
- native_bottom_controls_container_view);
- }
- void TabImpl::ExecuteScript(JNIEnv* env,
- const JavaParamRef<jstring>& script,
- bool use_separate_isolate,
- const JavaParamRef<jobject>& callback) {
- ScopedJavaGlobalRef<jobject> jcallback(env, callback);
- ExecuteScript(base::android::ConvertJavaStringToUTF16(script),
- use_separate_isolate,
- base::BindOnce(&HandleJavaScriptResult, jcallback));
- }
- void TabImpl::SetJavaImpl(JNIEnv* env, const JavaParamRef<jobject>& impl) {
- // This should only be called early on and only once.
- DCHECK(!java_impl_);
- java_impl_ = impl;
- }
- void TabImpl::InitializeAutofillIfNecessary(JNIEnv* env) {
- if (g_system_autofill_disabled_for_testing)
- return;
- if (!autofill::ContentAutofillDriverFactory::FromWebContents(
- web_contents_.get())) {
- InitializeAutofillDriver();
- }
- }
- void TabImpl::UpdateBrowserControlsConstraint(JNIEnv* env,
- jint constraint,
- jboolean animate) {
- current_browser_controls_visibility_constraint_ =
- static_cast<cc::BrowserControlsState>(constraint);
- // Passing BOTH here means that it doesn't matter what state the controls are
- // currently in; don't change the current state unless it's incompatible with
- // the new constraint.
- UpdateBrowserControlsState(cc::BrowserControlsState::kBoth, animate);
- }
- ScopedJavaLocalRef<jstring> TabImpl::GetGuid(JNIEnv* env) {
- return base::android::ConvertUTF8ToJavaString(AttachCurrentThread(),
- GetGuid());
- }
- TabImpl::ScreenShotErrors TabImpl::PrepareForCaptureScreenShot(
- float scale,
- content::RenderWidgetHostView** rwhv,
- gfx::Rect* src_rect,
- gfx::Size* output_size) {
- if (scale <= 0.f || scale > 1.f)
- return ScreenShotErrors::kScaleOutOfRange;
- if (!IsActive())
- return ScreenShotErrors::kTabNotActive;
- if (web_contents_->GetVisibility() != content::Visibility::VISIBLE)
- return ScreenShotErrors::kWebContentsNotVisible;
- if (!browser_ || !browser_->CompositorHasSurface())
- return ScreenShotErrors::kNoSurface;
- *rwhv = web_contents_->GetTopLevelRenderWidgetHostView();
- if (!*rwhv)
- return ScreenShotErrors::kNoRenderWidgetHostView;
- if (!(*rwhv)->GetNativeView()->GetWindowAndroid())
- return ScreenShotErrors::kNoWindowAndroid;
- *src_rect =
- gfx::Rect(web_contents_->GetNativeView()->GetPhysicalBackingSize());
- if (src_rect->IsEmpty())
- return ScreenShotErrors::kEmptyViewport;
- const int reduced_height =
- src_rect->height() -
- top_controls_container_view_->GetContentHeightDelta() -
- bottom_controls_container_view_->GetContentHeightDelta();
- if (reduced_height <= 0)
- return ScreenShotErrors::kHiddenByControls;
- src_rect->set_height(reduced_height);
- *output_size = gfx::ScaleToCeiledSize(src_rect->size(), scale, scale);
- if (output_size->IsEmpty())
- return ScreenShotErrors::kScaledToEmpty;
- return ScreenShotErrors::kNone;
- }
- void TabImpl::UpdateBrowserControlsState(cc::BrowserControlsState new_state,
- bool animate) {
- if (base::FeatureList::IsEnabled(kImmediatelyHideBrowserControlsForTest))
- animate = false;
- // The constraint is managed by Java code, so re-use the existing constraint
- // and only update the desired state.
- web_contents_->UpdateBrowserControlsState(
- current_browser_controls_visibility_constraint_, new_state, animate);
- }
- void TabImpl::CaptureScreenShot(
- JNIEnv* env,
- jfloat scale,
- const base::android::JavaParamRef<jobject>& value_callback) {
- content::RenderWidgetHostView* rwhv = nullptr;
- gfx::Rect src_rect;
- gfx::Size output_size;
- ScreenShotErrors error =
- PrepareForCaptureScreenShot(scale, &rwhv, &src_rect, &output_size);
- if (error != ScreenShotErrors::kNone) {
- Java_TabImpl_runCaptureScreenShotCallback(
- env, ScopedJavaLocalRef<jobject>(value_callback),
- ScopedJavaLocalRef<jobject>(), static_cast<int>(error));
- return;
- }
- rwhv->CopyFromSurface(
- src_rect, output_size,
- base::BindOnce(&OnScreenShotCaptured,
- ScopedJavaGlobalRef<jobject>(value_callback)));
- }
- jboolean TabImpl::SetData(
- JNIEnv* env,
- const base::android::JavaParamRef<jobjectArray>& data) {
- std::vector<std::string> flattened_map;
- base::android::AppendJavaStringArrayToStringVector(env, data, &flattened_map);
- std::map<std::string, std::string> data_map;
- for (size_t i = 0; i < flattened_map.size(); i += 2) {
- data_map.insert({flattened_map[i], flattened_map[i + 1]});
- }
- return SetDataInternal(data_map);
- }
- base::android::ScopedJavaLocalRef<jobjectArray> TabImpl::GetData(JNIEnv* env) {
- std::vector<std::string> flattened_map;
- for (const auto& kv : data_) {
- flattened_map.push_back(kv.first);
- flattened_map.push_back(kv.second);
- }
- return base::android::ToJavaArrayOfStrings(env, flattened_map);
- }
- jboolean TabImpl::IsRendererControllingBrowserControlsOffsets(JNIEnv* env) {
- return browser_controls_navigation_state_handler_
- ->IsRendererControllingOffsets();
- }
- base::android::ScopedJavaLocalRef<jstring> TabImpl::RegisterWebMessageCallback(
- JNIEnv* env,
- const base::android::JavaParamRef<jstring>& js_object_name,
- const base::android::JavaParamRef<jobjectArray>& js_origins,
- const base::android::JavaParamRef<jobject>& client) {
- auto proxy = std::make_unique<WebMessageHostFactoryProxy>(client);
- std::vector<std::string> origins;
- base::android::AppendJavaStringArrayToStringVector(env, js_origins, &origins);
- std::u16string result = AddWebMessageHostFactory(
- std::move(proxy),
- base::android::ConvertJavaStringToUTF16(env, js_object_name), origins);
- return base::android::ConvertUTF16ToJavaString(env, result);
- }
- void TabImpl::UnregisterWebMessageCallback(
- JNIEnv* env,
- const base::android::JavaParamRef<jstring>& js_object_name) {
- std::u16string name;
- base::android::ConvertJavaStringToUTF16(env, js_object_name, &name);
- RemoveWebMessageHostFactory(name);
- }
- jboolean TabImpl::CanTranslate(JNIEnv* env) {
- return TranslateClientImpl::FromWebContents(web_contents())
- ->GetTranslateManager()
- ->CanManuallyTranslate();
- }
- void TabImpl::ShowTranslateUi(JNIEnv* env) {
- TranslateClientImpl::FromWebContents(web_contents())
- ->ShowTranslateUiWhenReady();
- }
- void TabImpl::RemoveTabFromBrowserBeforeDestroying(JNIEnv* env) {
- DCHECK(browser_);
- browser_->RemoveTabBeforeDestroyingFromJava(this);
- }
- void TabImpl::SetTranslateTargetLanguage(
- JNIEnv* env,
- const base::android::JavaParamRef<jstring>& translate_target_lang) {
- SetTranslateTargetLanguage(
- base::android::ConvertJavaStringToUTF8(env, translate_target_lang));
- }
- void TabImpl::SetDesktopUserAgentEnabled(JNIEnv* env, jboolean enable) {
- if (desktop_user_agent_enabled_ == enable)
- return;
- desktop_user_agent_enabled_ = enable;
- // Reset state that an earlier call to Navigation::SetUserAgentString()
- // could have modified.
- embedder_support::SetDesktopUserAgentOverride(
- web_contents_.get(), embedder_support::GetUserAgentMetadata(),
- /* override_in_new_tabs= */ false);
- web_contents_->SetRendererInitiatedUserAgentOverrideOption(
- content::NavigationController::UA_OVERRIDE_INHERIT);
- content::NavigationEntry* entry =
- web_contents_->GetController().GetLastCommittedEntry();
- if (!entry)
- return;
- entry->SetIsOverridingUserAgent(enable);
- web_contents_->NotifyPreferencesChanged();
- web_contents_->GetController().Reload(
- content::ReloadType::ORIGINAL_REQUEST_URL, true);
- }
- jboolean TabImpl::IsDesktopUserAgentEnabled(JNIEnv* env) {
- auto* entry = web_contents_->GetController().GetLastCommittedEntry();
- if (!entry)
- return false;
- // The same user agent override mechanism is used for per-navigation user
- // agent and desktop mode. Make sure not to return desktop mode for
- // navigation entries which used a per-navigation user agent.
- auto* entry_data = NavigationEntryData::Get(entry);
- if (entry_data && entry_data->per_navigation_user_agent_override())
- return false;
- return entry->GetIsOverridingUserAgent();
- }
- void TabImpl::Download(JNIEnv* env, jlong native_context_menu_params) {
- auto* context_menu_params =
- reinterpret_cast<content::ContextMenuParams*>(native_context_menu_params);
- bool is_link = context_menu_params->media_type !=
- blink::mojom::ContextMenuDataMediaType::kImage &&
- context_menu_params->media_type !=
- blink::mojom::ContextMenuDataMediaType::kVideo;
- download::CreateContextMenuDownload(web_contents_.get(), *context_menu_params,
- std::string(), is_link);
- }
- #endif // BUILDFLAG(IS_ANDROID)
- content::WebContents* TabImpl::OpenURLFromTab(
- content::WebContents* source,
- const content::OpenURLParams& params) {
- if (blocked_content::ConsiderForPopupBlocking(params.disposition)) {
- bool blocked = blocked_content::MaybeBlockPopup(
- source, nullptr,
- std::make_unique<PopupNavigationDelegateImpl>(
- params, source, nullptr),
- ¶ms, blink::mojom::WindowFeatures(),
- HostContentSettingsMapFactory::GetForBrowserContext(
- source->GetBrowserContext())) == nullptr;
- if (blocked)
- return nullptr;
- }
- if (params.disposition == WindowOpenDisposition::CURRENT_TAB) {
- source->GetController().LoadURLWithParams(
- content::NavigationController::LoadURLParams(params));
- return source;
- }
- // All URLs not opening in the current tab will get a new tab.
- std::unique_ptr<content::WebContents> new_tab_contents =
- content::WebContents::Create(content::WebContents::CreateParams(
- web_contents()->GetBrowserContext()));
- base::WeakPtr<content::WebContents> new_tab_contents_weak_ptr(
- new_tab_contents->GetWeakPtr());
- bool was_blocked = false;
- AddNewContents(web_contents(), std::move(new_tab_contents), params.url,
- params.disposition, {}, params.user_gesture, &was_blocked);
- if (was_blocked || !new_tab_contents_weak_ptr)
- return nullptr;
- new_tab_contents_weak_ptr->GetController().LoadURLWithParams(
- content::NavigationController::LoadURLParams(params));
- return new_tab_contents_weak_ptr.get();
- }
- void TabImpl::ShowRepostFormWarningDialog(content::WebContents* source) {
- #if BUILDFLAG(IS_ANDROID)
- Java_TabImpl_showRepostFormWarningDialog(base::android::AttachCurrentThread(),
- java_impl_);
- #else
- source->GetController().CancelPendingReload();
- #endif
- }
- void TabImpl::NavigationStateChanged(content::WebContents* source,
- content::InvalidateTypes changed_flags) {
- DCHECK_EQ(web_contents_.get(), source);
- if (changed_flags & content::INVALIDATE_TYPE_URL) {
- for (auto& observer : observers_)
- observer.DisplayedUrlChanged(source->GetVisibleURL());
- UpdateBrowserVisibleSecurityStateIfNecessary();
- }
- // TODO(crbug.com/1064582): INVALIDATE_TYPE_TITLE is called only when a title
- // is set on the active navigation entry, but not when the active entry
- // changes, so check INVALIDATE_TYPE_LOAD here as well. However this should
- // be fixed and INVALIDATE_TYPE_LOAD should be removed.
- if (changed_flags &
- (content::INVALIDATE_TYPE_TITLE | content::INVALIDATE_TYPE_LOAD)) {
- std::u16string title = web_contents_->GetTitle();
- if (title_ != title) {
- title_ = title;
- for (auto& observer : observers_)
- observer.OnTitleUpdated(title);
- }
- }
- }
- content::JavaScriptDialogManager* TabImpl::GetJavaScriptDialogManager(
- content::WebContents* web_contents) {
- #if BUILDFLAG(IS_ANDROID)
- return javascript_dialogs::TabModalDialogManager::FromWebContents(
- web_contents);
- #else
- return nullptr;
- #endif
- }
- #if BUILDFLAG(IS_ANDROID)
- std::unique_ptr<content::ColorChooser> TabImpl::OpenColorChooser(
- content::WebContents* web_contents,
- SkColor color,
- const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) {
- return std::make_unique<web_contents_delegate_android::ColorChooserAndroid>(
- web_contents, color, suggestions);
- }
- #endif
- void TabImpl::CreateSmsPrompt(content::RenderFrameHost* render_frame_host,
- const std::vector<url::Origin>& origin_list,
- const std::string& one_time_code,
- base::OnceClosure on_confirm,
- base::OnceClosure on_cancel) {
- #if BUILDFLAG(IS_ANDROID)
- auto* web_contents =
- content::WebContents::FromRenderFrameHost(render_frame_host);
- sms::SmsInfoBar::Create(
- web_contents,
- infobars::ContentInfoBarManager::FromWebContents(web_contents),
- origin_list, one_time_code, std::move(on_confirm), std::move(on_cancel));
- #else
- NOTREACHED();
- #endif
- }
- void TabImpl::RunFileChooser(
- content::RenderFrameHost* render_frame_host,
- scoped_refptr<content::FileSelectListener> listener,
- const blink::mojom::FileChooserParams& params) {
- FileSelectHelper::RunFileChooser(render_frame_host, std::move(listener),
- params);
- }
- int TabImpl::GetTopControlsHeight() {
- #if BUILDFLAG(IS_ANDROID)
- return top_controls_container_view_
- ? top_controls_container_view_->GetControlsHeight()
- : 0;
- #else
- return 0;
- #endif
- }
- int TabImpl::GetTopControlsMinHeight() {
- #if BUILDFLAG(IS_ANDROID)
- return top_controls_container_view_
- ? top_controls_container_view_->GetMinHeight()
- : 0;
- #else
- return 0;
- #endif
- }
- int TabImpl::GetBottomControlsHeight() {
- #if BUILDFLAG(IS_ANDROID)
- return bottom_controls_container_view_
- ? bottom_controls_container_view_->GetControlsHeight()
- : 0;
- #else
- return 0;
- #endif
- }
- bool TabImpl::DoBrowserControlsShrinkRendererSize(
- content::WebContents* web_contents) {
- #if BUILDFLAG(IS_ANDROID)
- TRACE_EVENT0("weblayer", "Java_TabImpl_doBrowserControlsShrinkRendererSize");
- return Java_TabImpl_doBrowserControlsShrinkRendererSize(AttachCurrentThread(),
- java_impl_);
- #else
- return false;
- #endif
- }
- bool TabImpl::ShouldAnimateBrowserControlsHeightChanges() {
- #if BUILDFLAG(IS_ANDROID)
- return top_controls_container_view_
- ? top_controls_container_view_
- ->ShouldAnimateBrowserControlsHeightChanges()
- : false;
- #else
- return false;
- #endif
- }
- bool TabImpl::OnlyExpandTopControlsAtPageTop() {
- #if BUILDFLAG(IS_ANDROID)
- return top_controls_container_view_
- ? top_controls_container_view_->OnlyExpandControlsAtPageTop()
- : false;
- #else
- return false;
- #endif
- }
- bool TabImpl::IsBackForwardCacheSupported() {
- return true;
- }
- void TabImpl::RequestMediaAccessPermission(
- content::WebContents* web_contents,
- const content::MediaStreamRequest& request,
- content::MediaResponseCallback callback) {
- #if BUILDFLAG(IS_ANDROID)
- MediaStreamManager::FromWebContents(web_contents)
- ->RequestMediaAccessPermission(request, std::move(callback));
- #else
- std::move(callback).Run(blink::mojom::StreamDevicesSet(),
- blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
- nullptr);
- #endif
- }
- bool TabImpl::CheckMediaAccessPermission(
- content::RenderFrameHost* render_frame_host,
- const GURL& security_origin,
- blink::mojom::MediaStreamType type) {
- DCHECK(type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE ||
- type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
- blink::PermissionType permission_type =
- type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE
- ? blink::PermissionType::AUDIO_CAPTURE
- : blink::PermissionType::VIDEO_CAPTURE;
- // TODO(crbug.com/1321100): Remove `security_origin`.
- if (render_frame_host->GetLastCommittedOrigin().GetURL() != security_origin) {
- return false;
- }
- // It is OK to ignore `security_origin` because it will be calculated from
- // `render_frame_host` and we always ignore `requesting_origin` for
- // `AUDIO_CAPTURE` and `VIDEO_CAPTURE`.
- // `render_frame_host->GetMainFrame()->GetLastCommittedOrigin()` will be used
- // instead.
- return render_frame_host->GetBrowserContext()
- ->GetPermissionController()
- ->GetPermissionStatusForCurrentDocument(permission_type,
- render_frame_host) ==
- blink::mojom::PermissionStatus::GRANTED;
- }
- void TabImpl::EnterFullscreenModeForTab(
- content::RenderFrameHost* requesting_frame,
- const blink::mojom::FullscreenOptions& options) {
- // TODO(crbug.com/1232147): support |options|.
- if (is_fullscreen_) {
- // Typically EnterFullscreenModeForTab() should not be called consecutively,
- // but there may be corner cases with oopif that lead to multiple
- // consecutive calls. Avoid notifying the delegate in this case.
- return;
- }
- is_fullscreen_ = true;
- if (!IsActive()) {
- // Process the request the tab is made active.
- enter_fullscreen_on_gained_active_ = true;
- return;
- }
- EnterFullscreenImpl();
- }
- void TabImpl::ExitFullscreenModeForTab(content::WebContents* web_contents) {
- weak_ptr_factory_for_fullscreen_exit_.InvalidateWeakPtrs();
- is_fullscreen_ = false;
- if (enter_fullscreen_on_gained_active_)
- enter_fullscreen_on_gained_active_ = false;
- else
- fullscreen_delegate_->ExitFullscreen();
- #if BUILDFLAG(IS_ANDROID)
- // Attempt to show browser controls when exiting fullscreen.
- SetBrowserControlsConstraint(ControlsVisibilityReason::kFullscreen,
- cc::BrowserControlsState::kBoth);
- #endif
- }
- bool TabImpl::IsFullscreenForTabOrPending(
- const content::WebContents* web_contents) {
- return is_fullscreen_;
- }
- blink::mojom::DisplayMode TabImpl::GetDisplayMode(
- const content::WebContents* web_contents) {
- return is_fullscreen_ ? blink::mojom::DisplayMode::kFullscreen
- : blink::mojom::DisplayMode::kBrowser;
- }
- void TabImpl::AddNewContents(content::WebContents* source,
- std::unique_ptr<content::WebContents> new_contents,
- const GURL& target_url,
- WindowOpenDisposition disposition,
- const gfx::Rect& initial_rect,
- bool user_gesture,
- bool* was_blocked) {
- if (!new_tab_delegate_) {
- *was_blocked = true;
- return;
- }
- // At this point the |new_contents| is beyond the popup blocker, but we use
- // the same logic for determining if the popup tracker needs to be attached.
- if (source && blocked_content::ConsiderForPopupBlocking(disposition)) {
- blocked_content::PopupTracker::CreateForWebContents(new_contents.get(),
- source, disposition);
- }
- new_tab_delegate_->OnNewTab(browser_->CreateTab(std::move(new_contents)),
- NewTabTypeFromWindowDisposition(disposition));
- }
- void TabImpl::CloseContents(content::WebContents* source) {
- // The only time that |browser_| is null is during shutdown, and this callback
- // shouldn't come in at that time.
- DCHECK(browser_);
- #if BUILDFLAG(IS_ANDROID)
- JNIEnv* env = AttachCurrentThread();
- Java_TabImpl_handleCloseFromWebContents(env, java_impl_);
- // The above call resulted in the destruction of this; nothing to do but
- // return.
- #else
- browser_->DestroyTab(this);
- #endif
- }
- void TabImpl::FindReply(content::WebContents* web_contents,
- int request_id,
- int number_of_matches,
- const gfx::Rect& selection_rect,
- int active_match_ordinal,
- bool final_update) {
- GetFindTabHelper()->HandleFindReply(request_id, number_of_matches,
- selection_rect, active_match_ordinal,
- final_update);
- }
- #if BUILDFLAG(IS_ANDROID)
- // FindMatchRectsReply and OnFindResultAvailable forward find-related results to
- // the Java TabImpl. The find actions themselves are initiated directly from
- // Java via FindInPageBridge.
- void TabImpl::FindMatchRectsReply(content::WebContents* web_contents,
- int version,
- const std::vector<gfx::RectF>& rects,
- const gfx::RectF& active_rect) {
- JNIEnv* env = AttachCurrentThread();
- // Create the details object.
- ScopedJavaLocalRef<jobject> details_object =
- Java_TabImpl_createFindMatchRectsDetails(
- env, version, rects.size(),
- ScopedJavaLocalRef<jobject>(Java_TabImpl_createRectF(
- env, active_rect.x(), active_rect.y(), active_rect.right(),
- active_rect.bottom())));
- // Add the rects.
- for (size_t i = 0; i < rects.size(); ++i) {
- const gfx::RectF& rect = rects[i];
- Java_TabImpl_setMatchRectByIndex(
- env, details_object, i,
- ScopedJavaLocalRef<jobject>(Java_TabImpl_createRectF(
- env, rect.x(), rect.y(), rect.right(), rect.bottom())));
- }
- Java_TabImpl_onFindMatchRectsAvailable(env, java_impl_, details_object);
- }
- #endif
- void TabImpl::PrimaryMainFrameRenderProcessGone(
- base::TerminationStatus status) {
- #if BUILDFLAG(IS_ANDROID)
- // If a renderer process is lost when the tab is not visible, indicate to the
- // WebContents that it should automatically reload the next time it becomes
- // visible.
- JNIEnv* env = AttachCurrentThread();
- if (Java_TabImpl_willAutomaticallyReloadAfterCrashImpl(env, java_impl_))
- web_contents()->GetController().SetNeedsReload();
- #endif
- for (auto& observer : observers_)
- observer.OnRenderProcessGone();
- }
- void TabImpl::OnFindResultAvailable(content::WebContents* web_contents) {
- #if BUILDFLAG(IS_ANDROID)
- const find_in_page::FindNotificationDetails& find_result =
- GetFindTabHelper()->find_result();
- JNIEnv* env = AttachCurrentThread();
- Java_TabImpl_onFindResultAvailable(
- env, java_impl_, find_result.number_of_matches(),
- find_result.active_match_ordinal(), find_result.final_update());
- #endif
- }
- #if BUILDFLAG(IS_ANDROID)
- void TabImpl::OnBrowserControlsStateStateChanged(
- ControlsVisibilityReason reason,
- cc::BrowserControlsState state) {
- SetBrowserControlsConstraint(reason, state);
- }
- void TabImpl::OnUpdateBrowserControlsStateBecauseOfProcessSwitch(
- bool did_commit) {
- // This matches the logic of updateAfterRendererProcessSwitch() and
- // updateEnabledState() in Chrome's TabBrowserControlsConstraintsHelper.
- if (did_commit &&
- current_browser_controls_visibility_constraint_ ==
- cc::BrowserControlsState::kShown &&
- top_controls_container_view_ &&
- top_controls_container_view_->IsFullyVisible()) {
- // The top-control is fully visible, don't animate this else the controls
- // bounce around.
- UpdateBrowserControlsState(cc::BrowserControlsState::kShown, false);
- } else {
- if (did_commit && current_browser_controls_visibility_constraint_ ==
- cc::BrowserControlsState::kBoth) {
- // If the current state is kBoth, then
- // TabImpl::UpdateBrowserControlsState() is going to call
- // WebContents::UpdateBrowserControlsState() with both current and
- // constraints set to kBoth. cc does
- // nothing in this case. During a navigation the top-view needs to be
- // shown. To force the top-view to show, supply
- // kShown. This path is only hit if top-view
- // is configured to only-expand-at-top, as in this case the top-view isn't
- // forced shown during a page load.
- //
- // It's entirely possible the scroll offset is changed as part of the
- // loading process (such as happens with back/forward navigation or
- // links part way down a page). Trying to detect this and compensate
- // here is likely to be racy, so the top-view is always shown.
- const bool animate =
- !base::FeatureList::IsEnabled(kImmediatelyHideBrowserControlsForTest);
- web_contents_->UpdateBrowserControlsState(
- cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown,
- animate);
- // This falls through to call UpdateBrowserControlsState() again to
- // ensure the constraint is set back to BOTH.
- }
- UpdateBrowserControlsState(
- cc::BrowserControlsState::kBoth,
- current_browser_controls_visibility_constraint_ !=
- cc::BrowserControlsState::kHidden);
- }
- }
- #endif
- void TabImpl::DidChangeVisibleSecurityState() {
- UpdateBrowserVisibleSecurityStateIfNecessary();
- }
- void TabImpl::UpdateBrowserVisibleSecurityStateIfNecessary() {
- if (browser_ && browser_->GetActiveTab() == this)
- browser_->VisibleSecurityStateOfActiveTabChanged();
- }
- void TabImpl::OnExitFullscreen() {
- // If |processing_enter_fullscreen_| is true, it means the callback is being
- // called while processing EnterFullscreenModeForTab(). WebContents doesn't
- // deal well with this. FATAL as Android generally doesn't run with DCHECKs.
- LOG_IF(FATAL, processing_enter_fullscreen_)
- << "exiting fullscreen while entering fullscreen is not supported";
- web_contents_->ExitFullscreen(/* will_cause_resize */ false);
- }
- void TabImpl::UpdateRendererPrefs(bool should_sync_prefs) {
- blink::RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
- content::UpdateFontRendererPreferencesFromSystemSettings(prefs);
- prefs->accept_languages = i18n::GetAcceptLangs();
- if (should_sync_prefs)
- web_contents_->SyncRendererPrefs();
- }
- #if BUILDFLAG(IS_ANDROID)
- void TabImpl::SetBrowserControlsConstraint(
- ControlsVisibilityReason reason,
- cc::BrowserControlsState constraint) {
- Java_TabImpl_setBrowserControlsVisibilityConstraint(
- base::android::AttachCurrentThread(), java_impl_,
- static_cast<int>(reason), static_cast<int>(constraint));
- }
- void TabImpl::InitializeAutofillForTests() {
- InitializeAutofillDriver();
- }
- void TabImpl::InitializeAutofillDriver() {
- content::WebContents* web_contents = web_contents_.get();
- DCHECK(
- !autofill::ContentAutofillDriverFactory::FromWebContents(web_contents));
- DCHECK(autofill::AutofillProvider::FromWebContents(web_contents));
- AutofillClientImpl::CreateForWebContents(web_contents);
- autofill::ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
- web_contents, AutofillClientImpl::FromWebContents(web_contents),
- base::BindRepeating(&autofill::AndroidDriverInitHook,
- AutofillClientImpl::FromWebContents(web_contents),
- autofill::AutofillManager::EnableDownloadManager(
- !autofill::AutofillProvider::
- is_download_manager_disabled_for_testing())));
- }
- #endif // BUILDFLAG(IS_ANDROID)
- find_in_page::FindTabHelper* TabImpl::GetFindTabHelper() {
- return find_in_page::FindTabHelper::FromWebContents(web_contents_.get());
- }
- // static
- sessions::SessionTabHelperDelegate* TabImpl::GetSessionServiceTabHelperDelegate(
- content::WebContents* web_contents) {
- TabImpl* tab = FromWebContents(web_contents);
- return (tab && tab->browser_) ? tab->browser_->browser_persister() : nullptr;
- }
- bool TabImpl::SetDataInternal(const std::map<std::string, std::string>& data) {
- int total_size = 0;
- for (const auto& kv : data)
- total_size += kv.first.size() + kv.second.size();
- if (total_size > kMaxDataSize)
- return false;
- data_ = data;
- for (auto& observer : data_observers_)
- observer.OnDataChanged(this, data_);
- return true;
- }
- void TabImpl::EnterFullscreenImpl() {
- // This ensures the existing callback is ignored.
- weak_ptr_factory_for_fullscreen_exit_.InvalidateWeakPtrs();
- auto exit_fullscreen_closure =
- base::BindOnce(&TabImpl::OnExitFullscreen,
- weak_ptr_factory_for_fullscreen_exit_.GetWeakPtr());
- base::AutoReset<bool> reset(&processing_enter_fullscreen_, true);
- fullscreen_delegate_->EnterFullscreen(std::move(exit_fullscreen_closure));
- #if BUILDFLAG(IS_ANDROID)
- // Make sure browser controls cannot show when the tab is fullscreen.
- SetBrowserControlsConstraint(ControlsVisibilityReason::kFullscreen,
- cc::BrowserControlsState::kHidden);
- #endif
- }
- } // namespace weblayer
|