From 1bf95e7e4d3092ab6ac36a49da3ee8733eca2757 Mon Sep 17 00:00:00 2001 From: Alexander Frick Date: Sun, 8 Oct 2023 10:45:40 -0500 Subject: [PATCH] M117 stage 7 --- arm/android/media/media_options.gni | 10 +- .../media/base/supported_types.cc | 37 +- .../media/ffmpeg/ffmpeg_common.cc | 0 arm/raspi/media/base/supported_types.cc | 407 -- arm/raspi/media/ffmpeg/ffmpeg_common.cc | 931 ---- infra/THORIUM_DEV_BOOKMARKS.html | 2 +- setup.sh | 2 + src/build/config/android/BUILD.gn | 4 - src/chrome/android/BUILD.gn | 186 +- src/chrome/android/chrome_public_apk_tmpl.gni | 17 +- .../strings/android_chrome_strings.grd | 234 +- .../browser/ui/startup/bad_flags_prompt.cc | 8 +- .../ui/views/frame/browser_root_view.h | 2 +- src/chrome/browser/ui/views/tabs/tab.cc | 98 +- src/chrome/browser/ui/views/tabs/tab_strip.cc | 44 +- .../browser/ui/views/tabs/tab_style_views.cc | 404 +- .../browser/ui/views/tabs/tab_style_views.h | 8 +- .../drawable-hdpi/fre_product_logo.png | Bin .../drawable-hdpi/product_logo_name.png | Bin .../drawable-mdpi/fre_product_logo.png | Bin .../drawable-mdpi/product_logo_name.png | Bin .../drawable-xhdpi/fre_product_logo.png | Bin .../drawable-xhdpi/product_logo_name.png | Bin .../drawable-xxhdpi/fre_product_logo.png | Bin .../drawable-xxhdpi/product_logo_name.png | Bin .../drawable-xxxhdpi/fre_product_logo.png | Bin .../drawable-xxxhdpi/product_logo_name.png | Bin .../history/core/browser/history_backend.cc | 63 +- .../variations/service/variations_service.cc | 12 +- .../version_ui/resources/about_version.html | 11 + src/media/base/supported_types.cc | 37 +- .../renderer/core/exported/web_view_impl.cc | 3969 ----------------- src/tools/cfi/ignores.txt | 20 +- src/ui/gtk/native_theme_gtk.cc | 3 +- 34 files changed, 803 insertions(+), 5706 deletions(-) rename arm/{android => }/media/base/supported_types.cc (91%) rename arm/{android => }/media/ffmpeg/ffmpeg_common.cc (100%) delete mode 100644 arm/raspi/media/base/supported_types.cc delete mode 100644 arm/raspi/media/ffmpeg/ffmpeg_common.cc rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-hdpi/fre_product_logo.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-hdpi/product_logo_name.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-mdpi/fre_product_logo.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-mdpi/product_logo_name.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-xhdpi/fre_product_logo.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-xhdpi/product_logo_name.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-xxhdpi/fre_product_logo.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-xxhdpi/product_logo_name.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-xxxhdpi/fre_product_logo.png (100%) rename src/{chrome => components/browser_ui/styles}/android/java/res_chromium/drawable-xxxhdpi/product_logo_name.png (100%) delete mode 100644 src/third_party/blink/renderer/core/exported/web_view_impl.cc diff --git a/arm/android/media/media_options.gni b/arm/android/media/media_options.gni index e45fe3b2..40bad142 100644 --- a/arm/android/media/media_options.gni +++ b/arm/android/media/media_options.gni @@ -321,13 +321,9 @@ declare_args() { } declare_args() { - # Currently it is available on Win, Mac, Linux and ChromeOS since it requires - # the audio service to run in a separate process. - # ChromeOS(http://crbug/1407588): - # On CromeOS we are experimenting with the same set of systems CRAS runs on - # ie. is_chromeos_device. - chrome_wide_echo_cancellation_supported = - is_win || is_mac || is_linux || is_chromeos_device + # Currently it is available on Win, Mac and Linux, since it requires the audio + # service to run in a separate process. + chrome_wide_echo_cancellation_supported = is_win || is_mac || is_linux } # Do not expand this list without double-checking with OWNERS, this is a list of diff --git a/arm/android/media/base/supported_types.cc b/arm/media/base/supported_types.cc similarity index 91% rename from arm/android/media/base/supported_types.cc rename to arm/media/base/supported_types.cc index 0b2f596d..3fc515ec 100644 --- a/arm/android/media/base/supported_types.cc +++ b/arm/media/base/supported_types.cc @@ -42,24 +42,30 @@ namespace media { namespace { +template class SupplementalProfileCache { public: - void UpdateCache(const base::flat_set& profiles) { + void UpdateCache(const base::flat_set& profiles) { base::AutoLock lock(profiles_lock_); profiles_ = profiles; } - bool IsProfileSupported(media::VideoCodecProfile profile) { + bool IsProfileSupported(T profile) { base::AutoLock lock(profiles_lock_); return profiles_.find(profile) != profiles_.end(); } private: base::Lock profiles_lock_; - base::flat_set profiles_ GUARDED_BY(profiles_lock_); + base::flat_set profiles_ GUARDED_BY(profiles_lock_); }; -SupplementalProfileCache* GetSupplementalProfileCache() { - static base::NoDestructor cache; +SupplementalProfileCache* GetSupplementalProfileCache() { + static base::NoDestructor> cache; + return cache.get(); +} + +SupplementalProfileCache* GetSupplementalAudioTypeCache() { + static base::NoDestructor> cache; return cache.get(); } @@ -274,9 +280,7 @@ bool IsAACSupported(const AudioType& type) { return base::android::BuildInfo::GetInstance()->sdk_int() >= base::android::SDK_VERSION_P; #elif BUILDFLAG(IS_MAC) - if (__builtin_available(macOS 10.15, *)) - return true; - return false; + return true; #elif BUILDFLAG(IS_WIN) return base::win::GetVersion() >= base::win::Version::WIN11_22H2; #else @@ -284,6 +288,16 @@ bool IsAACSupported(const AudioType& type) { #endif } +bool IsDolbyVisionProfileSupported(const VideoType& type) { +#if BUILDFLAG(ENABLE_PLATFORM_HEVC) && \ + BUILDFLAG(PLATFORM_HAS_OPTIONAL_HEVC_SUPPORT) && \ + BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) + return GetSupplementalProfileCache()->IsProfileSupported(type.profile); +#else + return false; +#endif +} + } // namespace bool IsSupportedAudioType(const AudioType& type) { @@ -322,10 +336,11 @@ bool IsDefaultSupportedVideoType(const VideoType& type) { return IsHevcProfileSupported(type); case VideoCodec::kMPEG4: return IsMPEG4Supported(); + case VideoCodec::kDolbyVision: + return IsDolbyVisionProfileSupported(type); case VideoCodec::kUnknown: case VideoCodec::kVC1: case VideoCodec::kMPEG2: - case VideoCodec::kDolbyVision: return false; } } @@ -404,4 +419,8 @@ void UpdateDefaultSupportedVideoProfiles( GetSupplementalProfileCache()->UpdateCache(profiles); } +void UpdateDefaultSupportedAudioTypes(const base::flat_set& types) { + GetSupplementalAudioTypeCache()->UpdateCache(types); +} + } // namespace media diff --git a/arm/android/media/ffmpeg/ffmpeg_common.cc b/arm/media/ffmpeg/ffmpeg_common.cc similarity index 100% rename from arm/android/media/ffmpeg/ffmpeg_common.cc rename to arm/media/ffmpeg/ffmpeg_common.cc diff --git a/arm/raspi/media/base/supported_types.cc b/arm/raspi/media/base/supported_types.cc deleted file mode 100644 index 0b2f596d..00000000 --- a/arm/raspi/media/base/supported_types.cc +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright 2023 The Chromium Authors and Alex313031 -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/base/supported_types.h" - -#include "base/command_line.h" -#include "base/feature_list.h" -#include "base/logging.h" -#include "base/no_destructor.h" -#include "base/notreached.h" -#include "build/build_config.h" -#include "build/chromeos_buildflags.h" -#include "media/base/media.h" -#include "media/base/media_client.h" -#include "media/base/media_switches.h" -#include "media/media_buildflags.h" -#include "ui/display/display_switches.h" -#include "ui/gfx/hdr_metadata.h" - -#if BUILDFLAG(ENABLE_LIBVPX) -// TODO(dalecurtis): This technically should not be allowed in media/base. See -// TODO below about moving outside of base. -#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" // nogncheck -#include "third_party/libvpx/source/libvpx/vpx/vpx_codec.h" // nogncheck -#endif - -#if BUILDFLAG(IS_ANDROID) -#include "base/android/build_info.h" - -// TODO(dalecurtis): This include is not allowed by media/base since -// media/base/android is technically a different component. We should move -// supported_types*.{cc,h} out of media/base to fix this. -#include "media/base/android/media_codec_util.h" // nogncheck -#endif - -#if BUILDFLAG(IS_WIN) -#include "base/win/windows_version.h" -#endif - -namespace media { - -namespace { - -class SupplementalProfileCache { - public: - void UpdateCache(const base::flat_set& profiles) { - base::AutoLock lock(profiles_lock_); - profiles_ = profiles; - } - bool IsProfileSupported(media::VideoCodecProfile profile) { - base::AutoLock lock(profiles_lock_); - return profiles_.find(profile) != profiles_.end(); - } - - private: - base::Lock profiles_lock_; - base::flat_set profiles_ GUARDED_BY(profiles_lock_); -}; - -SupplementalProfileCache* GetSupplementalProfileCache() { - static base::NoDestructor cache; - return cache.get(); -} - -bool IsSupportedHdrMetadata(const gfx::HdrMetadataType& hdr_metadata_type) { - switch (hdr_metadata_type) { - case gfx::HdrMetadataType::kNone: - return true; - - case gfx::HdrMetadataType::kSmpteSt2086: - return base::FeatureList::IsEnabled(kSupportSmpteSt2086HdrMetadata); - - case gfx::HdrMetadataType::kSmpteSt2094_10: - case gfx::HdrMetadataType::kSmpteSt2094_40: - return false; - } -} - -bool IsColorSpaceSupported(const VideoColorSpace& color_space) { - switch (color_space.primaries) { - case VideoColorSpace::PrimaryID::EBU_3213_E: - case VideoColorSpace::PrimaryID::INVALID: - return false; - - // Transfers supported before color management. - case VideoColorSpace::PrimaryID::BT709: - case VideoColorSpace::PrimaryID::UNSPECIFIED: - case VideoColorSpace::PrimaryID::BT470M: - case VideoColorSpace::PrimaryID::BT470BG: - case VideoColorSpace::PrimaryID::SMPTE170M: - break; - - // Supported with color management. - case VideoColorSpace::PrimaryID::SMPTE240M: - case VideoColorSpace::PrimaryID::FILM: - case VideoColorSpace::PrimaryID::BT2020: - case VideoColorSpace::PrimaryID::SMPTEST428_1: - case VideoColorSpace::PrimaryID::SMPTEST431_2: - case VideoColorSpace::PrimaryID::SMPTEST432_1: - break; - } - - switch (color_space.transfer) { - // Transfers supported before color management. - case VideoColorSpace::TransferID::UNSPECIFIED: - case VideoColorSpace::TransferID::GAMMA22: - case VideoColorSpace::TransferID::BT709: - case VideoColorSpace::TransferID::SMPTE170M: - case VideoColorSpace::TransferID::BT2020_10: - case VideoColorSpace::TransferID::BT2020_12: - case VideoColorSpace::TransferID::IEC61966_2_1: - break; - - // Supported with color management. - case VideoColorSpace::TransferID::GAMMA28: - case VideoColorSpace::TransferID::SMPTE240M: - case VideoColorSpace::TransferID::LINEAR: - case VideoColorSpace::TransferID::LOG: - case VideoColorSpace::TransferID::LOG_SQRT: - case VideoColorSpace::TransferID::BT1361_ECG: - case VideoColorSpace::TransferID::SMPTEST2084: - case VideoColorSpace::TransferID::IEC61966_2_4: - case VideoColorSpace::TransferID::SMPTEST428_1: - case VideoColorSpace::TransferID::ARIB_STD_B67: - break; - - // Never supported. - case VideoColorSpace::TransferID::INVALID: - return false; - } - - switch (color_space.matrix) { - // Supported before color management. - case VideoColorSpace::MatrixID::BT709: - case VideoColorSpace::MatrixID::UNSPECIFIED: - case VideoColorSpace::MatrixID::BT470BG: - case VideoColorSpace::MatrixID::SMPTE170M: - case VideoColorSpace::MatrixID::BT2020_NCL: - break; - - // Supported with color management. - case VideoColorSpace::MatrixID::RGB: - case VideoColorSpace::MatrixID::FCC: - case VideoColorSpace::MatrixID::SMPTE240M: - case VideoColorSpace::MatrixID::YCOCG: - case VideoColorSpace::MatrixID::YDZDX: - case VideoColorSpace::MatrixID::BT2020_CL: - break; - - // Never supported. - case VideoColorSpace::MatrixID::INVALID: - return false; - } - - if (color_space.range == gfx::ColorSpace::RangeID::INVALID) - return false; - - return true; -} - -#if !BUILDFLAG(USE_PROPRIETARY_CODECS) -bool IsVideoCodecProprietary(VideoCodec codec) { - switch (codec) { - case VideoCodec::kVC1: - case VideoCodec::kH264: - case VideoCodec::kMPEG2: - case VideoCodec::kMPEG4: - case VideoCodec::kHEVC: - case VideoCodec::kDolbyVision: - return true; - case VideoCodec::kUnknown: - case VideoCodec::kTheora: - case VideoCodec::kVP8: - case VideoCodec::kVP9: - case VideoCodec::kAV1: - return false; - } -} - -bool IsAudioCodecProprietary(AudioCodec codec) { - switch (codec) { - case AudioCodec::kAAC: - case AudioCodec::kAC3: - case AudioCodec::kEAC3: - case AudioCodec::kAMR_NB: - case AudioCodec::kAMR_WB: - case AudioCodec::kGSM_MS: - case AudioCodec::kALAC: - case AudioCodec::kMpegHAudio: - case AudioCodec::kDTS: - case AudioCodec::kDTSXP2: - case AudioCodec::kDTSE: - return true; - - case AudioCodec::kFLAC: - case AudioCodec::kMP3: - case AudioCodec::kOpus: - case AudioCodec::kVorbis: - case AudioCodec::kPCM: - case AudioCodec::kPCM_MULAW: - case AudioCodec::kPCM_S16BE: - case AudioCodec::kPCM_S24BE: - case AudioCodec::kPCM_ALAW: - case AudioCodec::kUnknown: - return false; - } -} -#endif // !BUILDFLAG(USE_PROPRIETARY_CODECS) - -bool IsHevcProfileSupported(const VideoType& type) { - return true; -} - -bool IsVp9ProfileSupported(const VideoType& type) { -#if BUILDFLAG(ENABLE_LIBVPX) - // High bit depth capabilities may be toggled via LibVPX config flags. - static const bool vpx_supports_hbd = (vpx_codec_get_caps(vpx_codec_vp9_dx()) & - VPX_CODEC_CAP_HIGHBITDEPTH) != 0; - - // Color management required for HDR to not look terrible. - if (!IsColorSpaceSupported(type.color_space)) - return false; - - switch (type.profile) { - // LibVPX always supports Profiles 0 and 1. - case VP9PROFILE_PROFILE0: - case VP9PROFILE_PROFILE1: - return true; -#if BUILDFLAG(IS_ANDROID) - case VP9PROFILE_PROFILE2: - return vpx_supports_hbd || - MediaCodecUtil::IsVp9Profile2DecoderAvailable(); - case VP9PROFILE_PROFILE3: - return vpx_supports_hbd || - MediaCodecUtil::IsVp9Profile3DecoderAvailable(); -#else - case VP9PROFILE_PROFILE2: - case VP9PROFILE_PROFILE3: - return vpx_supports_hbd; -#endif // BUILDFLAG(IS_ANDROID) - default: - NOTREACHED(); - } -#endif // BUILDFLAG(ENABLE_LIBVPX) - return false; -} - -bool IsAV1Supported(const VideoType& type) { - // If the AV1 decoder is enabled, or if we're on Q or later, yes. -#if BUILDFLAG(ENABLE_AV1_DECODER) - return IsColorSpaceSupported(type.color_space); -#elif BUILDFLAG(IS_ANDROID) - return base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_Q && - IsColorSpaceSupported(type.color_space); -#else - return false; -#endif -} - -bool IsMPEG4Supported() { -#if BUILDFLAG(IS_CHROMEOS_ASH) - return true; -#else - return false; -#endif -} - -bool IsAACSupported(const AudioType& type) { - if (type.profile != AudioCodecProfile::kXHE_AAC) - return true; -#if BUILDFLAG(IS_ANDROID) - return base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_P; -#elif BUILDFLAG(IS_MAC) - if (__builtin_available(macOS 10.15, *)) - return true; - return false; -#elif BUILDFLAG(IS_WIN) - return base::win::GetVersion() >= base::win::Version::WIN11_22H2; -#else - return false; -#endif -} - -} // namespace - -bool IsSupportedAudioType(const AudioType& type) { - if (auto* media_client = GetMediaClient()) - return media_client->IsSupportedAudioType(type); - return IsDefaultSupportedAudioType(type); -} - -bool IsSupportedVideoType(const VideoType& type) { - if (auto* media_client = GetMediaClient()) - return media_client->IsSupportedVideoType(type); - return IsDefaultSupportedVideoType(type); -} - -// TODO(chcunningham): Add platform specific logic for Android (move from -// MimeUtilInternal). -bool IsDefaultSupportedVideoType(const VideoType& type) { - if (!IsSupportedHdrMetadata(type.hdr_metadata_type)) - return false; - -#if !BUILDFLAG(USE_PROPRIETARY_CODECS) - if (IsVideoCodecProprietary(type.codec)) - return false; -#endif - - switch (type.codec) { - case VideoCodec::kH264: - case VideoCodec::kVP8: - case VideoCodec::kTheora: - return true; - case VideoCodec::kAV1: - return IsAV1Supported(type); - case VideoCodec::kVP9: - return IsVp9ProfileSupported(type); - case VideoCodec::kHEVC: - return IsHevcProfileSupported(type); - case VideoCodec::kMPEG4: - return IsMPEG4Supported(); - case VideoCodec::kUnknown: - case VideoCodec::kVC1: - case VideoCodec::kMPEG2: - case VideoCodec::kDolbyVision: - return false; - } -} - -bool IsDefaultSupportedAudioType(const AudioType& type) { - if (type.spatial_rendering) - return false; - -#if !BUILDFLAG(USE_PROPRIETARY_CODECS) - if (IsAudioCodecProprietary(type.codec)) - return false; -#endif - - switch (type.codec) { - case AudioCodec::kAAC: - return IsAACSupported(type); - case AudioCodec::kFLAC: - case AudioCodec::kMP3: - case AudioCodec::kOpus: - case AudioCodec::kPCM: - case AudioCodec::kPCM_MULAW: - case AudioCodec::kPCM_S16BE: - case AudioCodec::kPCM_S24BE: - case AudioCodec::kPCM_ALAW: - case AudioCodec::kVorbis: - return true; - case AudioCodec::kAMR_NB: - case AudioCodec::kAMR_WB: - case AudioCodec::kGSM_MS: - case AudioCodec::kALAC: - case AudioCodec::kMpegHAudio: - case AudioCodec::kUnknown: - return false; - case AudioCodec::kDTS: - case AudioCodec::kDTSXP2: - case AudioCodec::kDTSE: -#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO) - return true; -#else - return false; -#endif - case AudioCodec::kAC3: - case AudioCodec::kEAC3: -#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) - return true; -#else - return false; -#endif - } -} - -bool IsBuiltInVideoCodec(VideoCodec codec) { -#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) - if (codec == VideoCodec::kTheora) - return true; - if (codec == VideoCodec::kVP8) - return true; -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - if (codec == VideoCodec::kH264 || codec == VideoCodec::kHEVC) - return true; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) -#endif // BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) -#if BUILDFLAG(ENABLE_LIBVPX) - if (codec == VideoCodec::kVP8 || codec == VideoCodec::kVP9) - return true; -#endif // BUILDFLAG(ENABLE_LIBVPX) -#if BUILDFLAG(ENABLE_AV1_DECODER) - if (codec == VideoCodec::kAV1) - return true; -#endif // BUILDFLAG(ENABLE_AV1_DECODER) - return false; -} - -void UpdateDefaultSupportedVideoProfiles( - const base::flat_set& profiles) { - GetSupplementalProfileCache()->UpdateCache(profiles); -} - -} // namespace media diff --git a/arm/raspi/media/ffmpeg/ffmpeg_common.cc b/arm/raspi/media/ffmpeg/ffmpeg_common.cc deleted file mode 100644 index 910f9ad5..00000000 --- a/arm/raspi/media/ffmpeg/ffmpeg_common.cc +++ /dev/null @@ -1,931 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/ffmpeg/ffmpeg_common.h" - -#include "base/hash/sha1.h" -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "build/build_config.h" -#include "media/base/audio_decoder_config.h" -#include "media/base/decoder_buffer.h" -#include "media/base/encryption_scheme.h" -#include "media/base/media_util.h" -#include "media/base/video_aspect_ratio.h" -#include "media/base/video_color_space.h" -#include "media/base/video_decoder_config.h" -#include "media/base/video_util.h" -#include "media/formats/mp4/box_definitions.h" -#include "media/media_buildflags.h" - -#if BUILDFLAG(USE_PROPRIETARY_CODECS) -#include "media/formats/mp4/aac.h" -#if BUILDFLAG(ENABLE_PLATFORM_HEVC) -#include "media/formats/mp4/hevc.h" -#endif -#endif - -namespace media { - -namespace { - -EncryptionScheme GetEncryptionScheme(const AVStream* stream) { - AVDictionaryEntry* key = - av_dict_get(stream->metadata, "enc_key_id", nullptr, 0); - return key ? EncryptionScheme::kCenc : EncryptionScheme::kUnencrypted; -} - -VideoDecoderConfig::AlphaMode GetAlphaMode(const AVStream* stream) { - AVDictionaryEntry* alpha_mode = - av_dict_get(stream->metadata, "alpha_mode", nullptr, 0); - return alpha_mode && !strcmp(alpha_mode->value, "1") - ? VideoDecoderConfig::AlphaMode::kHasAlpha - : VideoDecoderConfig::AlphaMode::kIsOpaque; -} - -VideoColorSpace GetGuessedColorSpace(const VideoColorSpace& color_space) { - return VideoColorSpace::FromGfxColorSpace( - // convert to gfx color space and make a guess. - color_space.GuessGfxColorSpace()); -} - -} // namespace - -// Alignment requirement by FFmpeg for input and output buffers. This need to -// be updated to match FFmpeg when it changes. -#if defined(ARCH_CPU_ARM_FAMILY) -static const int kFFmpegBufferAddressAlignment = 16; -#else -static const int kFFmpegBufferAddressAlignment = 32; -#endif - -// Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally. -// See video_get_buffer() in libavcodec/utils.c. -static const int kFFmpegOutputBufferPaddingSize = 16; - -static_assert(VideoFrame::kFrameSizePadding >= kFFmpegOutputBufferPaddingSize, - "VideoFrame padding size does not fit ffmpeg requirement"); - -static_assert( - VideoFrame::kFrameAddressAlignment >= kFFmpegBufferAddressAlignment && - VideoFrame::kFrameAddressAlignment % kFFmpegBufferAddressAlignment == 0, - "VideoFrame frame address alignment does not fit ffmpeg requirement"); - -static const AVRational kMicrosBase = { 1, base::Time::kMicrosecondsPerSecond }; - -base::TimeDelta ConvertFromTimeBase(const AVRational& time_base, - int64_t timestamp) { - int64_t microseconds = av_rescale_q(timestamp, time_base, kMicrosBase); - return base::Microseconds(microseconds); -} - -int64_t ConvertToTimeBase(const AVRational& time_base, - const base::TimeDelta& timestamp) { - return av_rescale_q(timestamp.InMicroseconds(), kMicrosBase, time_base); -} - -AudioCodec CodecIDToAudioCodec(AVCodecID codec_id) { - switch (codec_id) { - case AV_CODEC_ID_AAC: - return AudioCodec::kAAC; -#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) - case AV_CODEC_ID_AC3: - return AudioCodec::kAC3; - case AV_CODEC_ID_EAC3: - return AudioCodec::kEAC3; -#endif - case AV_CODEC_ID_MP3: - return AudioCodec::kMP3; - case AV_CODEC_ID_VORBIS: - return AudioCodec::kVorbis; - case AV_CODEC_ID_PCM_U8: - case AV_CODEC_ID_PCM_S16LE: - case AV_CODEC_ID_PCM_S24LE: - case AV_CODEC_ID_PCM_S32LE: - case AV_CODEC_ID_PCM_F32LE: - return AudioCodec::kPCM; - case AV_CODEC_ID_PCM_S16BE: - return AudioCodec::kPCM_S16BE; - case AV_CODEC_ID_PCM_S24BE: - return AudioCodec::kPCM_S24BE; - case AV_CODEC_ID_FLAC: - return AudioCodec::kFLAC; - case AV_CODEC_ID_PCM_ALAW: - return AudioCodec::kPCM_ALAW; - case AV_CODEC_ID_PCM_MULAW: - return AudioCodec::kPCM_MULAW; - case AV_CODEC_ID_OPUS: - return AudioCodec::kOpus; - case AV_CODEC_ID_ALAC: - return AudioCodec::kALAC; -#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) - case AV_CODEC_ID_MPEGH_3D_AUDIO: - return AudioCodec::kMpegHAudio; -#endif - default: - DVLOG(1) << "Unknown audio CodecID: " << codec_id; - } - return AudioCodec::kUnknown; -} - -AVCodecID AudioCodecToCodecID(AudioCodec audio_codec, - SampleFormat sample_format) { - switch (audio_codec) { - case AudioCodec::kAAC: - return AV_CODEC_ID_AAC; - case AudioCodec::kALAC: - return AV_CODEC_ID_ALAC; - case AudioCodec::kMP3: - return AV_CODEC_ID_MP3; - case AudioCodec::kPCM: - switch (sample_format) { - case kSampleFormatU8: - return AV_CODEC_ID_PCM_U8; - case kSampleFormatS16: - return AV_CODEC_ID_PCM_S16LE; - case kSampleFormatS24: - return AV_CODEC_ID_PCM_S24LE; - case kSampleFormatS32: - return AV_CODEC_ID_PCM_S32LE; - case kSampleFormatF32: - return AV_CODEC_ID_PCM_F32LE; - default: - DVLOG(1) << "Unsupported sample format: " << sample_format; - } - break; - case AudioCodec::kPCM_S16BE: - return AV_CODEC_ID_PCM_S16BE; - case AudioCodec::kPCM_S24BE: - return AV_CODEC_ID_PCM_S24BE; - case AudioCodec::kVorbis: - return AV_CODEC_ID_VORBIS; - case AudioCodec::kFLAC: - return AV_CODEC_ID_FLAC; - case AudioCodec::kPCM_ALAW: - return AV_CODEC_ID_PCM_ALAW; - case AudioCodec::kPCM_MULAW: - return AV_CODEC_ID_PCM_MULAW; - case AudioCodec::kOpus: - return AV_CODEC_ID_OPUS; -#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) - case AudioCodec::kMpegHAudio: - return AV_CODEC_ID_MPEGH_3D_AUDIO; -#endif - default: - DVLOG(1) << "Unknown AudioCodec: " << audio_codec; - } - return AV_CODEC_ID_NONE; -} - -// Converts an FFmpeg video codec ID into its corresponding supported codec id. -static VideoCodec CodecIDToVideoCodec(AVCodecID codec_id) { - switch (codec_id) { - case AV_CODEC_ID_H264: - return VideoCodec::kH264; -#if BUILDFLAG(ENABLE_PLATFORM_HEVC) - case AV_CODEC_ID_HEVC: - return VideoCodec::kHEVC; -#endif - case AV_CODEC_ID_THEORA: - return VideoCodec::kTheora; - case AV_CODEC_ID_MPEG4: - return VideoCodec::kMPEG4; - case AV_CODEC_ID_VP8: - return VideoCodec::kVP8; - case AV_CODEC_ID_VP9: - return VideoCodec::kVP9; - case AV_CODEC_ID_AV1: - return VideoCodec::kAV1; - default: - DVLOG(1) << "Unknown video CodecID: " << codec_id; - } - return VideoCodec::kUnknown; -} - -AVCodecID VideoCodecToCodecID(VideoCodec video_codec) { - switch (video_codec) { - case VideoCodec::kH264: - return AV_CODEC_ID_H264; -#if BUILDFLAG(ENABLE_PLATFORM_HEVC) - case VideoCodec::kHEVC: - return AV_CODEC_ID_HEVC; -#endif - case VideoCodec::kTheora: - return AV_CODEC_ID_THEORA; - case VideoCodec::kMPEG4: - return AV_CODEC_ID_MPEG4; - case VideoCodec::kVP8: - return AV_CODEC_ID_VP8; - case VideoCodec::kVP9: - return AV_CODEC_ID_VP9; - case VideoCodec::kAV1: - return AV_CODEC_ID_AV1; - default: - DVLOG(1) << "Unknown VideoCodec: " << video_codec; - } - return AV_CODEC_ID_NONE; -} - -static VideoCodecProfile ProfileIDToVideoCodecProfile(int profile) { - // Clear out the CONSTRAINED & INTRA flags which are strict subsets of the - // corresponding profiles with which they're used. - profile &= ~FF_PROFILE_H264_CONSTRAINED; - profile &= ~FF_PROFILE_H264_INTRA; - switch (profile) { - case FF_PROFILE_H264_BASELINE: - return H264PROFILE_BASELINE; - case FF_PROFILE_H264_MAIN: - return H264PROFILE_MAIN; - case FF_PROFILE_H264_EXTENDED: - return H264PROFILE_EXTENDED; - case FF_PROFILE_H264_HIGH: - return H264PROFILE_HIGH; - case FF_PROFILE_H264_HIGH_10: - return H264PROFILE_HIGH10PROFILE; - case FF_PROFILE_H264_HIGH_422: - return H264PROFILE_HIGH422PROFILE; - case FF_PROFILE_H264_HIGH_444_PREDICTIVE: - return H264PROFILE_HIGH444PREDICTIVEPROFILE; - default: - DVLOG(1) << "Unknown profile id: " << profile; - } - return VIDEO_CODEC_PROFILE_UNKNOWN; -} - -static int VideoCodecProfileToProfileID(VideoCodecProfile profile) { - switch (profile) { - case H264PROFILE_BASELINE: - return FF_PROFILE_H264_BASELINE; - case H264PROFILE_MAIN: - return FF_PROFILE_H264_MAIN; - case H264PROFILE_EXTENDED: - return FF_PROFILE_H264_EXTENDED; - case H264PROFILE_HIGH: - return FF_PROFILE_H264_HIGH; - case H264PROFILE_HIGH10PROFILE: - return FF_PROFILE_H264_HIGH_10; - case H264PROFILE_HIGH422PROFILE: - return FF_PROFILE_H264_HIGH_422; - case H264PROFILE_HIGH444PREDICTIVEPROFILE: - return FF_PROFILE_H264_HIGH_444_PREDICTIVE; - default: - DVLOG(1) << "Unknown VideoCodecProfile: " << profile; - } - return FF_PROFILE_UNKNOWN; -} - -SampleFormat AVSampleFormatToSampleFormat(AVSampleFormat sample_format, - AVCodecID codec_id) { - switch (sample_format) { - case AV_SAMPLE_FMT_U8: - return kSampleFormatU8; - case AV_SAMPLE_FMT_S16: - return kSampleFormatS16; - case AV_SAMPLE_FMT_S32: - if (codec_id == AV_CODEC_ID_PCM_S24LE) - return kSampleFormatS24; - else - return kSampleFormatS32; - case AV_SAMPLE_FMT_FLT: - return kSampleFormatF32; - case AV_SAMPLE_FMT_S16P: - return kSampleFormatPlanarS16; - case AV_SAMPLE_FMT_S32P: - return kSampleFormatPlanarS32; - case AV_SAMPLE_FMT_FLTP: - return kSampleFormatPlanarF32; - default: - DVLOG(1) << "Unknown AVSampleFormat: " << sample_format; - } - return kUnknownSampleFormat; -} - -static AVSampleFormat SampleFormatToAVSampleFormat(SampleFormat sample_format) { - switch (sample_format) { - case kSampleFormatU8: - return AV_SAMPLE_FMT_U8; - case kSampleFormatS16: - return AV_SAMPLE_FMT_S16; - // pcm_s24le is treated as a codec with sample format s32 in ffmpeg - case kSampleFormatS24: - case kSampleFormatS32: - return AV_SAMPLE_FMT_S32; - case kSampleFormatF32: - return AV_SAMPLE_FMT_FLT; - case kSampleFormatPlanarS16: - return AV_SAMPLE_FMT_S16P; - case kSampleFormatPlanarF32: - return AV_SAMPLE_FMT_FLTP; - default: - DVLOG(1) << "Unknown SampleFormat: " << sample_format; - } - return AV_SAMPLE_FMT_NONE; -} - -bool AVCodecContextToAudioDecoderConfig(const AVCodecContext* codec_context, - EncryptionScheme encryption_scheme, - AudioDecoderConfig* config) { - DCHECK_EQ(codec_context->codec_type, AVMEDIA_TYPE_AUDIO); - - AudioCodec codec = CodecIDToAudioCodec(codec_context->codec_id); - - SampleFormat sample_format = AVSampleFormatToSampleFormat( - codec_context->sample_fmt, codec_context->codec_id); - - ChannelLayout channel_layout = - codec_context->ch_layout.nb_channels > 8 - ? CHANNEL_LAYOUT_DISCRETE - : ChannelLayoutToChromeChannelLayout( - codec_context->ch_layout.u.mask, - codec_context->ch_layout.nb_channels); - - switch (codec) { - // For AC3/EAC3 we enable only demuxing, but not decoding, so FFmpeg does - // not fill |sample_fmt|. - case AudioCodec::kAC3: - case AudioCodec::kEAC3: -#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) - // The spec for AC3/EAC3 audio is ETSI TS 102 366. According to sections - // F.3.1 and F.5.1 in that spec the sample_format for AC3/EAC3 must be 16. - sample_format = kSampleFormatS16; -#else - NOTREACHED(); -#endif - break; -#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) - case AudioCodec::kMpegHAudio: - channel_layout = CHANNEL_LAYOUT_BITSTREAM; - sample_format = kSampleFormatMpegHAudio; - break; -#endif - - default: - break; - } - - base::TimeDelta seek_preroll; - if (codec_context->seek_preroll > 0) { - seek_preroll = base::Microseconds(codec_context->seek_preroll * 1000000.0 / - codec_context->sample_rate); - } - - // AVStream occasionally has invalid extra data. See http://crbug.com/517163 - if ((codec_context->extradata_size == 0) != - (codec_context->extradata == nullptr)) { - LOG(ERROR) << __func__ - << (codec_context->extradata == nullptr ? " NULL" : " Non-NULL") - << " extra data cannot have size of " - << codec_context->extradata_size << "."; - return false; - } - - std::vector extra_data; - if (codec_context->extradata_size > 0) { - extra_data.assign(codec_context->extradata, - codec_context->extradata + codec_context->extradata_size); - } - - config->Initialize(codec, sample_format, channel_layout, codec_context->sample_rate, - extra_data, encryption_scheme, seek_preroll, - codec_context->delay); - if (channel_layout == CHANNEL_LAYOUT_DISCRETE) - config->SetChannelsForDiscrete(codec_context->ch_layout.nb_channels); - -#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) - // These are bitstream formats unknown to ffmpeg, so they don't have - // a known sample format size. - if (codec == AudioCodec::kAC3 || codec == AudioCodec::kEAC3) - return true; -#endif -#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) - if (codec == AudioCodec::kMpegHAudio) - return true; -#endif - -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - if (codec == AudioCodec::kAAC) { - config->set_aac_extra_data(extra_data); - - // TODO(dalecurtis): Just use the profile from the codec context if ffmpeg - // ever starts supporting xHE-AAC. - if (codec_context->profile == FF_PROFILE_UNKNOWN) { - // Errors aren't fatal here, so just drop any MediaLog messages. - NullMediaLog media_log; - mp4::AAC aac_parser; - if (aac_parser.Parse(extra_data, &media_log)) - config->set_profile(aac_parser.GetProfile()); - } - } -#endif - - // Verify that AudioConfig.bits_per_channel was calculated correctly for - // codecs that have |sample_fmt| set by FFmpeg. - DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8, - config->bits_per_channel()); - return true; -} - -std::unique_ptr -AVStreamToAVCodecContext(const AVStream* stream) { - std::unique_ptr codec_context( - avcodec_alloc_context3(nullptr)); - if (avcodec_parameters_to_context(codec_context.get(), stream->codecpar) < - 0) { - return nullptr; - } - - return codec_context; -} - -bool AVStreamToAudioDecoderConfig(const AVStream* stream, - AudioDecoderConfig* config) { - std::unique_ptr codec_context( - AVStreamToAVCodecContext(stream)); - if (!codec_context) - return false; - - return AVCodecContextToAudioDecoderConfig( - codec_context.get(), GetEncryptionScheme(stream), config); -} - -void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config, - AVCodecContext* codec_context) { - codec_context->codec_type = AVMEDIA_TYPE_AUDIO; - codec_context->codec_id = AudioCodecToCodecID(config.codec(), - config.sample_format()); - codec_context->sample_fmt = SampleFormatToAVSampleFormat( - config.sample_format()); - - // TODO(scherkus): should we set |channel_layout|? I'm not sure if FFmpeg uses - // said information to decode. - codec_context->ch_layout.nb_channels = config.channels(); - codec_context->sample_rate = config.samples_per_second(); - - if (config.extra_data().empty()) { - codec_context->extradata = nullptr; - codec_context->extradata_size = 0; - } else { - codec_context->extradata_size = config.extra_data().size(); - codec_context->extradata = reinterpret_cast( - av_malloc(config.extra_data().size() + AV_INPUT_BUFFER_PADDING_SIZE)); - memcpy(codec_context->extradata, &config.extra_data()[0], - config.extra_data().size()); - memset(codec_context->extradata + config.extra_data().size(), '\0', - AV_INPUT_BUFFER_PADDING_SIZE); - } -} - -bool AVStreamToVideoDecoderConfig(const AVStream* stream, - VideoDecoderConfig* config) { - std::unique_ptr codec_context( - AVStreamToAVCodecContext(stream)); - if (!codec_context) - return false; - - // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true - // for now, but may not always be true forever. Fix this in the future. - gfx::Rect visible_rect(codec_context->width, codec_context->height); - gfx::Size coded_size = visible_rect.size(); - gfx::HDRMetadata hdr_metadata; - - // In some cases a container may have a DAR but no PAR, but FFmpeg translates - // everything to PAR. It is possible to get the render width and height, but I - // didn't find a way to determine whether that should be preferred to the PAR. - VideoAspectRatio aspect_ratio; - if (stream->sample_aspect_ratio.num) { - aspect_ratio = VideoAspectRatio::PAR(stream->sample_aspect_ratio.num, - stream->sample_aspect_ratio.den); - } else if (codec_context->sample_aspect_ratio.num) { - aspect_ratio = - VideoAspectRatio::PAR(codec_context->sample_aspect_ratio.num, - codec_context->sample_aspect_ratio.den); - } - - // Used to guess color space and to create the config. The first use should - // probably change to coded size, and the second should be removed as part of - // crbug.com/1214061. - gfx::Size natural_size = aspect_ratio.GetNaturalSize(visible_rect); - - VideoCodec codec = CodecIDToVideoCodec(codec_context->codec_id); - - // Without the ffmpeg decoder configured, libavformat is unable to get the - // profile, format, or coded size. So choose sensible defaults and let - // decoders fail later if the configuration is actually unsupported. - // - // TODO(chcunningham): We need real profiles for all of the codecs below to - // actually handle capabilities requests correctly. http://crbug.com/784610 - VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; - - // Prefer the color space found by libavcodec if available - VideoColorSpace color_space = - VideoColorSpace(codec_context->color_primaries, codec_context->color_trc, - codec_context->colorspace, - codec_context->color_range == AVCOL_RANGE_JPEG - ? gfx::ColorSpace::RangeID::FULL - : gfx::ColorSpace::RangeID::LIMITED); - - VideoDecoderConfig::AlphaMode alpha_mode = GetAlphaMode(stream); - - switch (codec) { -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - case VideoCodec::kH264: { - profile = ProfileIDToVideoCodecProfile(codec_context->profile); - // if the profile is still unknown, try to extract it from - // the extradata using the internal parser - if (profile == VIDEO_CODEC_PROFILE_UNKNOWN && codec_context->extradata && - codec_context->extradata_size) { - mp4::AVCDecoderConfigurationRecord avc_config; - if (avc_config.Parse(codec_context->extradata, - codec_context->extradata_size)) { - profile = ProfileIDToVideoCodecProfile(avc_config.profile_indication); - } - } - // All the heuristics failed, let's assign a default profile - if (profile == VIDEO_CODEC_PROFILE_UNKNOWN) - profile = H264PROFILE_BASELINE; - break; - } -#if BUILDFLAG(ENABLE_PLATFORM_HEVC) - case VideoCodec::kHEVC: { - int hevc_profile = -1; - // We need to parse extradata each time, because we wont add ffmpeg - // hevc decoder & parser to chromium and codec_context->profile - // should always be FF_PROFILE_UNKNOWN (-99) here - if (codec_context->extradata && codec_context->extradata_size) { - mp4::HEVCDecoderConfigurationRecord hevc_config; - if (hevc_config.Parse(codec_context->extradata, - codec_context->extradata_size)) { - hevc_profile = hevc_config.general_profile_idc; -#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER) - if (!color_space.IsSpecified()) { - // We should try to parsed color space from SPS if the - // result from libavcodec is not specified in case - // that some encoder not write extra colorspace info to - // the container - color_space = hevc_config.GetColorSpace(); - } - hdr_metadata = hevc_config.GetHDRMetadata(); - alpha_mode = hevc_config.GetAlphaMode(); -#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER) - } - } - // The values of general_profile_idc are taken from the HEVC standard, see - // the latest https://www.itu.int/rec/T-REC-H.265/en - switch (hevc_profile) { - case 1: - profile = HEVCPROFILE_MAIN; - break; - case 2: - profile = HEVCPROFILE_MAIN10; - break; - case 3: - profile = HEVCPROFILE_MAIN_STILL_PICTURE; - break; - case 4: - profile = HEVCPROFILE_REXT; - break; - case 5: - profile = HEVCPROFILE_HIGH_THROUGHPUT; - break; - case 6: - profile = HEVCPROFILE_MULTIVIEW_MAIN; - break; - case 7: - profile = HEVCPROFILE_SCALABLE_MAIN; - break; - case 8: - profile = HEVCPROFILE_3D_MAIN; - break; - case 9: - profile = HEVCPROFILE_SCREEN_EXTENDED; - break; - case 10: - profile = HEVCPROFILE_SCALABLE_REXT; - break; - case 11: - profile = HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED; - break; - default: - // Always assign a default if all heuristics fail. - profile = HEVCPROFILE_MAIN; - break; - } - break; - } -#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) - case VideoCodec::kVP8: - profile = VP8PROFILE_ANY; - break; - case VideoCodec::kVP9: - switch (codec_context->profile) { - case FF_PROFILE_VP9_0: - profile = VP9PROFILE_PROFILE0; - break; - case FF_PROFILE_VP9_1: - profile = VP9PROFILE_PROFILE1; - break; - case FF_PROFILE_VP9_2: - profile = VP9PROFILE_PROFILE2; - break; - case FF_PROFILE_VP9_3: - profile = VP9PROFILE_PROFILE3; - break; - default: - profile = VP9PROFILE_MIN; - break; - } - break; -#if BUILDFLAG(ENABLE_AV1_DECODER) - case VideoCodec::kAV1: - profile = AV1PROFILE_PROFILE_MAIN; - if (codec_context->extradata && codec_context->extradata_size) { - mp4::AV1CodecConfigurationRecord av1_config; - if (av1_config.Parse(codec_context->extradata, - codec_context->extradata_size)) { - profile = av1_config.profile; - } else { - DLOG(WARNING) << "Failed to parse AV1 extra data for profile."; - } - } - break; -#endif // BUILDFLAG(ENABLE_AV1_DECODER) - case VideoCodec::kTheora: - profile = THEORAPROFILE_ANY; - break; - default: - profile = ProfileIDToVideoCodecProfile(codec_context->profile); - } - - void* display_matrix = - av_stream_get_side_data(stream, AV_PKT_DATA_DISPLAYMATRIX, nullptr); - - VideoTransformation video_transformation = VideoTransformation(); - if (display_matrix) { - video_transformation = VideoTransformation::FromFFmpegDisplayMatrix( - static_cast(display_matrix)); - } - - if (!color_space.IsSpecified()) { - // VP9 frames may have color information, but that information cannot - // express new color spaces, like HDR. For that reason, color space - // information from the container should take precedence over color space - // information from the VP9 stream. However, if we infer the color space - // based on resolution here, it looks as if it came from the container. - // Since this inference causes color shifts and is slated to go away - // we just skip it for VP9 and leave the color space undefined, which - // will make the VP9 decoder behave correctly.. - // We also ignore the resolution for AV1, since it's new and it's easy - // to make it behave correctly from the get-go. - // TODO(hubbe): Skip this inference for all codecs. - if (codec_context->codec_id != AV_CODEC_ID_VP9 && - codec_context->codec_id != AV_CODEC_ID_AV1) { - // Otherwise, assume that SD video is usually Rec.601, and HD is usually - // Rec.709. - color_space = (natural_size.height() < 720) ? VideoColorSpace::REC601() - : VideoColorSpace::REC709(); - } - } else if (codec_context->codec_id == AV_CODEC_ID_H264 && - codec_context->colorspace == AVCOL_SPC_RGB && - AVPixelFormatToVideoPixelFormat(codec_context->pix_fmt) == - PIXEL_FORMAT_I420) { - // Some H.264 videos contain a VUI that specifies a color matrix of GBR, - // when they are actually ordinary YUV. Only 4:2:0 formats are checked, - // because GBR is reasonable for 4:4:4 content. See crbug.com/1067377. - color_space = VideoColorSpace::REC709(); - } else if (codec_context->codec_id == AV_CODEC_ID_HEVC && - (color_space.primaries == VideoColorSpace::PrimaryID::INVALID || - color_space.transfer == VideoColorSpace::TransferID::INVALID || - color_space.matrix == VideoColorSpace::MatrixID::INVALID) && - AVPixelFormatToVideoPixelFormat(codec_context->pix_fmt) == - PIXEL_FORMAT_I420) { - // Some HEVC SDR content encoded by the Adobe Premiere HW HEVC encoder has - // invalid primaries but valid transfer and matrix, and some HEVC SDR - // content encoded by web camera has invalid primaries and transfer, this - // will cause IsHevcProfileSupported return "false" and fail to playback. - // make a guess can at least make these videos able to play. See - // crbug.com/1374270. - color_space = GetGuessedColorSpace(color_space); - } - - // AVCodecContext occasionally has invalid extra data. See - // http://crbug.com/517163 - if (codec_context->extradata != nullptr && - codec_context->extradata_size == 0) { - DLOG(ERROR) << __func__ << " Non-Null extra data cannot have size of 0."; - return false; - } - - std::vector extra_data; - if (codec_context->extradata_size > 0) { - extra_data.assign(codec_context->extradata, - codec_context->extradata + codec_context->extradata_size); - } - // TODO(tmathmeyer) ffmpeg can't provide us with an actual video rotation yet. - config->Initialize(codec, profile, alpha_mode, color_space, - video_transformation, coded_size, visible_rect, - natural_size, extra_data, GetEncryptionScheme(stream)); - // Set the aspect ratio explicitly since our version hasn't been rounded. - config->set_aspect_ratio(aspect_ratio); - - if (stream->nb_side_data) { - for (int i = 0; i < stream->nb_side_data; ++i) { - AVPacketSideData side_data = stream->side_data[i]; - if (side_data.type != AV_PKT_DATA_MASTERING_DISPLAY_METADATA) - continue; - - AVMasteringDisplayMetadata* metadata = - reinterpret_cast(side_data.data); - gfx::HdrMetadataSmpteSt2086 smpte_st_2086; - if (metadata->has_primaries) { - smpte_st_2086.primaries = { - static_cast(av_q2d(metadata->display_primaries[0][0])), - static_cast(av_q2d(metadata->display_primaries[0][1])), - static_cast(av_q2d(metadata->display_primaries[1][0])), - static_cast(av_q2d(metadata->display_primaries[1][1])), - static_cast(av_q2d(metadata->display_primaries[2][0])), - static_cast(av_q2d(metadata->display_primaries[2][1])), - static_cast(av_q2d(metadata->white_point[0])), - static_cast(av_q2d(metadata->white_point[1])), - }; - } - if (metadata->has_luminance) { - smpte_st_2086.luminance_max = av_q2d(metadata->max_luminance); - smpte_st_2086.luminance_min = av_q2d(metadata->min_luminance); - } - - // TODO(https://crbug.com/1446302): Consider rejecting metadata that does - // not specify all values. - if (metadata->has_primaries || metadata->has_luminance) { - hdr_metadata.smpte_st_2086 = smpte_st_2086; - } - } - } - - if (hdr_metadata.IsValid()) { - config->set_hdr_metadata(hdr_metadata); - } - - return true; -} - -void VideoDecoderConfigToAVCodecContext( - const VideoDecoderConfig& config, - AVCodecContext* codec_context) { - codec_context->codec_type = AVMEDIA_TYPE_VIDEO; - codec_context->codec_id = VideoCodecToCodecID(config.codec()); - codec_context->profile = VideoCodecProfileToProfileID(config.profile()); - codec_context->coded_width = config.coded_size().width(); - codec_context->coded_height = config.coded_size().height(); - if (config.color_space_info().range == gfx::ColorSpace::RangeID::FULL) - codec_context->color_range = AVCOL_RANGE_JPEG; - - if (config.extra_data().empty()) { - codec_context->extradata = nullptr; - codec_context->extradata_size = 0; - } else { - codec_context->extradata_size = config.extra_data().size(); - codec_context->extradata = reinterpret_cast( - av_malloc(config.extra_data().size() + AV_INPUT_BUFFER_PADDING_SIZE)); - memcpy(codec_context->extradata, &config.extra_data()[0], - config.extra_data().size()); - memset(codec_context->extradata + config.extra_data().size(), '\0', - AV_INPUT_BUFFER_PADDING_SIZE); - } -} - -ChannelLayout ChannelLayoutToChromeChannelLayout(int64_t layout, int channels) { - switch (layout) { - case AV_CH_LAYOUT_MONO: - return CHANNEL_LAYOUT_MONO; - case AV_CH_LAYOUT_STEREO: - return CHANNEL_LAYOUT_STEREO; - case AV_CH_LAYOUT_2_1: - return CHANNEL_LAYOUT_2_1; - case AV_CH_LAYOUT_SURROUND: - return CHANNEL_LAYOUT_SURROUND; - case AV_CH_LAYOUT_4POINT0: - return CHANNEL_LAYOUT_4_0; - case AV_CH_LAYOUT_2_2: - return CHANNEL_LAYOUT_2_2; - case AV_CH_LAYOUT_QUAD: - return CHANNEL_LAYOUT_QUAD; - case AV_CH_LAYOUT_5POINT0: - return CHANNEL_LAYOUT_5_0; - case AV_CH_LAYOUT_5POINT1: - return CHANNEL_LAYOUT_5_1; - case AV_CH_LAYOUT_5POINT0_BACK: - return CHANNEL_LAYOUT_5_0_BACK; - case AV_CH_LAYOUT_5POINT1_BACK: - return CHANNEL_LAYOUT_5_1_BACK; - case AV_CH_LAYOUT_7POINT0: - return CHANNEL_LAYOUT_7_0; - case AV_CH_LAYOUT_7POINT1: - return CHANNEL_LAYOUT_7_1; - case AV_CH_LAYOUT_7POINT1_WIDE: - return CHANNEL_LAYOUT_7_1_WIDE; - case AV_CH_LAYOUT_STEREO_DOWNMIX: - return CHANNEL_LAYOUT_STEREO_DOWNMIX; - case AV_CH_LAYOUT_2POINT1: - return CHANNEL_LAYOUT_2POINT1; - case AV_CH_LAYOUT_3POINT1: - return CHANNEL_LAYOUT_3_1; - case AV_CH_LAYOUT_4POINT1: - return CHANNEL_LAYOUT_4_1; - case AV_CH_LAYOUT_6POINT0: - return CHANNEL_LAYOUT_6_0; - case AV_CH_LAYOUT_6POINT0_FRONT: - return CHANNEL_LAYOUT_6_0_FRONT; - case AV_CH_LAYOUT_HEXAGONAL: - return CHANNEL_LAYOUT_HEXAGONAL; - case AV_CH_LAYOUT_6POINT1: - return CHANNEL_LAYOUT_6_1; - case AV_CH_LAYOUT_6POINT1_BACK: - return CHANNEL_LAYOUT_6_1_BACK; - case AV_CH_LAYOUT_6POINT1_FRONT: - return CHANNEL_LAYOUT_6_1_FRONT; - case AV_CH_LAYOUT_7POINT0_FRONT: - return CHANNEL_LAYOUT_7_0_FRONT; -#ifdef AV_CH_LAYOUT_7POINT1_WIDE_BACK - case AV_CH_LAYOUT_7POINT1_WIDE_BACK: - return CHANNEL_LAYOUT_7_1_WIDE_BACK; -#endif - case AV_CH_LAYOUT_OCTAGONAL: - return CHANNEL_LAYOUT_OCTAGONAL; - default: - // FFmpeg channel_layout is 0 for .wav and .mp3. Attempt to guess layout - // based on the channel count. - return GuessChannelLayout(channels); - } -} - -#if !defined(ARCH_CPU_LITTLE_ENDIAN) -#error The code below assumes little-endianness. -#endif - -VideoPixelFormat AVPixelFormatToVideoPixelFormat(AVPixelFormat pixel_format) { - // The YUVJ alternatives are FFmpeg's (deprecated, but still in use) way to - // specify a pixel format and full range color combination. - switch (pixel_format) { - case AV_PIX_FMT_YUV444P: - case AV_PIX_FMT_YUVJ444P: - return PIXEL_FORMAT_I444; - - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUVJ420P: - return PIXEL_FORMAT_I420; - - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUVJ422P: - return PIXEL_FORMAT_I422; - - case AV_PIX_FMT_YUVA420P: - return PIXEL_FORMAT_I420A; - - case AV_PIX_FMT_YUV420P9LE: - return PIXEL_FORMAT_YUV420P9; - case AV_PIX_FMT_YUV420P10LE: - return PIXEL_FORMAT_YUV420P10; - case AV_PIX_FMT_YUV420P12LE: - return PIXEL_FORMAT_YUV420P12; - - case AV_PIX_FMT_YUV422P9LE: - return PIXEL_FORMAT_YUV422P9; - case AV_PIX_FMT_YUV422P10LE: - return PIXEL_FORMAT_YUV422P10; - case AV_PIX_FMT_YUV422P12LE: - return PIXEL_FORMAT_YUV422P12; - - case AV_PIX_FMT_YUV444P9LE: - return PIXEL_FORMAT_YUV444P9; - case AV_PIX_FMT_YUV444P10LE: - return PIXEL_FORMAT_YUV444P10; - case AV_PIX_FMT_YUV444P12LE: - return PIXEL_FORMAT_YUV444P12; - - case AV_PIX_FMT_P016LE: - return PIXEL_FORMAT_P016LE; - - default: - DVLOG(1) << "Unsupported AVPixelFormat: " << pixel_format; - } - return PIXEL_FORMAT_UNKNOWN; -} - -std::string AVErrorToString(int errnum) { - char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0}; - av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE); - return std::string(errbuf); -} - -int32_t HashCodecName(const char* codec_name) { - // Use the first 32-bits from the SHA1 hash as the identifier. - int32_t hash; - memcpy(&hash, base::SHA1HashString(codec_name).substr(0, 4).c_str(), 4); - return hash; -} - -} // namespace media diff --git a/infra/THORIUM_DEV_BOOKMARKS.html b/infra/THORIUM_DEV_BOOKMARKS.html index 2b3cf0da..86fdf703 100644 --- a/infra/THORIUM_DEV_BOOKMARKS.html +++ b/infra/THORIUM_DEV_BOOKMARKS.html @@ -190,6 +190,7 @@

java - Chromium Code Search
BUILD.gn - Chromium Code Search +
chrome_public_apk_tmpl.gni - Chromium Code Search
android_chrome_strings.grd - Chromium Code Search
native_theme_gtk.cc - Chromium Code Search
about_version.html - Chromium Code Search @@ -213,7 +214,6 @@
new_tab_page_feed_v2_expandable_header.xml - Chromium Code Search
new_tab_page_multi_feed_header.xml - Chromium Code Search
pref_names.cc - Chromium Code Search -
web_view_impl.cc - Chromium Code Search

Chromium Code Search
overlay-amd64-generic - Chromium Code Search diff --git a/setup.sh b/setup.sh index 3d1a4e3d..69a0cc46 100755 --- a/setup.sh +++ b/setup.sh @@ -92,6 +92,7 @@ esac copyRaspi () { printf "\n" && printf "${YEL}Copying Raspberry Pi build files...${c0}\n" && + cp -r -v arm/media/* ${CR_SRC_DIR}/media/ && cp -r -v arm/raspi/* ${CR_SRC_DIR}/ && rm -v ${CR_SRC_DIR}/out/thorium/pak && cp -v pak_src/binaries/pak_arm64 ${CR_SRC_DIR}/out/thorium/pak && @@ -160,6 +161,7 @@ copyAndroid () { printf "\n" && printf "${YEL}Copying Android (ARM64 and ARM32) build files...${c0}\n" && cp -r -v arm/build/config/* ${CR_SRC_DIR}/build/config/ && + cp -r -v arm/media/* ${CR_SRC_DIR}/media/ && cp -r -v arm/android/* ${CR_SRC_DIR}/ && cp -r -v arm/android/third_party/* ${CR_SRC_DIR}/third_party/ && rm -v -r -f ${CR_SRC_DIR}/chrome/android/java/res_base/drawable-v26/ic_launcher.xml && diff --git a/src/build/config/android/BUILD.gn b/src/build/config/android/BUILD.gn index 1319db46..8e37ef8e 100644 --- a/src/build/config/android/BUILD.gn +++ b/src/build/config/android/BUILD.gn @@ -59,10 +59,6 @@ config("compiler") { } } - # Instead of using an unwind lib from the toolchain, - # buildtools/third_party/libunwind will be built and used directly. - ldflags += [ "--unwindlib=none" ] - # $compile_api_level corresponds to the API level used for the sysroot path # calculation in //build/config/android/config.gni if (android_64bit_target_cpu) { diff --git a/src/chrome/android/BUILD.gn b/src/chrome/android/BUILD.gn index 37b78dac..cf9a9f40 100644 --- a/src/chrome/android/BUILD.gn +++ b/src/chrome/android/BUILD.gn @@ -48,14 +48,14 @@ if (android_64bit_target_cpu && skip_secondary_abi_for_cq) { assert(current_toolchain != android_secondary_abi_toolchain) } -if (current_toolchain == default_toolchain) { - # 32-bit library will have browser code in it. 64-bit is webview-only. - if (android_64bit_target_cpu && !skip_secondary_abi_for_cq) { - _monochrome_browser_toolchain = android_secondary_abi_toolchain - } else { - _monochrome_browser_toolchain = current_toolchain - } +# 32-bit library will have browser code in it. 64-bit is webview-only. +if (android_64bit_target_cpu && !skip_secondary_abi_for_cq) { + _monochrome_browser_toolchain = android_secondary_abi_toolchain +} else { + _monochrome_browser_toolchain = default_toolchain +} +if (current_toolchain == default_toolchain) { app_hooks_impl = "java/src/org/chromium/chrome/browser/AppHooksImpl.java" template("chrome_public_bundle") { @@ -101,7 +101,7 @@ if (current_toolchain == default_toolchain) { forward_variables_from(invoker, [ "add_view_trace_events", - "baseline_profile_path", + "art_profile_path", "bundle_name", "enable_lint", "include_32_bit_webview", @@ -244,8 +244,11 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/partnercustomizations:delegate_public_impl_java", "//chrome/browser/password_manager/android:public_impl_java", "//chrome/browser/policy/android:delegate_public_impl_java", + "//chrome/browser/readaloud/android:hooks_public_impl_java", + "//chrome/browser/readaloud/android:hooks_public_impl_java", "//chrome/browser/supervised_user:parent_auth_delegate_impl_java", "//chrome/browser/touch_to_fill/android/internal:resource_provider_public_impl_java", + "//components/environment_integrity/android:integrity_service_bridge_public_impl_java", "//components/externalauth/android:google_delegate_public_impl_java", "//components/language/android:ulp_delegate_public_java", "//components/signin/public/android:account_email_domain_displayability_java", @@ -277,6 +280,7 @@ if (current_toolchain == default_toolchain) { "//chrome/android/features/start_surface:public_java", "//chrome/android/features/tab_ui:tab_suggestions_java", "//chrome/android/features/tab_ui/public:java", + "//chrome/android/features/tab_ui/public:ui_java_resources", "//chrome/android/modules/cablev2_authenticator/public:java", "//chrome/android/modules/image_editor/provider:java", "//chrome/android/modules/stack_unwinder/provider:java", @@ -301,6 +305,7 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/battery/android:java", "//chrome/browser/bluetooth/android:java", "//chrome/browser/browser_controls/android:java", + "//chrome/browser/browsing_data/android:java", "//chrome/browser/commerce/android:java", "//chrome/browser/commerce/merchant_viewer/android:java", "//chrome/browser/commerce/price_tracking/android:java", @@ -359,11 +364,13 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/privacy_sandbox/android:java", "//chrome/browser/profiles/android:java", "//chrome/browser/quick_delete:java", + "//chrome/browser/readaloud/android:java", "//chrome/browser/recent_tabs:factory_java", "//chrome/browser/recent_tabs:helper_java", "//chrome/browser/recent_tabs:java", "//chrome/browser/safe_browsing/android:java", "//chrome/browser/safety_check/android:java", + "//chrome/browser/screenshot_monitor:java", "//chrome/browser/search_engines/android:java", "//chrome/browser/search_resumption:java", "//chrome/browser/segmentation_platform:factory_java", @@ -387,6 +394,7 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/ui/android/edge_to_edge:java", "//chrome/browser/ui/android/fast_checkout:java", "//chrome/browser/ui/android/favicon:java", + "//chrome/browser/ui/android/hats:java", "//chrome/browser/ui/android/layouts:java", "//chrome/browser/ui/android/layouts/glue:java", "//chrome/browser/ui/android/logo:java", @@ -461,8 +469,10 @@ if (current_toolchain == default_toolchain) { "//components/embedder_support/android:browser_context_java", "//components/embedder_support/android:content_view_java", "//components/embedder_support/android:context_menu_java", + "//components/embedder_support/android:simple_factory_key_java", "//components/embedder_support/android:util_java", "//components/embedder_support/android:web_contents_delegate_java", + "//components/environment_integrity/android:java", "//components/external_intents/android:java", "//components/externalauth/android:java", "//components/favicon/android:java", @@ -590,6 +600,7 @@ if (current_toolchain == default_toolchain) { "//third_party/androidx:androidx_coordinatorlayout_coordinatorlayout_java", "//third_party/androidx:androidx_customview_customview_java", "//third_party/androidx:androidx_gridlayout_gridlayout_java", + "//third_party/androidx:androidx_interpolator_interpolator_java", "//third_party/androidx:androidx_lifecycle_lifecycle_common_java8_java", "//third_party/androidx:androidx_lifecycle_lifecycle_runtime_java", "//third_party/androidx:androidx_localbroadcastmanager_localbroadcastmanager_java", @@ -628,7 +639,6 @@ if (current_toolchain == default_toolchain) { "//chrome/browser:sharing_dialog_type_generated_enum", "//chrome/browser:sharing_send_message_result_generated_enum", "//chrome/browser/notifications/scheduler/public:jni_enums", - "//chrome/browser/ui:duplicate_download_enums_java", "//components/contextual_search/core/browser:quick_action_category_enum_javagen", "//components/dom_distiller/core:distiller_type_java", "//components/ntp_tiles:ntp_tiles_enums_java", @@ -655,14 +665,16 @@ if (current_toolchain == default_toolchain) { # Include sources for start_surface_java_sources.gni sources += start_surface_java_sources - srcjar_deps += [ ":chrome_vr_android_java_enums_srcjar" ] + srcjar_deps += [ + ":chrome_jni_headers", + ":chrome_vr_android_java_enums_srcjar", + ] # Add the actual implementation where necessary so that downstream targets # can provide their own implementations. jar_excluded_patterns = [ "*/AppHooksImpl.class" ] annotation_processor_deps = [ - "//base/android/jni_generator:jni_processor", "//components/module_installer/android:module_interface_processor", "//third_party/android_deps:dagger_processor", ] @@ -762,6 +774,7 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/ui/android/edge_to_edge/internal:java", "//chrome/browser/ui/android/fast_checkout/internal:java", "//chrome/browser/ui/android/webid/internal:java", + "//components/autofill/android:payments_autofill_java", "//components/browser_ui/bottomsheet/android/internal:java", "//components/messages/android/internal:java", "//components/segmentation_platform/internal:internal_java", @@ -831,11 +844,8 @@ if (current_toolchain == default_toolchain) { # Needed by androidx.test.core.app.ActivityScenario android_manifest = "//chrome/android/junit/AndroidManifest.xml" - # This target OOMs with the default 1G, and hits CodeCache errors with - # default 4 shards (crbug.com/1453254). - # TODO(crbug.com/1383650): Remove once test runner shards by SDK. - max_heap_size = "3600M" - extra_args = [ "--shards=7" ] + # TODO(crbug.com/1383650): Remove once memory leak is fixed. + max_heap_size = "1800M" package_name = chrome_public_manifest_package @@ -932,6 +942,7 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/image_editor/public:java", "//chrome/browser/incognito:incognito_junit_tests", "//chrome/browser/incognito:java", + "//chrome/browser/language/android:java", "//chrome/browser/language/android:junit", "//chrome/browser/lens:delegate_public_impl_java", "//chrome/browser/lens:java", @@ -959,11 +970,14 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/profiles/android:junit", "//chrome/browser/quick_delete:java", "//chrome/browser/quick_delete:junit", + "//chrome/browser/readaloud/android:java", + "//chrome/browser/readaloud/android:junit", "//chrome/browser/recent_tabs:java", "//chrome/browser/recent_tabs:junit", "//chrome/browser/recent_tabs/internal:junit", "//chrome/browser/safety_check/android:java", "//chrome/browser/safety_check/android:junit", + "//chrome/browser/screenshot_monitor:java", "//chrome/browser/search_engines/android:java", "//chrome/browser/search_resumption:junit", "//chrome/browser/segmentation_platform:factory_java", @@ -1007,6 +1021,7 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/ui/android/night_mode:junit", "//chrome/browser/ui/android/omnibox:java", "//chrome/browser/ui/android/omnibox:junit", + "//chrome/browser/ui/android/page_insights:junit", "//chrome/browser/ui/android/quickactionsearchwidget:java", "//chrome/browser/ui/android/searchactivityutils:java", "//chrome/browser/ui/android/signin:java", @@ -1030,12 +1045,15 @@ if (current_toolchain == default_toolchain) { "//chrome/test/android:chrome_java_unit_test_support", "//components/autofill/android:autofill_features_java", "//components/autofill/android:main_autofill_java", + "//components/autofill/android:payments_autofill_java", "//components/background_task_scheduler:background_task_scheduler_java", "//components/background_task_scheduler:background_task_scheduler_task_ids_java", "//components/bookmarks/common/android:bookmarks_java", "//components/browser_ui/accessibility/android:java", "//components/browser_ui/accessibility/android:junit", + "//components/browser_ui/bottomsheet/android:factory_java", "//components/browser_ui/bottomsheet/android:java", + "//components/browser_ui/bottomsheet/android:manager_java", "//components/browser_ui/display_cutout/android:java", "//components/browser_ui/media/android:java", "//components/browser_ui/media/android:java_resources", @@ -1083,6 +1101,7 @@ if (current_toolchain == default_toolchain) { "//components/optimization_guide/proto:optimization_guide_proto_java", "//components/page_info/android:java", "//components/page_info/core:proto_java", + "//components/paint_preview/browser/android:java", "//components/paint_preview/player/android:java", "//components/payments/content/android:java", "//components/payments/content/android:service_java", @@ -1139,6 +1158,7 @@ if (current_toolchain == default_toolchain) { "//third_party/androidx:androidx_collection_collection_java", "//third_party/androidx:androidx_lifecycle_lifecycle_runtime_java", "//third_party/androidx:androidx_mediarouter_mediarouter_java", + "//third_party/androidx:androidx_preference_preference_java", "//third_party/androidx:androidx_swiperefreshlayout_swiperefreshlayout_java", "//third_party/androidx:androidx_test_core_java", "//third_party/androidx:androidx_test_ext_junit_java", @@ -1167,14 +1187,6 @@ if (current_toolchain == default_toolchain) { deps += chrome_junit_test_java_deps } - generate_jni("chrome_test_util_jni_headers") { - testonly = true - sources = [ - "javatests/src/org/chromium/chrome/browser/FederatedIdentityTestUtils.java", - "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java", - ] - } - # Files used by chrome integration and unit javatests. android_library("chrome_unit_test_util_java") { testonly = true @@ -1207,11 +1219,20 @@ if (current_toolchain == default_toolchain) { ] } + generate_jni("chrome_test_util_jni") { + testonly = true + sources = [ + "javatests/src/org/chromium/chrome/browser/FederatedIdentityTestUtils.java", + "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java", + ] + } + # Files used for both chrome tests and VR/AR tests android_library("chrome_test_util_java") { testonly = true resources_package = "org.chromium.chrome" + srcjar_deps = [ ":chrome_test_util_jni" ] sources = [ "javatests/src/org/chromium/chrome/browser/FederatedIdentityTestUtils.java", "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java", @@ -1260,8 +1281,6 @@ if (current_toolchain == default_toolchain) { "//ui/android:ui_no_recycler_view_java", "//url:gurl_java", ] - - annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] } android_resources("chrome_unit_test_java_resources") { @@ -1301,13 +1320,13 @@ if (current_toolchain == default_toolchain) { "javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationDialogTest.java", "javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java", "javatests/src/org/chromium/chrome/browser/externalnav/IntentWithRequestMetadataHandlerTest.java", - "javatests/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorTest.java", "javatests/src/org/chromium/chrome/browser/firstrun/FirstRunUtilsTest.java", "javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java", "javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeUnitTest.java", "javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java", "javatests/src/org/chromium/chrome/browser/ntp/TitleUtilTest.java", "javatests/src/org/chromium/chrome/browser/payments/CurrencyFormatterTest.java", + "javatests/src/org/chromium/chrome/browser/screenshot_monitor/ScreenshotMonitorTest.java", "javatests/src/org/chromium/chrome/browser/share/ShareUrlTest.java", "javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java", "javatests/src/org/chromium/chrome/browser/tab/WebContentsStateBridgeTest.java", @@ -1326,11 +1345,13 @@ if (current_toolchain == default_toolchain) { ":chrome_unit_test_util_java", "//base:base_java", "//base:base_java_test_support", + "//base:jni_java", "//chrome/android:base_module_java", "//chrome/android:chrome_java", "//chrome/browser/android/browserservices/intents:java", "//chrome/browser/android/browserservices/verification:java", "//chrome/browser/android/crypto:java", + "//chrome/browser/browser_controls/android:java", "//chrome/browser/commerce/android:java", "//chrome/browser/commerce/subscriptions/android:subscriptions_java", "//chrome/browser/contextmenu:java", @@ -1345,6 +1366,7 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/lens:java", "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", + "//chrome/browser/screenshot_monitor:java", "//chrome/browser/tab:java", "//chrome/browser/tabmodel:java", "//chrome/browser/tabpersistence:java", @@ -1393,6 +1415,8 @@ if (current_toolchain == default_toolchain) { "//net/android:net_java", "//third_party/android_deps:espresso_java", "//third_party/android_deps:guava_android_java", + "//third_party/android_deps:material_design_java", + "//third_party/android_deps:protobuf_lite_runtime_java", "//third_party/android_sdk:android_test_base_java", "//third_party/android_sdk:android_test_mock_java", "//third_party/androidx:androidx_annotation_annotation_java", @@ -1401,6 +1425,7 @@ if (current_toolchain == default_toolchain) { "//third_party/androidx:androidx_test_core_java", "//third_party/androidx:androidx_test_monitor_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_viewpager_viewpager_java", "//third_party/blink/public:blink_headers_java", "//third_party/hamcrest:hamcrest_core_java", "//third_party/hamcrest:hamcrest_library_java", @@ -1484,6 +1509,7 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/back_press/android:java", "//chrome/browser/banners/android:java", "//chrome/browser/browser_controls/android:java", + "//chrome/browser/browsing_data/android:java", "//chrome/browser/commerce/android:java", "//chrome/browser/commerce/android:javatests", "//chrome/browser/commerce/merchant_viewer/android:java", @@ -1549,6 +1575,7 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/safe_browsing/android:javatests", "//chrome/browser/safety_check/android:java", "//chrome/browser/safety_check/android:javatests", + "//chrome/browser/screenshot_monitor:java", "//chrome/browser/search_engines/android:java", "//chrome/browser/selection/android:javatests", "//chrome/browser/settings:java", @@ -1608,6 +1635,7 @@ if (current_toolchain == default_toolchain) { "//components/bookmarks/common/android:bookmarks_java", "//components/browser_ui/accessibility/android:java", "//components/browser_ui/bottomsheet/android:java", + "//components/browser_ui/bottomsheet/android:manager_java", "//components/browser_ui/bottomsheet/android/test:java", "//components/browser_ui/display_cutout/android:java", "//components/browser_ui/media/android:java", @@ -1647,12 +1675,14 @@ if (current_toolchain == default_toolchain) { "//components/embedder_support/android:simple_factory_key_java", "//components/embedder_support/android:util_java", "//components/embedder_support/android:web_contents_delegate_java", + "//components/environment_integrity/android:java", "//components/external_intents/android:java", "//components/external_intents/android:test_support_java", "//components/externalauth/android:java", "//components/favicon/android:java", "//components/feature_engagement:feature_engagement_java", "//components/feed/core/v2:feedv2_core_java", + "//components/find_in_page/android:java", "//components/gcm_driver/android:gcm_driver_java", "//components/gcm_driver/instance_id/android:instance_id_driver_java", "//components/gcm_driver/instance_id/android:instance_id_driver_test_support_java", @@ -1740,7 +1770,9 @@ if (current_toolchain == default_toolchain) { "//services/network/public/mojom:url_loader_base_java", "//services/service_manager/public/java:service_manager_java", "//third_party/android_deps:com_google_code_findbugs_jsr305_java", + "//third_party/android_deps:com_google_guava_listenablefuture_java", "//third_party/android_deps:espresso_java", + "//third_party/android_deps:guava_android_java", "//third_party/android_deps:material_design_java", "//third_party/android_deps:protobuf_lite_runtime_java", "//third_party/android_deps/local_modifications/preconditions/javatests", @@ -1861,9 +1893,11 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/ui/messages/android:java", "//chrome/browser/util:java", "//chrome/test/android:chrome_java_integration_test_support", + "//components/embedder_support/android:content_view_java", "//components/embedder_support/android:util_java", "//components/permissions/android:java", "//components/policy/android:policy_java", + "//components/webxr/android:xr_java", "//content/public/android:content_java", "//content/public/test/android:content_java_test_support", "//net/android:net_java_test_support", @@ -1975,6 +2009,19 @@ if (current_toolchain == default_toolchain) { ] } + if (enable_cardboard) { + sources += [ + "javatests/src/org/chromium/chrome/browser/vr/WebXrVrCardboardDeviceTest.java", + "javatests/src/org/chromium/chrome/browser/vr/WebXrVrCardboardPermissionTest.java", + "javatests/src/org/chromium/chrome/browser/vr/WebXrVrCardboardTabTest.java", + "javatests/src/org/chromium/chrome/browser/vr/WebXrVrCardboardTransitionTest.java", + "javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityVrCardboardTestRule.java", + "javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityVrCardboardTestRule.java", + "javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityVrCardboardTestRule.java", + "javatests/src/org/chromium/chrome/browser/vr/util/VrCardboardTestRuleUtils.java", + ] + } + data = [ "//chrome/android/shared_preference_files/test/", "//third_party/gvr-android-sdk/test-apks/", @@ -2322,6 +2369,7 @@ if (current_toolchain == default_toolchain) { # Test support code that needs access to the browser. android_library("browser_java_test_support") { testonly = true + srcjar_deps = [ ":test_support_jni_headers" ] sources = [ "javatests/src/org/chromium/chrome/browser/ServicificationBackgroundService.java", "javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java", @@ -2351,8 +2399,6 @@ if (current_toolchain == default_toolchain) { "//url:gurl_java", "//url:origin_java", ] - - annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] } static_library("browser_test_support") { @@ -2384,7 +2430,7 @@ if (current_toolchain == default_toolchain) { target_type = "android_apk" apk_name = "Thorium_Public" enable_multidex = is_java_debug - baseline_profile_path = "//chrome/android/baseline_profiles/profile.txt" + art_profile_path = "//chrome/android/baseline_profiles/profile.txt" } chrome_public_bundle("chrome_public_bundle") { @@ -2423,6 +2469,10 @@ if (current_toolchain == default_toolchain) { } } + generate_jni("base_module_jni") { + sources = [ "java/src/org/chromium/chrome/browser/metrics/UmaUtils.java" ] + } + # Target for classes which should be in the base module, even when //chrome code # is in a DFM. android_library("base_module_java") { @@ -2454,7 +2504,6 @@ if (current_toolchain == default_toolchain) { "java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java", "java/src/org/chromium/chrome/browser/crash/ApplicationStatusTracker.java", "java/src/org/chromium/chrome/browser/crash/ChromeMinidumpUploadJobService.java", - "java/src/org/chromium/chrome/browser/crash/FirebaseConfig.java", "java/src/org/chromium/chrome/browser/crash/MinidumpUploadService.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java", "java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java", @@ -2523,7 +2572,10 @@ if (current_toolchain == default_toolchain) { deps += [ "//chrome/android/modules/dev_ui/provider:java" ] } - srcjar_deps = [ ":chrome_product_config" ] + srcjar_deps = [ + ":base_module_jni", + ":chrome_product_config", + ] # If this throws an error, try depending on # //content/public/android:content_main_dex_java instead. @@ -2534,7 +2586,6 @@ if (current_toolchain == default_toolchain) { jar_excluded_patterns = [ "*/ProductConfig.class" ] resources_package = "org.chromium.chrome.base" - annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] } if (android_64bit_target_cpu && skip_secondary_abi_for_cq) { @@ -2649,12 +2700,14 @@ if (current_toolchain == default_toolchain) { "//chrome/browser/signin/services/android:unit_device_javatests", "//chrome/browser/thumbnail/generator:unit_device_javatests", "//chrome/browser/ui/android/appmenu/internal:unit_device_javatests", + "//chrome/browser/ui/android/hats:unit_device_javatests", "//chrome/browser/ui/android/night_mode:unit_device_javatests", "//chrome/browser/ui/android/omnibox:unit_device_javatests", "//chrome/browser/ui/android/page_insights:unit_device_javatests", "//chrome/browser/ui/android/searchactivityutils:unit_device_javatests", "//chrome/browser/ui/android/signin:unit_device_javatests", "//chrome/browser/ui/messages/android:unit_device_javatests", + "//components/browser_ui/accessibility/android:unit_device_javatests", "//components/browser_ui/bottomsheet/android/internal:unit_device_javatests", "//components/browser_ui/contacts_picker/android:unit_device_javatests", "//components/browser_ui/modaldialog/android:unit_device_javatests", @@ -2761,7 +2814,7 @@ if (current_toolchain == default_toolchain) { if (enable_arcore) { # In order to run this test, first run: - # DOWNLOAD_VR_TEST_APKS=1 third_party/arcore-android-sdk/test-apks/update.py + # DOWNLOAD_XR_TEST_APKS=1 third_party/arcore-android-sdk/test-apks/update.py # See also: //chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md chrome_public_test_apk_tmpl("monochrome_public_test_ar_apk") { apk_name = "MonochromePublicTestAr" @@ -2865,6 +2918,7 @@ if (current_toolchain == default_toolchain) { "//third_party/androidx:androidx_test_core_java", "//third_party/androidx:androidx_test_monitor_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/junit", ] } @@ -3069,7 +3123,7 @@ if (current_toolchain == default_toolchain) { bundle_name = "TrichromeChrome" static_library_provider = ":trichrome_library_apk" add_view_trace_events = true - baseline_profile_path = "//chrome/android/baseline_profiles/profile.txt" + art_profile_path = "//chrome/android/baseline_profiles/profile.txt" if (android_64bit_target_cpu) { is_64_bit_browser = false include_64_bit_webview = true @@ -3240,8 +3294,16 @@ if (current_toolchain == default_toolchain) { generate_jni("chrome_jni_headers") { sources = [ - # Files under a feature's public/ dir are included in chrome_java's source - # files, so include these files in chrome_jni_headers. + "../browser/share/android/java/src/org/chromium/chrome/browser/share/BitmapDownloadRequest.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextBridge.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsTabService.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsTabServiceFactory.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QRCodeGenerationRequest.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/EditorScreenshotTask.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/MetricsRecorder.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationManager.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridge.java", + "../browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/TargetDeviceInfo.java", "java/src/org/chromium/chrome/browser/ApplicationLifetime.java", "java/src/org/chromium/chrome/browser/ChromeBackupAgentImpl.java", "java/src/org/chromium/chrome/browser/ChromeBackupWatcher.java", @@ -3262,6 +3324,7 @@ generate_jni("chrome_jni_headers") { "java/src/org/chromium/chrome/browser/autofill/AutofillLogger.java", "java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridge.java", "java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java", + "java/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridge.java", "java/src/org/chromium/chrome/browser/autofill/AutofillSnackbarController.java", "java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java", "java/src/org/chromium/chrome/browser/autofill/CreditCardScannerBridge.java", @@ -3342,7 +3405,6 @@ generate_jni("chrome_jni_headers") { "java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java", "java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java", "java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java", - "java/src/org/chromium/chrome/browser/javascript/WebContextFetcher.java", "java/src/org/chromium/chrome/browser/lens/LensDebugBridge.java", "java/src/org/chromium/chrome/browser/lens/LensPolicyUtils.java", "java/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandler.java", @@ -3351,7 +3413,6 @@ generate_jni("chrome_jni_headers") { "java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterClient.java", "java/src/org/chromium/chrome/browser/metrics/LaunchMetrics.java", "java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java", - "java/src/org/chromium/chrome/browser/metrics/UmaUtils.java", "java/src/org/chromium/chrome/browser/metrics/VariationsSession.java", "java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java", "java/src/org/chromium/chrome/browser/navigation_predictor/NavigationPredictorBridge.java", @@ -3385,6 +3446,7 @@ generate_jni("chrome_jni_headers") { "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerLauncher.java", "java/src/org/chromium/chrome/browser/password_manager/PasswordMigrationWarningBridge.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordUIView.java", + "java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java", "java/src/org/chromium/chrome/browser/permissions/NotificationBlockedDialog.java", "java/src/org/chromium/chrome/browser/permissions/PermissionSettingsBridge.java", "java/src/org/chromium/chrome/browser/permissions/PermissionUpdateRequester.java", @@ -3415,7 +3477,6 @@ generate_jni("chrome_jni_headers") { "java/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorSceneLayer.java", "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSites.java", "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java", - "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java", "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountService.java", "java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java", "java/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelper.java", @@ -3439,20 +3500,26 @@ generate_jni("chrome_jni_headers") { "java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java", ] + if (enable_vr) { + sources += [ "features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java" ] + } + # Used for testing only, should not be shipped to end users. if (enable_offline_pages_harness) { sources += [ "java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java" ] } + + public_deps = [ ":base_module_jni" ] } -source_set("chrome_test_util_jni") { +source_set("chrome_test_util") { testonly = true sources = [ "javatests/src/custom_tabs_test_utils.cc", "javatests/src/federated_identity_test_utils.cc", ] deps = [ - ":chrome_test_util_jni_headers", + ":chrome_test_util_jni", "//base", "//chrome/browser", "//chrome/browser/profiles:profile", @@ -3497,8 +3564,10 @@ group("jni_headers") { "//chrome/browser/touch_to_fill/payments/android:jni_headers", "//chrome/browser/ui/android/fast_checkout:jni_headers", "//chrome/browser/ui/android/favicon:jni_headers", + "//chrome/browser/ui/android/hats:jni_headers", "//chrome/browser/ui/android/logo:jni_headers", "//chrome/browser/ui/android/omnibox:jni_headers", + "//chrome/browser/ui/android/page_insights:jni_headers", "//chrome/browser/ui/android/toolbar:jni_headers", "//chrome/browser/ui/android/webid:jni_headers", "//chrome/browser/ui/messages/android:jni_headers", @@ -3555,7 +3624,7 @@ chrome_common_shared_library("libchromefortest") { sources = [ "../browser/android/chrome_entry_point_for_test.cc" ] deps = [ ":browser_test_support", - ":chrome_test_util_jni", + ":chrome_test_util", "//base/test:test_support", "//chrome:chrome_android_core", "//chrome/browser/android/metrics:ukm_utils_for_test", @@ -3631,37 +3700,38 @@ template("libmonochrome_apk_or_bundle_tmpl") { } } -if (!android_64bit_target_cpu || - (!skip_secondary_abi_for_cq && - current_toolchain == android_secondary_abi_toolchain)) { +libmonochrome_apk_or_bundle_tmpl("libmonochrome") { + enable_target = current_toolchain == _monochrome_browser_toolchain + define_unwind_table_target = + add_unwind_tables_in_chrome_32bit_apk && current_cpu == "arm" + if (enable_resource_allowlist_generation) { + # Make sure allowlist_inputs is built first so when concurrent_links == 1 + # it comes before the actual (very slow) link step. + deps = [ ":libmonochrome_inputs($_monochrome_browser_toolchain)" ] + } +} + +if (current_toolchain == _monochrome_browser_toolchain) { # Avoiding a real link for this step allows the actual libmonochrome to # run at the same time as R8. libmonochrome_apk_or_bundle_tmpl("libmonochrome_inputs") { collect_inputs_only = true } - libmonochrome_apk_or_bundle_tmpl("libmonochrome") { - define_unwind_table_target = - add_unwind_tables_in_chrome_32bit_apk && current_cpu == "arm" - if (enable_resource_allowlist_generation) { - # Make sure allowlist_inputs is built first so when concurrent_links == 1 - # it comes before the actual (very slow) link step. - deps = [ ":libmonochrome_inputs" ] - } - } - if (android_64bit_target_cpu && !skip_secondary_abi_for_cq) { group("monochrome_64_secondary_abi_lib") { public_deps = [ ":libmonochrome_64($android_secondary_abi_toolchain)" ] } } -} else { +} + +if (android_64bit_target_cpu) { # 64-bit browser library targets (APK and bundle). libmonochrome_apk_or_bundle_tmpl("libmonochrome_64") { } # 32-bit browser library alias targets, pulled in by 64-bit WebView builds. - if (android_64bit_target_cpu && !skip_secondary_abi_for_cq) { + if (!skip_secondary_abi_for_cq) { group("monochrome_secondary_abi_lib") { public_deps = [ ":libmonochrome($android_secondary_abi_toolchain)" ] } diff --git a/src/chrome/android/chrome_public_apk_tmpl.gni b/src/chrome/android/chrome_public_apk_tmpl.gni index a9ea421e..a52f0955 100644 --- a/src/chrome/android/chrome_public_apk_tmpl.gni +++ b/src/chrome/android/chrome_public_apk_tmpl.gni @@ -42,6 +42,7 @@ default_chrome_public_jinja_variables = [ "channel=$android_channel", "enable_cardboard=$enable_cardboard", "enable_vr=$enable_vr", + "enable_openxr=$enable_openxr", "enable_arcore=$enable_arcore", "zygote_preload_class=org.chromium.content_public.app.ZygotePreload", ] @@ -303,10 +304,6 @@ template("chrome_common_apk_or_module_tmpl") { custom_assertion_handler = crash_reporting_assertion_handler } - if (allow_jni_multiplexing) { - enable_jni_multiplexing = true - } - # Include resource strings files only for supported locales. aapt_locale_allowlist = platform_pak_locales @@ -372,7 +369,7 @@ template("chrome_common_apk_or_module_tmpl") { # Resources config for blocklisting resource names from obfuscation resources_config_paths = [ "//chrome/android/aapt2.config" ] - if (_is_monochrome || _is_trichrome) { + if (_is_monochrome) { resources_config_paths += [ "//android_webview/aapt2.config" ] } if (defined(invoker.resources_config_paths)) { @@ -481,6 +478,10 @@ template("chrome_common_apk_or_module_tmpl") { # are needed by the base module. "//components/language/android:ulp_delegate_public_java", ] + if (_is_monochrome) { + # WebView needs this in the base module. + deps += [ "//components/environment_integrity/android:integrity_service_bridge_public_impl_java" ] + } } else { deps += [ "//chrome/android:chrome_all_java", @@ -572,7 +573,7 @@ template("chrome_common_apk_or_module_tmpl") { } } } else { - srcjar_deps = [ "//chrome/android:libmonochrome__jni_registration($android_secondary_abi_toolchain)" ] + srcjar_deps = [ "//chrome/android:libmonochrome__jni_registration($default_toolchain)" ] if (_is_monochrome) { if (_include_64_bit_webview) { shared_libraries += [ "//android_webview:monochrome" ] @@ -701,10 +702,10 @@ template("chrome_common_apk_or_module_tmpl") { # depend on their respective versions of the shared library APK even # though they're functionally the same. if (_include_primary_abi && loadable_modules == []) { - native_lib_placeholders = [ "libdummy.so" ] + native_lib_placeholders = [ "libplaceholder.so" ] } if (_include_secondary_abi && secondary_abi_loadable_modules == []) { - secondary_native_lib_placeholders = [ "libdummy.so" ] + secondary_native_lib_placeholders = [ "libplaceholder.so" ] } # http://crbug.com/1042107. diff --git a/src/chrome/browser/ui/android/strings/android_chrome_strings.grd b/src/chrome/browser/ui/android/strings/android_chrome_strings.grd index ac887825..8f2806d6 100644 --- a/src/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/src/chrome/browser/ui/android/strings/android_chrome_strings.grd @@ -204,6 +204,11 @@ CHAR_LIMIT guidelines: + + + Site not working? Third-party cookies are blocked + + Basics @@ -521,12 +526,6 @@ CHAR_LIMIT guidelines: Copied to Thorium - - Verify your card - - - Your bank wants to confirm it\u2019s you. - Not seeing your current info? Please contact your bank to update it. @@ -557,6 +556,10 @@ CHAR_LIMIT guidelines: Turn off + + + Autofill Options + + Passwords - - Password Manager <new>New</new> + + Password Manager Save passwords @@ -600,6 +603,12 @@ CHAR_LIMIT guidelines: Warn you if passwords are exposed in a data breach + + Warn you if a password was compromised in a data breach + + + When you use a password, Thorium warns you if it has been published online. When doing this, your passwords and usernames are encrypted, so they can’t be read by anyone, including Google. + Check passwords @@ -739,7 +748,7 @@ CHAR_LIMIT guidelines: We’re changing how passwords are saved on this device - Your lists of saved passwords for Thorium and Thorium %1$sDev will merge after version 121. You’ll be able to autofill all your saved passwords on both apps. + Right now, passwords saved on this device cannot be used across Thorium channels. After Thorium 121, passwords saved on your device for Thorium and %1$sThorium Dev will be merged and can be used in both apps. Got it @@ -763,7 +772,7 @@ CHAR_LIMIT guidelines: Export & delete passwords saved to this device - All passwords will be downloaded on your device and removed from Thorium %1$sDev + All passwords will be downloaded on your device and removed from %1$sThorium Dev Next @@ -774,12 +783,27 @@ CHAR_LIMIT guidelines: Delete passwords from Google Password Manager? + + Deleting + + + Exporting + - Your passwords will be deleted from Google Password Manager for Thorium %1$sDev. You will keep the passwords file you just downloaded. + Your passwords will be deleted from Google Password Manager for %1$sThorium Dev. You will keep the passwords file you just downloaded. Delete passwords + + Thorium Canary + + + Thorium Dev + + + Thorium Beta + @@ -1197,10 +1221,10 @@ Private state tokens improve privacy on the web and can’t be used to find out You can block sites you don’t want. Thorium also auto-deletes sites from the list that are older than 30 days. <link>Learn more</link> - When on, a list of sites you visit that guess your interests appears here. + When on, a list of sites you visit that guess your interests appears here - It can take up to a week for a list of sites to appear here based on your browsing history. + No sites to show right now See all sites @@ -1348,16 +1372,16 @@ Your Google account may have other forms of browsing history like searches and a Cookies and site data - Signs you out of most sites. + Signs you out of most sites Signs you out of most sites. You won't be signed out of your Google Account. - Clears history, including in the search box. + Clears history, including in the search box - Clears history from all synced devices. + Clears history from all synced devices <link1>Search history</link1> and <link2>other forms of activity</link2> may be saved in your Google Account when you’re signed in. You can delete them anytime. @@ -1392,6 +1416,9 @@ Your Google account may have other forms of browsing history like searches and a Time range + + Last 15 minutes + Last hour @@ -1700,6 +1727,9 @@ Your Google account may have other forms of browsing history like searches and a Standard protection against websites, downloads, and extensions that are known to be dangerous. + + Protects against sites, downloads, and extensions that are known to be dangerous. If a page does something suspicious, URLs and bits of page content are sent to Google Safe Browsing. + No protection (not recommended) @@ -1731,6 +1761,9 @@ Your Google account may have other forms of browsing history like searches and a Standard protection: + + Standard protection + Detects and warns you about dangerous events when they happen. @@ -1740,6 +1773,9 @@ Your Google account may have other forms of browsing history like searches and a Help improve security on the web + + Help improve security on the web for everyone + Sends URLs of some pages you visit, limited system information, and some page content to Google, to help discover new threats and protect everyone on the web. @@ -1795,9 +1831,6 @@ Your Google account may have other forms of browsing history like searches and a Offer to translate - - What languages do you read? - Pick Thorium’s language @@ -2149,7 +2182,12 @@ Your Google account may have other forms of browsing history like searches and a Tabs that you've opened in Thorium on your other devices will appear here. - + + You’ll find your recent tabs here + + + To see your tabs from wherever you use Thorium, sign in on all your devices + Search and browse @@ -2431,6 +2469,10 @@ To change this setting, <resetlink>reset sync

+ + Listen to this page + + Print… @@ -3000,10 +3042,10 @@ To change this setting, <resetlink>reset sync

- %1$sGoogle Maps will open in Thorium. By continuing, you agree to the <LINK1>Google Terms of Service</LINK1>, and the <LINK2>Thorium and ThoriumOS Additional Terms of Service</LINK2>. + %1$sGoogle Maps will open in Thorium. By continuing, you agree to the <LINK1>Google Terms of Service</LINK1>, and the <LINK2>Google Thorium and ThoriumOS Additional Terms of Service</LINK2>. - %1$sGoogle Maps will open in Thorium. By continuing, you agree to the <LINK1>Google Terms of Service</LINK1>, and the <LINK2>Thorium and ThoriumOS Additional Terms of Service</LINK2>. The <LINK3>Privacy Policy</LINK3> also applies. + %1$sGoogle Maps will open in Thorium. By continuing, you agree to the <LINK1>Google Terms of Service</LINK1>, and the <LINK2>Google Thorium and ThoriumOS Additional Terms of Service</LINK2>. The <LINK3>Privacy Policy</LINK3> also applies. Accept & continue @@ -3081,16 +3123,16 @@ To change this setting, <resetlink>reset sync

- To sync your info and keep your data secure in the car, you must create a profile lock. You’ll use a code or password every time you enter the car. + To sync your Thorium info and keep your data secure in the car, you must create a profile lock. You’ll use a code or password every time you enter the car. - To sync your info and keep your data secure in the car, you must create a profile lock in your security settings. You’ll use a code or password every time you enter the car. + To sync your Thorium info and keep your data secure in the car, you must create a profile lock in your security settings. You’ll use a code or password every time you enter the car. Your profile lock keeps your info secure in the car, including synced passwords, payments and more. - Your saved info will be erased if you remove profile lock later. + Your saved data will be erased if the profile lock is removed later. Create a profile lock @@ -3145,6 +3187,12 @@ To change this setting, <resetlink>reset sync

Choose an account + + Choose an account. Currently selected %1$sjohn.doe@example.com. + + + Choose an account. + Sign in to Thorium @@ -3541,6 +3589,9 @@ To change this setting, <resetlink>reset sync

Translate + + Listen to this page + Based on your usage @@ -3565,10 +3616,13 @@ To change this setting, <resetlink>reset sync

Quickly translate this page. To edit this shortcut, touch and hold. + + Listen to this page. To edit this shortcut, touch and hold. + Quickly open a new tab. To edit this shortcut, go to Settings. - + Quickly share this page. To edit this shortcut, go to Settings. @@ -3633,8 +3687,8 @@ To change this setting, <resetlink>reset sync

History - - Delete last 15 minutes + + Clear browsing data Downloads @@ -3887,6 +3941,9 @@ To change this setting, <resetlink>reset sync

Sort by oldest + + Sort by last opened + Sort by A to Z @@ -3902,6 +3959,15 @@ To change this setting, <resetlink>reset sync

Create new folder + + Move to\u2026 + + + Move here + + + Cancel + @@ -4048,9 +4114,6 @@ To change this setting, <resetlink>reset sync

You can request the mobile site for %1$swww.example.com - - Switch to desktop site for a better view of this site - @@ -4079,6 +4142,12 @@ To change this setting, <resetlink>reset sync

+ + You’ll find your tabs here + + + Open tabs to visit different pages at the same time + Switch or close tabs @@ -4086,13 +4155,13 @@ To change this setting, <resetlink>reset sync

- Signed in as %1$sPeter Parker. %2$speter.parker@gmail.com. Button. Opens settings. + Signed in as %1$sPeter Parker. %2$speter.parker@gmail.com. Opens settings. - Signed in as %sBruce Wayne. Button. Opens settings. + Signed in as %sBruce Wayne. Opens settings. - Signed out. Button. Opens dialog to sign in and turn on sync. + Signed out. Opens dialog to sign in and turn on sync. Home @@ -4334,6 +4403,9 @@ To change this setting, <resetlink>reset sync

Page insights bottom sheet is closed + + Related Insights + @@ -4558,7 +4630,7 @@ To change this setting, <resetlink>reset sync

- Thorium feature shortcuts + Google Thorium feature shortcuts Webpage shortcuts @@ -5012,7 +5084,7 @@ To change this setting, <resetlink>reset sync

- Thorium as a Security Key + Google Thorium as a Security Key <resetlink>reset sync

- Use Lite mode on Thorium + Use Lite mode on Google Thorium - Alex313031 recommends Thorium + Google recommends Thorium Save up to 60% data, read today's news @@ -5581,6 +5653,12 @@ To change this setting, <resetlink>reset sync

Sign in bottom sheet is closed. + + You can use your %1$sidp.com account on this site. To continue, sign in to %1$sidp.com. + + + Continue + Signing you in… @@ -5698,24 +5776,6 @@ To change this setting, <resetlink>reset sync

Price drop spotted - - - - Resume your last task? - - - Easily continue where you left off - - - Restore - - - Task resumed - - - Undo - - Bottom sheet @@ -5728,24 +5788,65 @@ To change this setting, <resetlink>reset sync

- - Delete last 15 minutes? + + Clear browsing data - - History from the last 15 minutes will be deleted: - - + {NUM_TABS, plural, =1 {1 tab on this device} other {# tabs on this device}} + + No tabs on this device + + + No tabs from the %1$slast 15 minutes + + + {DOMAIN_COUNT, plural, + =1 {+ 1 site} + other {+ # sites}} + + + No sites + + + No sites from the %1$slast 15 minutes + + + More on synced devices + Cookies, cache, and other site data - + <link1>Search history</link1> and <link2>other forms of activity</link2> may be saved in your Google Account - + + More options + + + Calculating... + + + %1$sLast 15 minutes deleted + + Deleted + + last 15 minutes + + + last hour + + + last 24 hours + + + last 7 days + + + last 4 weeks + @@ -5769,6 +5870,9 @@ To change this setting, <resetlink>reset sync

Create my own + + Please wait… + diff --git a/src/chrome/browser/ui/startup/bad_flags_prompt.cc b/src/chrome/browser/ui/startup/bad_flags_prompt.cc index c5582a55..ead60456 100644 --- a/src/chrome/browser/ui/startup/bad_flags_prompt.cc +++ b/src/chrome/browser/ui/startup/bad_flags_prompt.cc @@ -15,6 +15,7 @@ #include "base/trace_event/memory_dump_manager.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "cc/base/switches.h" #include "chrome/browser/infobars/simple_alert_infobar_creator.h" #include "chrome/browser/ui/simple_message_box.h" #include "chrome/browser/webauthn/webauthn_switches.h" @@ -163,6 +164,11 @@ static const char* kBadFlags[] = { // This flag disables protection against potentially unintentional user // interaction with certain UI elements. views::switches::kDisableInputEventActivationProtectionForTesting, + + // This flag enables injecting synthetic input. It is meant to be used only + // in tests and performance benchmarks. Using it could allow faking user + // interaction across origins. + cc::switches::kEnableGpuBenchmarking, }; #endif // !BUILDFLAG(IS_ANDROID) @@ -239,7 +245,7 @@ void MaybeShowInvalidUserDataDirWarningDialog() { if (user_data_dir.empty()) return; - startup_metric_utils::SetNonBrowserUIDisplayed(); + startup_metric_utils::GetBrowser().SetNonBrowserUIDisplayed(); // Ensure there is an instance of ResourceBundle that is initialized for // localized string resource accesses. diff --git a/src/chrome/browser/ui/views/frame/browser_root_view.h b/src/chrome/browser/ui/views/frame/browser_root_view.h index f4a55dc6..93876f69 100644 --- a/src/chrome/browser/ui/views/frame/browser_root_view.h +++ b/src/chrome/browser/ui/views/frame/browser_root_view.h @@ -138,7 +138,7 @@ class BrowserRootView : public views::internal::RootView { std::unique_ptr drag_image_layer_owner); // The BrowserView. - raw_ptr browser_view_ = nullptr; + raw_ptr browser_view_ = nullptr; // Used to calculate partial offsets in scrolls that occur for a smooth // scroll device. diff --git a/src/chrome/browser/ui/views/tabs/tab.cc b/src/chrome/browser/ui/views/tabs/tab.cc index 08ecc711..fb30da16 100644 --- a/src/chrome/browser/ui/views/tabs/tab.cc +++ b/src/chrome/browser/ui/views/tabs/tab.cc @@ -138,7 +138,7 @@ class TabStyleHighlightPathGenerator : public views::HighlightPathGenerator { } private: - const raw_ptr tab_style_views_; + const raw_ptr tab_style_views_; }; } // namespace @@ -222,6 +222,12 @@ Tab::Tab(TabSlotController* controller) // need a manual suppression by detecting cases where the text is painted onto // onto opaque parts of a not-entirely-opaque layer. title_->SetSkipSubpixelRenderingOpacityCheck(true); + + if (features::IsChromeRefresh2023()) { + title_->SetTextContext(views::style::CONTEXT_LABEL); + title_->SetTextStyle(views::style::STYLE_BODY_4_EMPHASIS); + } + AddChildView(title_.get()); SetEventTargeter(std::make_unique(this)); @@ -327,31 +333,34 @@ void Tab::Layout() { int close_x = contents_rect.right(); if (showing_close_button_) { - // If the ratio of the close button size to tab width exceeds the maximum. - // The close button should be as large as possible so that there is a larger - // hit-target for touch events. So the close button bounds extends to the - // edges of the tab. However, the larger hit-target should be active only - // for touch events, and the close-image should show up in the right place. - // So a border is added to the button with necessary padding. The close - // button (Tab::TabCloseButton) makes sure the padding is a hit-target only - // for touch events. - // TODO(pkasting): The padding should maybe be removed, see comments in - // TabCloseButton::TargetForRect(). - const int close_button_size = GetLayoutConstant(TAB_CLOSE_BUTTON_SIZE); + // The visible size is the button's hover shape size. The actual size + // includes the border insets for the button. + const int close_button_visible_size = + GetLayoutConstant(TAB_CLOSE_BUTTON_SIZE); + const gfx::Size close_button_actual_size = + close_button_->GetPreferredSize(); + + // The close button is vertically centered in the contents_rect. const int top = - contents_rect.y() + Center(contents_rect.height(), close_button_size); - // Clamp the close button position to "centered within the tab"; this should - // only have an effect when animating in a new active tab, which might start - // out narrower than the minimum active tab width. - close_x = std::max(contents_rect.right() - close_button_size, - Center(width(), close_button_size)); - const int left = std::min(after_title_padding, close_x); - const int bottom = height() - close_button_size - top; - const int right = std::max(0, width() - (close_x + close_button_size)); - close_button_->SetButtonPadding( - gfx::Insets::TLBR(top, left, bottom, right)); + contents_rect.y() + + Center(contents_rect.height(), close_button_actual_size.height()); + + // The visible part of the close button should be placed against the + // right of the contents rect unless the tab is so small that it would + // overflow the left side of the contents_rect, in that case it will be + // placed in the middle of the tab. + const int visible_left = + std::max(close_x - close_button_visible_size, + Center(width(), close_button_visible_size)); + + // Offset the new bounds rect by the extra padding in the close button. + const int non_visible_left_padding = + (close_button_actual_size.width() - close_button_visible_size) / 2; + close_button_->SetBoundsRect( - {gfx::Point(close_x - left, 0), close_button_->GetPreferredSize()}); + {gfx::Point(visible_left - non_visible_left_padding, top), + close_button_actual_size}); + close_x = visible_left - after_title_padding; } close_button_->SetVisible(showing_close_button_); @@ -799,22 +808,23 @@ ui::ColorId Tab::GetAlertIndicatorColor(TabAlertState state) const { group = 2; break; } - ui::ColorId color_ids[3][2][2] = { - {{kColorTabAlertMediaRecordingInactiveFrameInactive, - kColorTabAlertMediaRecordingInactiveFrameActive}, - {kColorTabAlertMediaRecordingActiveFrameInactive, - kColorTabAlertMediaRecordingActiveFrameActive}}, - {{kColorTabAlertPipPlayingInactiveFrameInactive, - kColorTabAlertPipPlayingInactiveFrameActive}, - {kColorTabAlertPipPlayingActiveFrameInactive, - kColorTabAlertPipPlayingActiveFrameActive}}, - {{kColorTabAlertAudioPlayingInactiveFrameInactive, - kColorTabAlertAudioPlayingInactiveFrameActive}, - {kColorTabAlertAudioPlayingActiveFrameInactive, - kColorTabAlertAudioPlayingActiveFrameActive}}}; - return color_ids[group][tab_style_views()->GetApparentActiveState() == - TabActive::kActive] - [GetWidget()->ShouldPaintAsActive()]; + + const ui::ColorId color_ids[3][2][2] = { + {{kColorTabAlertMediaRecordingInactiveFrameInactive, + kColorTabAlertMediaRecordingInactiveFrameActive}, + {kColorTabAlertMediaRecordingActiveFrameInactive, + kColorTabAlertMediaRecordingActiveFrameActive}}, + {{kColorTabAlertPipPlayingInactiveFrameInactive, + kColorTabAlertPipPlayingInactiveFrameActive}, + {kColorTabAlertPipPlayingActiveFrameInactive, + kColorTabAlertPipPlayingActiveFrameActive}}, + {{kColorTabAlertAudioPlayingInactiveFrameInactive, + kColorTabAlertAudioPlayingInactiveFrameActive}, + {kColorTabAlertAudioPlayingActiveFrameInactive, + kColorTabAlertAudioPlayingActiveFrameActive}}}; + return color_ids[group][tab_style_views()->GetApparentActiveState() == + TabActive::kActive] + [GetWidget()->ShouldPaintAsActive()]; } bool Tab::IsActive() const { @@ -1007,10 +1017,8 @@ void Tab::UpdateIconVisibility() { alert_indicator_button_->GetPreferredSize().width(); // In case of touch optimized UI, the close button has an extra padding on the // left that needs to be considered. - const int close_button_width = - close_button_->GetPreferredSize().width() - - (touch_ui ? close_button_->GetInsets().right() - : close_button_->GetInsets().width()); + const int close_button_width = GetLayoutConstant(TAB_CLOSE_BUTTON_SIZE) + + GetLayoutConstant(TAB_AFTER_TITLE_PADDING); const bool large_enough_for_close_button = available_width >= (touch_ui ? kTouchMinimumContentsWidthForCloseButtons : kMinimumContentsWidthForCloseButtons); @@ -1100,7 +1108,7 @@ int Tab::GetWidthOfLargestSelectableRegion() const { } void Tab::UpdateForegroundColors() { - TabStyle::TabColors colors = tab_style_views()->CalculateColors(); + TabStyle::TabColors colors = tab_style_views()->CalculateTargetColors(); title_->SetEnabledColor(colors.foreground_color); close_button_->SetColors(colors); alert_indicator_button_->OnParentTabButtonColorChanged(); diff --git a/src/chrome/browser/ui/views/tabs/tab_strip.cc b/src/chrome/browser/ui/views/tabs/tab_strip.cc index 057dc81d..7df2a7fb 100644 --- a/src/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/src/chrome/browser/ui/views/tabs/tab_strip.cc @@ -311,7 +311,8 @@ class TabStrip::TabDragContextImpl : public TabDragContext, std::move(drag_controller_set_callback_).Run(drag_controller_.get()); } - Liveness ContinueDrag(views::View* view, const ui::LocatedEvent& event) { + [[nodiscard]] Liveness ContinueDrag(views::View* view, + const ui::LocatedEvent& event) { if (!drag_controller_.get() || drag_controller_->event_source() != EventSourceFromEvent(event)) { return Liveness::kAlive; @@ -503,7 +504,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext, int x = 0; for (const TabSlotView* view : views) { const int width = view->width(); - bounds.emplace_back(x, 0, width, view->height()); + bounds.emplace_back(x, height() - view->height(), width, view->height()); x += width - overlap; } @@ -1184,8 +1185,9 @@ bool TabStrip::ShouldDrawStrokes() const { // against the active frame color, to avoid toggling the stroke on and off as // the window activation state changes. constexpr float kMinimumContrastRatioForOutlines = 1.3f; - const SkColor background_color = GetTabBackgroundColor( - TabActive::kActive, BrowserFrameActiveState::kActive); + const SkColor background_color = TabStyle::Get()->GetTabBackgroundColor( + TabStyle::TabSelectionState::kActive, /*hovered=*/false, + /*frame_active=*/true, *GetColorProvider()); const SkColor frame_color = controller_->GetFrameColor(BrowserFrameActiveState::kActive); const float contrast_ratio = @@ -1708,27 +1710,6 @@ SkColor TabStrip::GetTabSeparatorColor() const { return separator_color_; } -SkColor TabStrip::GetTabBackgroundColor( - TabActive active, - BrowserFrameActiveState active_state) const { - const auto* cp = GetColorProvider(); - if (!cp) - return gfx::kPlaceholderColor; - - constexpr ChromeColorIds kColorIds[2][2] = { - {kColorTabBackgroundInactiveFrameInactive, - kColorTabBackgroundInactiveFrameActive}, - {kColorTabBackgroundActiveFrameInactive, - kColorTabBackgroundActiveFrameActive}}; - - using State = BrowserFrameActiveState; - const bool tab_active = active == TabActive::kActive; - const bool frame_active = (active_state == State::kActive) || - ((active_state == State::kUseCurrent) && - GetWidget()->ShouldPaintAsActive()); - return cp->GetColor(kColorIds[tab_active][frame_active]); -} - SkColor TabStrip::GetTabForegroundColor(TabActive active) const { const ui::ColorProvider* cp = GetColorProvider(); if (!cp) @@ -1847,7 +1828,7 @@ void TabStrip::Layout() { tab_container_->GetAvailableWidthForTabContainer(); // Be as wide as possible subject to the above constraints. const int width = std::min(max_width, std::max(min_width, available_width)); - SetBounds(0, 0, width, GetLayoutConstant(TAB_HEIGHT)); + SetBounds(0, 0, width, GetLayoutConstant(TAB_STRIP_HEIGHT)); } if (tab_container_->bounds() != GetLocalBounds()) { @@ -1997,15 +1978,18 @@ void TabStrip::UpdateContrastRatioValues() { if (!controller_) return; - const SkColor inactive_bg = GetTabBackgroundColor( - TabActive::kInactive, BrowserFrameActiveState::kUseCurrent); + const SkColor inactive_bg = TabStyle::Get()->GetTabBackgroundColor( + TabStyle::TabSelectionState::kInactive, + /*hovered=*/false, GetWidget()->ShouldPaintAsActive(), + *GetColorProvider()); const auto get_blend = [inactive_bg](SkColor target, float contrast) { return color_utils::BlendForMinContrast(inactive_bg, inactive_bg, target, contrast); }; - const SkColor active_bg = GetTabBackgroundColor( - TabActive::kActive, BrowserFrameActiveState::kUseCurrent); + const SkColor active_bg = TabStyle::Get()->GetTabBackgroundColor( + TabStyle::TabSelectionState::kActive, /*hovered=*/false, + GetWidget()->ShouldPaintAsActive(), *GetColorProvider()); const auto get_hover_opacity = [active_bg, &get_blend](float contrast) { return get_blend(active_bg, contrast).alpha / 255.0f; }; diff --git a/src/chrome/browser/ui/views/tabs/tab_style_views.cc b/src/chrome/browser/ui/views/tabs/tab_style_views.cc index 86439c6b..5cbb2c8a 100644 --- a/src/chrome/browser/ui/views/tabs/tab_style_views.cc +++ b/src/chrome/browser/ui/views/tabs/tab_style_views.cc @@ -34,6 +34,7 @@ #include "ui/base/theme_provider.h" #include "ui/base/ui_base_features.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/favicon_size.h" #include "ui/gfx/font_list.h" #include "ui/gfx/geometry/skia_conversions.h" #include "ui/gfx/scoped_canvas.h" @@ -80,9 +81,10 @@ class GM2TabStyleViews : public TabStyleViews { TabStyle::RenderUnits::kPixels) const override; gfx::Insets GetContentsInsets() const override; float GetZValue() const override; - float GetActiveOpacity() const override; + float GetTargetActiveOpacity() const override; + float GetCurrentActiveOpacity() const override; TabActive GetApparentActiveState() const override; - TabStyle::TabColors CalculateColors() const override; + TabStyle::TabColors CalculateTargetColors() const override; const gfx::FontList& GetFontList() const override; void PaintTab(gfx::Canvas* canvas) const override; void SetHoverLocation(const gfx::Point& location) override; @@ -93,7 +95,12 @@ class GM2TabStyleViews : public TabStyleViews { virtual SkColor GetTabSeparatorColor() const; // Painting helper functions: - virtual SkColor GetTabBackgroundColor(TabActive active) const; + virtual SkColor GetTargetTabBackgroundColor( + TabStyle::TabSelectionState selection_state, + bool hovered) const; + virtual SkColor GetCurrentTabBackgroundColor( + TabStyle::TabSelectionState selection_state, + bool hovered) const; // Returns the thickness of the stroke drawn around the top and sides of the // tab. Only active tabs may have a stroke, and not in all cases. If there @@ -101,8 +108,9 @@ class GM2TabStyleViews : public TabStyleViews { // treated as an active tab regardless of its true current state. virtual int GetStrokeThickness(bool should_paint_as_active = false) const; - virtual bool ShouldPaintTabBackgroundColor(TabActive active, - bool has_custom_background) const; + virtual bool ShouldPaintTabBackgroundColor( + TabStyle::TabSelectionState selection_state, + bool has_custom_background) const; // Returns the progress (0 to 1) of the hover animation. double GetHoverAnimationValue() const override; @@ -116,7 +124,6 @@ class GM2TabStyleViews : public TabStyleViews { // Given a tab of width |width|, returns the radius to use for the corners. float GetTopCornerRadiusForWidth(int width) const; - protected: // Returns a single separator's opacity based on whether it is the // logically `leading` separator. `for_layout` has the same meaning as in // GetSeparatorOpacities(). @@ -129,6 +136,8 @@ class GM2TabStyleViews : public TabStyleViews { float GetHoverInterpolatedSeparatorOpacity(bool for_layout, const Tab* other_tab) const; + TabStyle::TabSelectionState GetSelectionState() const; + private: // Gets the bounds for the leading and trailing separators for a tab. TabStyle::SeparatorBounds GetSeparatorBounds(float scale) const; @@ -141,16 +150,16 @@ class GM2TabStyleViews : public TabStyleViews { // Returns whether we shoould extend the hit test region for Fitts' Law. bool ShouldExtendHitTest() const; + // Returns whether the mouse is currently hovering this tab. + bool IsHovering() const; + // Returns whether the hover animation is being shown. - bool IsHoverActive() const; + bool IsHoverAnimationActive() const; // Returns the opacity of the hover effect that should be drawn, which may not // be the same as GetHoverAnimationValue. float GetHoverOpacity() const; - // Gets the throb value. A value of 0 indicates no throbbing. - float GetThrobValue() const; - // When selected, non-active, non-hovered tabs are adjacent to each other, // there are anti-aliasing artifacts in the overlapped lower arc region. This // returns how to modify the tab shape to eliminate the lower arcs on the @@ -160,17 +169,22 @@ class GM2TabStyleViews : public TabStyleViews { // Painting helper functions: void PaintInactiveTabBackground(gfx::Canvas* canvas) const; void PaintTabBackground(gfx::Canvas* canvas, - TabActive active, + TabStyle::TabSelectionState selection_state, + bool hovered, absl::optional fill_id, int y_inset) const; + void PaintTabBackgroundWithImages( + gfx::Canvas* canvas, + absl::optional active_tab_fill_id, + absl::optional inactive_tab_fill_id) const; void PaintTabBackgroundFill(gfx::Canvas* canvas, - TabActive active, - bool paint_hover_effect, + TabStyle::TabSelectionState selection_state, + bool hovered, absl::optional fill_id, int y_inset) const; virtual void PaintBackgroundHover(gfx::Canvas* canvas, float scale) const; void PaintBackgroundStroke(gfx::Canvas* canvas, - TabActive active, + TabStyle::TabSelectionState selection_state, SkColor stroke_color) const; void PaintSeparators(gfx::Canvas* canvas) const; @@ -233,7 +247,8 @@ SkPath GM2TabStyleViews::GetPath(TabStyle::PathType path_type, // Calculate the bounds of the actual path. const float left = aligned_bounds.x(); const float right = aligned_bounds.right(); - float tab_top = aligned_bounds.y(); + float tab_top = + aligned_bounds.y() + GetLayoutConstant(TAB_STRIP_PADDING) * scale; float tab_left = left + extension; float tab_right = right - extension; @@ -445,8 +460,9 @@ float GM2TabStyleViews::GetZValue() const { float sort_value = GetHoverAnimationValue(); if (tab_->IsSelected()) sort_value += 4.f; - if (tab_->mouse_hovered()) + if (IsHovering()) { sort_value += 2.f; + } DCHECK_GE(sort_value, 0.0f); DCHECK_LE(sort_value, TabStyle::kMaximumZValue); @@ -454,14 +470,32 @@ float GM2TabStyleViews::GetZValue() const { return sort_value; } -float GM2TabStyleViews::GetActiveOpacity() const { - if (tab_->IsActive()) +float GM2TabStyleViews::GetTargetActiveOpacity() const { + const TabStyle::TabSelectionState selection_state = GetSelectionState(); + if (selection_state == TabStyle::TabSelectionState::kActive) { return 1.0f; - if (tab_->IsSelected()) - return tab_style()->GetSelectedTabOpacity(); - if (tab_->mouse_hovered()) + } + if (IsHovering()) { return GetHoverOpacity(); - return 0.0f; + } + return selection_state == TabStyle::TabSelectionState::kSelected + ? tab_style()->GetSelectedTabOpacity() + : 0.0f; +} + +float GM2TabStyleViews::GetCurrentActiveOpacity() const { + const TabStyle::TabSelectionState selection_state = GetSelectionState(); + if (selection_state == TabStyle::TabSelectionState::kActive) { + return 1.0f; + } + const float base_opacity = + selection_state == TabStyle::TabSelectionState::kSelected + ? tab_style()->GetSelectedTabOpacity() + : 0.0f; + if (!IsHoverAnimationActive()) { + return base_opacity; + } + return std::lerp(base_opacity, GetHoverOpacity(), GetHoverAnimationValue()); } TabActive GM2TabStyleViews::GetApparentActiveState() const { @@ -470,16 +504,17 @@ TabActive GM2TabStyleViews::GetApparentActiveState() const { // In particular, text should have plenty of contrast in all cases, so switch // to using foreground color designed for active tabs if the tab looks more // like an active tab than an inactive tab. - return GetActiveOpacity() > 0.5f ? TabActive::kActive : TabActive::kInactive; + return GetTargetActiveOpacity() > 0.5f ? TabActive::kActive + : TabActive::kInactive; } -TabStyle::TabColors GM2TabStyleViews::CalculateColors() const { +TabStyle::TabColors GM2TabStyleViews::CalculateTargetColors() const { + // TODO(tbergquist): Using GetApparentActiveState doesn't make sense for GM3. const TabActive active = GetApparentActiveState(); const SkColor foreground_color = tab_->controller()->GetTabForegroundColor(active); - const SkColor background_color = color_utils::AlphaBlend( - GetTabBackgroundColor(TabActive::kActive), - GetTabBackgroundColor(TabActive::kInactive), GetActiveOpacity()); + const SkColor background_color = + GetTargetTabBackgroundColor(GetSelectionState(), IsHovering()); const ui::ColorId focus_ring_color = (active == TabActive::kActive) ? kColorTabFocusRingActive : kColorTabFocusRingInactive; @@ -502,25 +537,52 @@ const gfx::FontList& GM2TabStyleViews::GetFontList() const { return normal_font_; } + void GM2TabStyleViews::PaintTab(gfx::Canvas* canvas) const { absl::optional active_tab_fill_id; - int active_tab_y_inset = 0; if (tab_->GetThemeProvider()->HasCustomImage(IDR_THEME_TOOLBAR)) { active_tab_fill_id = IDR_THEME_TOOLBAR; - active_tab_y_inset = GetStrokeThickness(true); } + const absl::optional inactive_tab_fill_id = + tab_->controller()->GetCustomBackgroundId( + BrowserFrameActiveState::kUseCurrent); - if (tab_->IsActive()) { - PaintTabBackground(canvas, TabActive::kActive, active_tab_fill_id, + if (active_tab_fill_id.has_value() || inactive_tab_fill_id.has_value()) { + PaintTabBackgroundWithImages(canvas, active_tab_fill_id, + inactive_tab_fill_id); + } else { + PaintTabBackground(canvas, GetSelectionState(), IsHoverAnimationActive(), + absl::nullopt, 0); + } +} + +void GM2TabStyleViews::PaintTabBackgroundWithImages( + gfx::Canvas* canvas, + absl::optional active_tab_fill_id, + absl::optional inactive_tab_fill_id) const { + // When at least one of the active or inactive tab backgrounds have an image, + // we must paint them with the previous method of layering the active and + // inactive images with two paint calls. + + const int active_tab_y_inset = GetStrokeThickness(true); + const TabStyle::TabSelectionState current_state = GetSelectionState(); + + if (current_state == TabStyle::TabSelectionState::kActive) { + PaintTabBackground(canvas, TabStyle::TabSelectionState::kActive, + /*hovered=*/false, active_tab_fill_id, active_tab_y_inset); } else { - PaintInactiveTabBackground(canvas); + // TODO(tbergquist): This needs to paint a pill shape for hover, especially + // when selected, in GM3. + PaintTabBackground(canvas, TabStyle::TabSelectionState::kInactive, + /*hovered=*/false, inactive_tab_fill_id, 0); - const float throb_value = GetThrobValue(); - if (throb_value > 0) { - canvas->SaveLayerAlpha(base::ClampRound(throb_value * 0xff), + const float opacity = GetCurrentActiveOpacity(); + if (opacity > 0) { + canvas->SaveLayerAlpha(base::ClampRound(opacity * 0xff), tab_->GetLocalBounds()); - PaintTabBackground(canvas, TabActive::kActive, active_tab_fill_id, + PaintTabBackground(canvas, TabStyle::TabSelectionState::kActive, + /*hovered=*/false, active_tab_fill_id, active_tab_y_inset); canvas->Restore(); } @@ -564,12 +626,15 @@ TabStyle::SeparatorBounds GM2TabStyleViews::GetSeparatorBounds( TabStyle::SeparatorBounds separator_bounds; + const int extra_vertical_space = + aligned_bounds.height() - + (separator_size.height() + separator_margin.bottom() + + separator_margin.top()); + separator_bounds.leading = gfx::RectF( aligned_bounds.x() + corner_radius - separator_margin.right() - separator_size.width(), - aligned_bounds.y() + (aligned_bounds.height() - separator_size.height() - - separator_margin.bottom()) / - 2, + aligned_bounds.y() + extra_vertical_space / 2 + separator_margin.top(), separator_size.width(), separator_size.height()); separator_bounds.trailing = separator_bounds.leading; @@ -718,15 +783,18 @@ bool GM2TabStyleViews::ShouldExtendHitTest() const { return widget->IsMaximized() || widget->IsFullscreen(); } -bool GM2TabStyleViews::IsHoverActive() const { - if (!hover_controller_) - return false; - return hover_controller_->ShouldDraw(); +bool GM2TabStyleViews::IsHovering() const { + return tab_->mouse_hovered(); +} + +bool GM2TabStyleViews::IsHoverAnimationActive() const { + return IsHovering() || (hover_controller_ && hover_controller_->ShouldDraw()); } double GM2TabStyleViews::GetHoverAnimationValue() const { - if (!hover_controller_) - return 0.0; + if (!hover_controller_) { + return IsHoverAnimationActive() ? 1.0 : 0.0; + } return hover_controller_->GetAnimationValue(); } @@ -743,22 +811,6 @@ float GM2TabStyleViews::GetHoverOpacity() const { return tab_->controller()->GetHoverOpacityForTab(t * t); } -float GM2TabStyleViews::GetThrobValue() const { - const bool is_selected = tab_->IsSelected(); - double val = is_selected ? tab_style()->GetSelectedTabOpacity() : 0; - - if (IsHoverActive()) { - const float kSelectedTabThrobScale = - 0.95f - tab_style()->GetSelectedTabOpacity(); - const float opacity = GetHoverOpacity(); - const float offset = - is_selected ? (kSelectedTabThrobScale * opacity) : opacity; - val += GetHoverAnimationValue() * offset; - } - - return val; -} - int GM2TabStyleViews::GetStrokeThickness(bool should_paint_as_active) const { absl::optional group = tab_->group(); if (group.has_value() && tab_->IsActive()) @@ -771,17 +823,19 @@ int GM2TabStyleViews::GetStrokeThickness(bool should_paint_as_active) const { } bool GM2TabStyleViews::ShouldPaintTabBackgroundColor( - TabActive active, + TabStyle::TabSelectionState selection_state, bool has_custom_background) const { // In the active case, always paint the tab background. The fill image may be // transparent. - if (active == TabActive::kActive) + if (selection_state == TabStyle::TabSelectionState::kActive) { return true; + } // In the inactive case, the fill image is guaranteed to be opaque, so it's // not necessary to paint the background when there is one. - if (has_custom_background) + if (has_custom_background) { return false; + } return tab_->GetThemeProvider()->GetDisplayProperty( ThemeProperties::SHOULD_FILL_BACKGROUND_TAB_COLOR); @@ -791,18 +845,59 @@ SkColor GM2TabStyleViews::GetTabSeparatorColor() const { return tab_->controller()->GetTabSeparatorColor(); } -SkColor GM2TabStyleViews::GetTabBackgroundColor(TabActive active) const { - SkColor color = tab_->controller()->GetTabBackgroundColor( - active, BrowserFrameActiveState::kUseCurrent); +SkColor GM2TabStyleViews::GetTargetTabBackgroundColor( + const TabStyle::TabSelectionState selection_state, + bool hovered) const { + // Tests may not have a color provider or a widget. + const bool active_widget = + tab_->GetWidget() ? tab_->GetWidget()->ShouldPaintAsActive() : true; + if (!tab_->GetColorProvider()) { + return gfx::kPlaceholderColor; + } - return color; + const SkColor color = tab_style()->GetTabBackgroundColor( + selection_state, hovered, active_widget, *tab_->GetColorProvider()); + if (!hovered) { + return color; + } + + // In GM2, we blend the target hover color here because it depends on the tab + // width. + const SkColor unhovered_color = tab_style()->GetTabBackgroundColor( + selection_state, /*hovered=*/false, active_widget, + *tab_->GetColorProvider()); + return color_utils::AlphaBlend(color, unhovered_color, GetHoverOpacity()); +} + +SkColor GM2TabStyleViews::GetCurrentTabBackgroundColor( + const TabStyle::TabSelectionState selection_state, + bool hovered) const { + const SkColor color = GetTargetTabBackgroundColor(selection_state, hovered); + if (!hovered) { + return color; + } + + const SkColor unhovered_color = + GetTargetTabBackgroundColor(selection_state, /*hovered=*/false); + return color_utils::AlphaBlend(color, unhovered_color, + static_cast(GetHoverAnimationValue())); +} + +TabStyle::TabSelectionState GM2TabStyleViews::GetSelectionState() const { + if (tab_->IsActive()) { + return TabStyle::TabSelectionState::kActive; + } + if (tab_->IsSelected()) { + return TabStyle::TabSelectionState::kSelected; + } + return TabStyle::TabSelectionState::kInactive; } ShapeModifier GM2TabStyleViews::GetShapeModifier( TabStyle::PathType path_type) const { ShapeModifier shape_modifier = kNone; if (path_type == TabStyle::PathType::kFill && tab_->IsSelected() && - !IsHoverActive() && !tab_->IsActive()) { + !IsHoverAnimationActive() && !tab_->IsActive()) { auto check_adjacent_tab = [](const Tab* tab, int offset, ShapeModifier modifier) { const Tab* adjacent_tab = tab->controller()->GetAdjacentTab(tab, offset); @@ -817,25 +912,18 @@ ShapeModifier GM2TabStyleViews::GetShapeModifier( return shape_modifier; } -void GM2TabStyleViews::PaintInactiveTabBackground(gfx::Canvas* canvas) const { - PaintTabBackground(canvas, TabActive::kInactive, - tab_->controller()->GetCustomBackgroundId( - BrowserFrameActiveState::kUseCurrent), - 0); -} - -void GM2TabStyleViews::PaintTabBackground(gfx::Canvas* canvas, - TabActive active, - absl::optional fill_id, - int y_inset) const { +void GM2TabStyleViews::PaintTabBackground( + gfx::Canvas* canvas, + TabStyle::TabSelectionState selection_state, + bool hovered, + absl::optional fill_id, + int y_inset) const { // |y_inset| is only set when |fill_id| is being used. DCHECK(!y_inset || fill_id.has_value()); absl::optional group_color = tab_->GetGroupColor(); - PaintTabBackgroundFill(canvas, active, - active == TabActive::kInactive && IsHoverActive(), - fill_id, y_inset); + PaintTabBackgroundFill(canvas, selection_state, hovered, fill_id, y_inset); const auto* widget = tab_->GetWidget(); DCHECK(widget); @@ -843,27 +931,29 @@ void GM2TabStyleViews::PaintTabBackground(gfx::Canvas* canvas, tab_->GetWidget()->ShouldPaintAsActive() ? kColorTabStrokeFrameActive : kColorTabStrokeFrameInactive); - PaintBackgroundStroke(canvas, active, group_color.value_or(tab_stroke_color)); + PaintBackgroundStroke(canvas, selection_state, + group_color.value_or(tab_stroke_color)); PaintSeparators(canvas); } -void GM2TabStyleViews::PaintTabBackgroundFill(gfx::Canvas* canvas, - TabActive active, - bool paint_hover_effect, - absl::optional fill_id, - int y_inset) const { +void GM2TabStyleViews::PaintTabBackgroundFill( + gfx::Canvas* canvas, + TabStyle::TabSelectionState selection_state, + bool hovered, + absl::optional fill_id, + int y_inset) const { const SkPath fill_path = GetPath(TabStyle::PathType::kFill, canvas->image_scale(), - active == TabActive::kActive); + selection_state == TabStyle::TabSelectionState::kActive); gfx::ScopedCanvas scoped_canvas(canvas); const float scale = canvas->UndoDeviceScaleFactor(); canvas->ClipPath(fill_path, true); - if (ShouldPaintTabBackgroundColor(active, fill_id.has_value())) { + if (ShouldPaintTabBackgroundColor(selection_state, fill_id.has_value())) { cc::PaintFlags flags; flags.setAntiAlias(true); - flags.setColor(GetTabBackgroundColor(active)); + flags.setColor(GetCurrentTabBackgroundColor(selection_state, hovered)); canvas->DrawRect(gfx::ScaleToEnclosingRect(tab_->GetLocalBounds(), scale), flags); } @@ -877,20 +967,29 @@ void GM2TabStyleViews::PaintTabBackgroundFill(gfx::Canvas* canvas, y_inset, tab_->width(), tab_->height()); } - if (paint_hover_effect) { + if (hovered) { PaintBackgroundHover(canvas, scale); } } void GM2TabStyleViews::PaintBackgroundHover(gfx::Canvas* canvas, float scale) const { + if (!hover_controller_) { + return; + } + + // Paint an extra radial 'glow' effect around the cursor, using the active tab + // color as a highlight. + SkPoint hover_location(gfx::PointToSkPoint(hover_controller_->location())); hover_location.scale(SkFloatToScalar(scale)); const SkScalar kMinHoverRadius = 16; const SkScalar radius = std::max(SkFloatToScalar(tab_->width() / 4.f), kMinHoverRadius) * scale; - const SkColor color = SkColorSetA(GetTabBackgroundColor(TabActive::kActive), - hover_controller_->GetAlpha()); + const SkColor color = + SkColorSetA(GetCurrentTabBackgroundColor( + TabStyle::TabSelectionState::kActive, /*hovered=*/false), + hover_controller_->GetAlpha()); // TODO(crbug/1308932): Remove FromColor and make all SkColor4f. const SkColor4f colors[2] = { @@ -906,10 +1005,12 @@ void GM2TabStyleViews::PaintBackgroundHover(gfx::Canvas* canvas, flags); } -void GM2TabStyleViews::PaintBackgroundStroke(gfx::Canvas* canvas, - TabActive active, - SkColor stroke_color) const { - const bool is_active = active == TabActive::kActive; +void GM2TabStyleViews::PaintBackgroundStroke( + gfx::Canvas* canvas, + TabStyle::TabSelectionState selection_state, + SkColor stroke_color) const { + const bool is_active = + selection_state == TabStyle::TabSelectionState::kActive; const int stroke_thickness = GetStrokeThickness(is_active); if (!stroke_thickness) return; @@ -946,9 +1047,11 @@ void GM2TabStyleViews::PaintSeparators(gfx::Canvas* canvas) const { cc::PaintFlags flags; flags.setAntiAlias(true); flags.setColor(separator_color(separator_opacities.left)); - canvas->DrawRect(separator_bounds.leading, flags); + canvas->DrawRoundRect(separator_bounds.leading, + tab_style()->GetSeparatorCornerRadius() * scale, flags); flags.setColor(separator_color(separator_opacities.right)); - canvas->DrawRect(separator_bounds.trailing, flags); + canvas->DrawRoundRect(separator_bounds.trailing, + tab_style()->GetSeparatorCornerRadius() * scale, flags); } float GM2TabStyleViews::GetTopCornerRadiusForWidth(int width) const { @@ -1001,7 +1104,9 @@ class ChromeRefresh2023TabStyleViews : public GM2TabStyleViews { public: explicit ChromeRefresh2023TabStyleViews(Tab* tab); ~ChromeRefresh2023TabStyleViews() override = default; - SkColor GetTabBackgroundColor(TabActive active) const override; + SkColor GetTargetTabBackgroundColor( + TabStyle::TabSelectionState selection_state, + bool hovered) const override; int GetStrokeThickness(bool should_paint_as_active = false) const override; SkPath GetPath(TabStyle::PathType path_type, float scale, @@ -1018,22 +1123,18 @@ class ChromeRefresh2023TabStyleViews : public GM2TabStyleViews { ChromeRefresh2023TabStyleViews::ChromeRefresh2023TabStyleViews(Tab* tab) : GM2TabStyleViews(tab) {} -SkColor ChromeRefresh2023TabStyleViews::GetTabBackgroundColor( - TabActive active) const { - const auto* cp = tab()->GetWidget()->GetColorProvider(); - DCHECK(cp); - if (!cp) { +SkColor ChromeRefresh2023TabStyleViews::GetTargetTabBackgroundColor( + TabStyle::TabSelectionState selection_state, + bool hovered) const { + // Tests may not have a color provider or a widget. + const bool active_widget = + tab()->GetWidget() ? tab()->GetWidget()->ShouldPaintAsActive() : true; + if (!tab()->GetColorProvider()) { return gfx::kPlaceholderColor; } - constexpr ChromeColorIds kColorIds[2][2] = { - {kColorTabBackgroundInactiveFrameInactive, - kColorTabBackgroundInactiveFrameActive}, - {kColorTabBackgroundActiveFrameInactive, - kColorTabBackgroundActiveFrameActive}}; - - return cp->GetColor(kColorIds[int(active == TabActive::kActive)][int( - tab()->GetWidget()->ShouldPaintAsActive())]); + return tab_style()->GetTabBackgroundColor( + selection_state, hovered, active_widget, *tab()->GetColorProvider()); } int ChromeRefresh2023TabStyleViews::GetStrokeThickness( @@ -1053,13 +1154,16 @@ SkPath ChromeRefresh2023TabStyleViews::GetPath( CHECK(tab()); const int stroke_thickness = GetStrokeThickness(force_active); - // Active fill for CR23 is the same as GM2. Selected/hover is a detached tab. - if ((path_type == TabStyle::PathType::kFill && !tab()->IsActive() && - tab()->IsSelected()) || - (path_type == TabStyle::PathType::kHighlight)) { + const TabStyle::TabSelectionState state = GetSelectionState(); + // Active tab fill for CR23 is the same 'folio' style as GM2. Selected, hover, + // and inactive tab fills are a detached squarcle tab. + if ((path_type == TabStyle::PathType::kFill && + state != TabStyle::TabSelectionState::kActive) || + path_type == TabStyle::PathType::kHighlight || + path_type == TabStyle::PathType::kInteriorClip || + path_type == TabStyle::PathType::kHitTest) { // TODO (crbug.com/1451400): This constant should be unified with // kCRtabstripRegionViewControlPadding in tab_strip_region_view. - constexpr int kChromeRefreshDetachedTabBottomPadding = 6; gfx::RectF aligned_bounds = ScaleAndAlignBounds(tab()->bounds(), scale, stroke_thickness); @@ -1070,17 +1174,52 @@ SkPath ChromeRefresh2023TabStyleViews::GetPath( GetTopCornerRadiusForWidth(tab()->width()) * scale; const float extension_corner_radius = tab_style()->GetBottomCornerRadius() * scale; - const float tab_height = - (tab_style()->GetHeight() - kChromeRefreshDetachedTabBottomPadding) * - scale; + float tab_height = GetLayoutConstant(TAB_HEIGHT) * scale; - SkPath path; + // The tab displays favicon animations that can emerge from the toolbar. The + // interior clip needs to extend the entire height of the toolbar to support + // this. Detached tab shapes do not need to respect this. + if (path_type != TabStyle::PathType::kInteriorClip && + path_type != TabStyle::PathType::kHitTest) { + tab_height -= GetLayoutConstant(TAB_STRIP_PADDING) * scale; + tab_height -= GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP) * scale; + } - const int left = aligned_bounds.x() + extension_corner_radius; - const int top = aligned_bounds.y(); - const int right = aligned_bounds.right() - extension_corner_radius; + int left = aligned_bounds.x() + extension_corner_radius; + int top = aligned_bounds.y() + GetLayoutConstant(TAB_STRIP_PADDING) * scale; + int right = aligned_bounds.right() - extension_corner_radius; const int bottom = top + tab_height; + // For maximized and fullscreen windows, extend the tab hit test to the top + // of the tab, encompassing the top padding. This makes it easy to click on + // tabs by moving the mouse to the top of the screen. + if (path_type == TabStyle::PathType::kHitTest && + (tab()->GetWidget()->IsMaximized() || + tab()->GetWidget()->IsFullscreen())) { + top -= GetLayoutConstant(TAB_STRIP_PADDING) * scale; + } + + // if the size of the space for the path is smaller than the size of a + // favicon or if we are building a path for the hit test, expand to take the + // entire width of the separator margins AND the separator. + if ((right - left) < (gfx::kFaviconSize * scale) || + path_type == TabStyle::PathType::kHitTest) { + // Take the entire size of the separator. in odd separator size cases, the + // right side will take the remaining space. + const int left_separator_overlap = + tab_style()->GetSeparatorSize().width() / 2; + const int right_separator_overlap = + tab_style()->GetSeparatorSize().width() - left_separator_overlap; + + left -= (tab_style()->GetSeparatorMargins().right() + + left_separator_overlap) * + scale; + right += (tab_style()->GetSeparatorMargins().left() + + right_separator_overlap) * + scale; + } + + SkPath path; SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeLTRB(left, top, right, bottom), content_corner_radius, content_corner_radius); @@ -1109,17 +1248,12 @@ void ChromeRefresh2023TabStyleViews::PaintBackgroundHover(gfx::Canvas* canvas, GetPath(TabStyle::PathType::kHighlight, canvas->image_scale(), true); canvas->ClipPath(fill_path, true); - const auto* cp = tab()->GetWidget()->GetColorProvider(); - const SkColor color = - cp->GetColor(tab()->GetWidget()->ShouldPaintAsActive() - ? kColorTabBackgroundHoverFrameActive - : kColorTabBackgroundHoverFrameInactive); - const SkColor4f color_with_alpha_animation = SkColor4f::FromColor( - SkColorSetA(color, GetHoverAnimationValue() * SkColorGetA(color))); + const SkColor hover_color = + GetCurrentTabBackgroundColor(GetSelectionState(), /*hovered=*/true); cc::PaintFlags flags; flags.setAntiAlias(true); - flags.setColor(color_with_alpha_animation); + flags.setColor(hover_color); canvas->DrawRect(gfx::ScaleToEnclosingRect(tab()->GetLocalBounds(), scale), flags); } diff --git a/src/chrome/browser/ui/views/tabs/tab_style_views.h b/src/chrome/browser/ui/views/tabs/tab_style_views.h index b9067180..1374babe 100644 --- a/src/chrome/browser/ui/views/tabs/tab_style_views.h +++ b/src/chrome/browser/ui/views/tabs/tab_style_views.h @@ -66,11 +66,15 @@ class TabStyleViews { // active opacity. virtual TabActive GetApparentActiveState() const = 0; + // Returns the target opacity of the "active" portion of the tab's state. The + // current opacity may be animating towards this value. + virtual float GetTargetActiveOpacity() const = 0; + // Returns the current opacity of the "active" portion of the tab's state. - virtual float GetActiveOpacity() const = 0; + virtual float GetCurrentActiveOpacity() const = 0; // Derives and returns colors for the tab. See TabColors, above. - virtual TabStyle::TabColors CalculateColors() const = 0; + virtual TabStyle::TabColors CalculateTargetColors() const = 0; // Sets the center of the radial highlight in the hover animation. virtual void SetHoverLocation(const gfx::Point& location) = 0; diff --git a/src/chrome/android/java/res_chromium/drawable-hdpi/fre_product_logo.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-hdpi/fre_product_logo.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-hdpi/fre_product_logo.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-hdpi/fre_product_logo.png diff --git a/src/chrome/android/java/res_chromium/drawable-hdpi/product_logo_name.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-hdpi/product_logo_name.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-hdpi/product_logo_name.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-hdpi/product_logo_name.png diff --git a/src/chrome/android/java/res_chromium/drawable-mdpi/fre_product_logo.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-mdpi/fre_product_logo.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-mdpi/fre_product_logo.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-mdpi/fre_product_logo.png diff --git a/src/chrome/android/java/res_chromium/drawable-mdpi/product_logo_name.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-mdpi/product_logo_name.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-mdpi/product_logo_name.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-mdpi/product_logo_name.png diff --git a/src/chrome/android/java/res_chromium/drawable-xhdpi/fre_product_logo.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-xhdpi/fre_product_logo.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-xhdpi/fre_product_logo.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-xhdpi/fre_product_logo.png diff --git a/src/chrome/android/java/res_chromium/drawable-xhdpi/product_logo_name.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-xhdpi/product_logo_name.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-xhdpi/product_logo_name.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-xhdpi/product_logo_name.png diff --git a/src/chrome/android/java/res_chromium/drawable-xxhdpi/fre_product_logo.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-xxhdpi/fre_product_logo.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-xxhdpi/fre_product_logo.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-xxhdpi/fre_product_logo.png diff --git a/src/chrome/android/java/res_chromium/drawable-xxhdpi/product_logo_name.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-xxhdpi/product_logo_name.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-xxhdpi/product_logo_name.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-xxhdpi/product_logo_name.png diff --git a/src/chrome/android/java/res_chromium/drawable-xxxhdpi/fre_product_logo.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-xxxhdpi/fre_product_logo.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-xxxhdpi/fre_product_logo.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-xxxhdpi/fre_product_logo.png diff --git a/src/chrome/android/java/res_chromium/drawable-xxxhdpi/product_logo_name.png b/src/components/browser_ui/styles/android/java/res_chromium/drawable-xxxhdpi/product_logo_name.png similarity index 100% rename from src/chrome/android/java/res_chromium/drawable-xxxhdpi/product_logo_name.png rename to src/components/browser_ui/styles/android/java/res_chromium/drawable-xxxhdpi/product_logo_name.png diff --git a/src/components/history/core/browser/history_backend.cc b/src/components/history/core/browser/history_backend.cc index 30ec5a54..afaa552d 100644 --- a/src/components/history/core/browser/history_backend.cc +++ b/src/components/history/core/browser/history_backend.cc @@ -967,6 +967,11 @@ void HistoryBackend::AddPage(const HistoryAddPageArgs& request) { VisitID last_visit_id = tracker_.GetLastVisit( request.context_id, request.nav_entry_id, request.referrer); + GURL external_referrer_url; + if (request.referrer.is_valid() && last_visit_id == kInvalidVisitID) { + external_referrer_url = request.referrer; + } + const VisitID from_visit_id = last_visit_id; // If a redirect chain is given, we expect the last item in that chain to be @@ -1015,10 +1020,11 @@ void HistoryBackend::AddPage(const HistoryAddPageArgs& request) { // No redirect case (one element means just the page itself). last_visit_id = - AddPageVisit(request.url, request.time, last_visit_id, t, - request.hidden, request.visit_source, IsTypedIncrement(t), - opener_visit, request.consider_for_ntp_most_visited, - request.title) + AddPageVisit(request.url, request.time, last_visit_id, + external_referrer_url, t, request.hidden, + request.visit_source, IsTypedIncrement(t), opener_visit, + request.consider_for_ntp_most_visited, + request.local_navigation_id, request.title) .second; // Update the segment for this visit. KEYWORD_GENERATED visits should not @@ -1141,10 +1147,12 @@ void HistoryBackend::AddPage(const HistoryAddPageArgs& request) { // the chain. last_visit_id = AddPageVisit(redirects[redirect_index], request.time, last_visit_id, - t, request.hidden, request.visit_source, + redirect_index == 0 ? external_referrer_url : GURL(), t, + request.hidden, request.visit_source, should_increment_typed_count, redirect_index == 0 ? opener_visit : 0, - request.consider_for_ntp_most_visited, request.title) + request.consider_for_ntp_most_visited, + request.local_navigation_id, request.title) .second; if (t & ui::PAGE_TRANSITION_CHAIN_START) { @@ -1338,12 +1346,14 @@ std::pair HistoryBackend::AddPageVisit( const GURL& url, Time time, VisitID referring_visit, + const GURL& external_referrer_url, ui::PageTransition transition, bool hidden, VisitSource visit_source, bool should_increment_typed_count, VisitID opener_visit, bool consider_for_ntp_most_visited, + absl::optional local_navigation_id, absl::optional title, absl::optional visit_duration, absl::optional originator_cache_guid, @@ -1391,6 +1401,7 @@ std::pair HistoryBackend::AddPageVisit( VisitRow visit_info(url_id, time, referring_visit, transition, /*arg_segment_id=*/0, should_increment_typed_count, opener_visit); + visit_info.external_referrer_url = external_referrer_url; if (visit_duration.has_value()) visit_info.visit_duration = *visit_duration; if (originator_cache_guid.has_value()) @@ -1411,7 +1422,7 @@ std::pair HistoryBackend::AddPageVisit( // Broadcast a notification of the visit. if (visit_info.visit_id) { - NotifyURLVisited(url_info, visit_info); + NotifyURLVisited(url_info, visit_info, local_navigation_id); } else { DLOG(ERROR) << "Failed to build visit insert statement: " << "url_id = " << url_id; @@ -1635,11 +1646,13 @@ bool HistoryBackend::AddVisits(const GURL& url, VisitSource visit_source) { if (db_) { for (const auto& visit : visits) { - if (!AddPageVisit(url, visit.first, /*referring_visit=*/0, visit.second, + if (!AddPageVisit(url, visit.first, /*referring_visit=*/0, + /*external_referrer_url=*/GURL(), visit.second, /*hidden=*/!ui::PageTransitionIsMainFrame(visit.second), visit_source, IsTypedIncrement(visit.second), /*opener_visit=*/0, - /*consider_for_ntp_most_visited=*/true) + /*consider_for_ntp_most_visited=*/true, + /*local_navigation_id=*/absl::nullopt) .first) { return false; } @@ -1682,12 +1695,14 @@ VisitID HistoryBackend::AddSyncedVisit( } auto [url_id, visit_id] = AddPageVisit( - url, visit.visit_time, visit.referring_visit, visit.transition, hidden, - VisitSource::SOURCE_SYNCED, IsTypedIncrement(visit.transition), - visit.opener_visit, visit.consider_for_ntp_most_visited, title, - visit.visit_duration, visit.originator_cache_guid, - visit.originator_visit_id, visit.originator_referring_visit, - visit.originator_opener_visit, visit.is_known_to_sync); + url, visit.visit_time, visit.referring_visit, visit.external_referrer_url, + visit.transition, hidden, VisitSource::SOURCE_SYNCED, + IsTypedIncrement(visit.transition), visit.opener_visit, + visit.consider_for_ntp_most_visited, + /*local_navigation_id=*/absl::nullopt, title, visit.visit_duration, + visit.originator_cache_guid, visit.originator_visit_id, + visit.originator_referring_visit, visit.originator_opener_visit, + visit.is_known_to_sync); if (visit_id == kInvalidVisitID) { // Adding the page visit failed, do not continue. @@ -2447,6 +2462,16 @@ void HistoryBackend::UpdateClusterVisit( db_->UpdateClusterVisit(cluster_id, cluster_visit); } +void HistoryBackend::UpdateVisitsInteractionState( + const std::vector& visit_ids, + const ClusterVisit::InteractionState interaction_state) { + TRACE_EVENT0("browser", "HistoryBackend::UpdateVisitsInteractionState"); + if (!db_) { + return; + } + db_->UpdateVisitsInteractionState(visit_ids, interaction_state); +} + std::vector HistoryBackend::GetMostRecentClusters( base::Time inclusive_min_time, base::Time exclusive_max_time, @@ -3521,12 +3546,14 @@ void HistoryBackend::NotifyFaviconsChanged(const std::set& page_urls, delegate_->NotifyFaviconsChanged(page_urls, icon_url); } -void HistoryBackend::NotifyURLVisited(const URLRow& url_row, - const VisitRow& visit_row) { +void HistoryBackend::NotifyURLVisited( + const URLRow& url_row, + const VisitRow& visit_row, + absl::optional local_navigation_id) { for (HistoryBackendObserver& observer : observers_) observer.OnURLVisited(this, url_row, visit_row); - delegate_->NotifyURLVisited(url_row, visit_row); + delegate_->NotifyURLVisited(url_row, visit_row, local_navigation_id); } void HistoryBackend::NotifyURLsModified(const URLRows& changed_urls, diff --git a/src/components/variations/service/variations_service.cc b/src/components/variations/service/variations_service.cc index ec2a59cd..b81a1412 100644 --- a/src/components/variations/service/variations_service.cc +++ b/src/components/variations/service/variations_service.cc @@ -223,6 +223,7 @@ bool IsFetchingEnabled() { return false; } + // Returns the already downloaded first run seed, and clear the seed from the // native-side prefs. At this point, the seed has already been fetched from the // native seed storage, so it's no longer needed there. This is done regardless @@ -693,7 +694,8 @@ void VariationsService::InitResourceRequestedAllowedNotifier() { // ResourceRequestAllowedNotifier does not install an observer if there is no // NetworkChangeNotifier, which results in never being notified of changes to // network status. - resource_request_allowed_notifier_->Init(this, false /* leaky */); + resource_request_allowed_notifier_->Init(this, /*leaky=*/false, + /*wait_for_eula=*/false); } void VariationsService::StartRepeatedVariationsSeedFetch() { @@ -977,13 +979,17 @@ bool VariationsService::OverrideStoredPermanentCountry( const std::string& country_override) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + const std::string country_override_lowercase = + base::ToLowerASCII(country_override); const std::string stored_country = local_state_->GetString(prefs::kVariationsPermanentOverriddenCountry); - if (stored_country == country_override) + if (stored_country == country_override_lowercase) { return false; + } - field_trial_creator_.StoreVariationsOverriddenCountry(country_override); + field_trial_creator_.StoreVariationsOverriddenCountry( + country_override_lowercase); return true; } diff --git a/src/components/version_ui/resources/about_version.html b/src/components/version_ui/resources/about_version.html index 4b704b72..f1d594e0 100644 --- a/src/components/version_ui/resources/about_version.html +++ b/src/components/version_ui/resources/about_version.html @@ -65,6 +65,7 @@ about:version template page

+
@@ -76,6 +77,16 @@ about:version template page media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)"> Thorium Mascot +
+ +
+ + + + + Thorium Mascot + +
diff --git a/src/media/base/supported_types.cc b/src/media/base/supported_types.cc index 1aa6e048..392a7077 100644 --- a/src/media/base/supported_types.cc +++ b/src/media/base/supported_types.cc @@ -42,24 +42,30 @@ namespace media { namespace { +template class SupplementalProfileCache { public: - void UpdateCache(const base::flat_set& profiles) { + void UpdateCache(const base::flat_set& profiles) { base::AutoLock lock(profiles_lock_); profiles_ = profiles; } - bool IsProfileSupported(media::VideoCodecProfile profile) { + bool IsProfileSupported(T profile) { base::AutoLock lock(profiles_lock_); return profiles_.find(profile) != profiles_.end(); } private: base::Lock profiles_lock_; - base::flat_set profiles_ GUARDED_BY(profiles_lock_); + base::flat_set profiles_ GUARDED_BY(profiles_lock_); }; -SupplementalProfileCache* GetSupplementalProfileCache() { - static base::NoDestructor cache; +SupplementalProfileCache* GetSupplementalProfileCache() { + static base::NoDestructor> cache; + return cache.get(); +} + +SupplementalProfileCache* GetSupplementalAudioTypeCache() { + static base::NoDestructor> cache; return cache.get(); } @@ -274,9 +280,7 @@ bool IsAACSupported(const AudioType& type) { return base::android::BuildInfo::GetInstance()->sdk_int() >= base::android::SDK_VERSION_P; #elif BUILDFLAG(IS_MAC) - if (__builtin_available(macOS 10.15, *)) - return true; - return false; + return true; #elif BUILDFLAG(IS_WIN) return base::win::GetVersion() >= base::win::Version::WIN11_22H2; #else @@ -284,6 +288,16 @@ bool IsAACSupported(const AudioType& type) { #endif } +bool IsDolbyVisionProfileSupported(const VideoType& type) { +#if BUILDFLAG(ENABLE_PLATFORM_HEVC) && \ + BUILDFLAG(PLATFORM_HAS_OPTIONAL_HEVC_SUPPORT) && \ + BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) + return GetSupplementalProfileCache()->IsProfileSupported(type.profile); +#else + return false; +#endif +} + } // namespace bool IsSupportedAudioType(const AudioType& type) { @@ -323,9 +337,10 @@ bool IsDefaultSupportedVideoType(const VideoType& type) { return IsHevcProfileSupported(type); case VideoCodec::kMPEG4: return IsMPEG4Supported(); + case VideoCodec::kDolbyVision: + return IsDolbyVisionProfileSupported(type); case VideoCodec::kUnknown: case VideoCodec::kVC1: - case VideoCodec::kDolbyVision: return false; } } @@ -404,4 +419,8 @@ void UpdateDefaultSupportedVideoProfiles( GetSupplementalProfileCache()->UpdateCache(profiles); } +void UpdateDefaultSupportedAudioTypes(const base::flat_set& types) { + GetSupplementalAudioTypeCache()->UpdateCache(types); +} + } // namespace media diff --git a/src/third_party/blink/renderer/core/exported/web_view_impl.cc b/src/third_party/blink/renderer/core/exported/web_view_impl.cc deleted file mode 100644 index dcd60eb0..00000000 --- a/src/third_party/blink/renderer/core/exported/web_view_impl.cc +++ /dev/null @@ -1,3969 +0,0 @@ -/* - * Copyright (C) 2011, 2012, 2023 Google Inc. and Alex313031. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "third_party/blink/renderer/core/exported/web_view_impl.h" - -#include -#include -#include - -#include "base/command_line.h" -#include "base/debug/crash_logging.h" -#include "base/debug/dump_without_crashing.h" -#include "base/memory/scoped_refptr.h" -#include "base/metrics/histogram_macros.h" -#include "base/observer_list.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "cc/layers/picture_layer.h" -#include "components/viz/common/features.h" -#include "media/base/media_switches.h" -#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/public/common/history/session_history_constants.h" -#include "third_party/blink/public/common/input/web_input_event.h" -#include "third_party/blink/public/common/input/web_menu_source_type.h" -#include "third_party/blink/public/common/page/page_zoom.h" -#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h" -#include "third_party/blink/public/common/switches.h" -#include "third_party/blink/public/common/web_preferences/web_preferences.h" -#include "third_party/blink/public/mojom/frame/frame_replication_state.mojom-blink.h" -#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" -#include "third_party/blink/public/mojom/window_features/window_features.mojom-blink.h" -#include "third_party/blink/public/platform/interface_registry.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" -#include "third_party/blink/public/platform/web_media_player.h" -#include "third_party/blink/public/platform/web_network_state_notifier.h" -#include "third_party/blink/public/platform/web_runtime_features.h" -#include "third_party/blink/public/platform/web_text_input_info.h" -#include "third_party/blink/public/platform/web_url_request.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/public/web/web_autofill_client.h" -#include "third_party/blink/public/web/web_console_message.h" -#include "third_party/blink/public/web/web_element.h" -#include "third_party/blink/public/web/web_frame.h" -#include "third_party/blink/public/web/web_hit_test_result.h" -#include "third_party/blink/public/web/web_input_element.h" -#include "third_party/blink/public/web/web_local_frame_client.h" -#include "third_party/blink/public/web/web_meaningful_layout.h" -#include "third_party/blink/public/web/web_navigation_type.h" -#include "third_party/blink/public/web/web_node.h" -#include "third_party/blink/public/web/web_plugin.h" -#include "third_party/blink/public/web/web_range.h" -#include "third_party/blink/public/web/web_render_theme.h" -#include "third_party/blink/public/web/web_view_client.h" -#include "third_party/blink/public/web/web_window_features.h" -#include "third_party/blink/renderer/core/clipboard/data_object.h" -#include "third_party/blink/renderer/core/content_capture/content_capture_manager.h" -#include "third_party/blink/renderer/core/core_initializer.h" -#include "third_party/blink/renderer/core/css_value_keywords.h" -#include "third_party/blink/renderer/core/dom/context_features_client_impl.h" -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/events/native_event_listener.h" -#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h" -#include "third_party/blink/renderer/core/dom/text.h" -#include "third_party/blink/renderer/core/editing/editing_utilities.h" -#include "third_party/blink/renderer/core/editing/editor.h" -#include "third_party/blink/renderer/core/editing/ephemeral_range.h" -#include "third_party/blink/renderer/core/editing/frame_selection.h" -#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h" -#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h" -#include "third_party/blink/renderer/core/editing/selection_template.h" -#include "third_party/blink/renderer/core/editing/serializers/html_interchange.h" -#include "third_party/blink/renderer/core/editing/serializers/serialization.h" -#include "third_party/blink/renderer/core/events/current_input_event.h" -#include "third_party/blink/renderer/core/events/keyboard_event.h" -#include "third_party/blink/renderer/core/events/ui_event_with_key_state.h" -#include "third_party/blink/renderer/core/events/web_input_event_conversion.h" -#include "third_party/blink/renderer/core/events/wheel_event.h" -#include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h" -#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h" -#include "third_party/blink/renderer/core/exported/web_settings_impl.h" -#include "third_party/blink/renderer/core/frame/browser_controls.h" -#include "third_party/blink/renderer/core/frame/dom_window.h" -#include "third_party/blink/renderer/core/frame/event_handler_registry.h" -#include "third_party/blink/renderer/core/frame/fullscreen_controller.h" -#include "third_party/blink/renderer/core/frame/local_dom_window.h" -#include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/core/frame/local_frame_client.h" -#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h" -#include "third_party/blink/renderer/core/frame/local_frame_view.h" -#include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h" -#include "third_party/blink/renderer/core/frame/remote_frame.h" -#include "third_party/blink/renderer/core/frame/resize_viewport_anchor.h" -#include "third_party/blink/renderer/core/frame/rotation_viewport_anchor.h" -#include "third_party/blink/renderer/core/frame/settings.h" -#include "third_party/blink/renderer/core/frame/viewport_data.h" -#include "third_party/blink/renderer/core/frame/visual_viewport.h" -#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h" -#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" -#include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h" -#include "third_party/blink/renderer/core/fullscreen/fullscreen.h" -#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h" -#include "third_party/blink/renderer/core/html/html_plugin_element.h" -#include "third_party/blink/renderer/core/html/plugin_document.h" -#include "third_party/blink/renderer/core/html_names.h" -#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h" -#include "third_party/blink/renderer/core/input/event_handler.h" -#include "third_party/blink/renderer/core/input/touch_action_util.h" -#include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h" -#include "third_party/blink/renderer/core/layout/layout_embedded_content.h" -#include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/text_autosizer.h" -#include "third_party/blink/renderer/core/loader/document_loader.h" -#include "third_party/blink/renderer/core/loader/frame_load_request.h" -#include "third_party/blink/renderer/core/loader/frame_loader.h" -#include "third_party/blink/renderer/core/loader/interactive_detector.h" -#include "third_party/blink/renderer/core/loader/no_state_prefetch_client.h" -#include "third_party/blink/renderer/core/page/chrome_client_impl.h" -#include "third_party/blink/renderer/core/page/context_menu_controller.h" -#include "third_party/blink/renderer/core/page/context_menu_provider.h" -#include "third_party/blink/renderer/core/page/focus_controller.h" -#include "third_party/blink/renderer/core/page/frame_tree.h" -#include "third_party/blink/renderer/core/page/link_highlight.h" -#include "third_party/blink/renderer/core/page/page.h" -#include "third_party/blink/renderer/core/page/page_popup_client.h" -#include "third_party/blink/renderer/core/page/pointer_lock_controller.h" -#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h" -#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h" -#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" -#include "third_party/blink/renderer/core/paint/timing/paint_timing.h" -#include "third_party/blink/renderer/core/paint/timing/paint_timing_detector.h" -#include "third_party/blink/renderer/core/probe/core_probes.h" -#include "third_party/blink/renderer/core/scroll/scroll_into_view_util.h" -#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h" -#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h" -#include "third_party/blink/renderer/core/timing/dom_window_performance.h" -#include "third_party/blink/renderer/core/timing/performance.h" -#include "third_party/blink/renderer/core/timing/window_performance.h" -#include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h" -#include "third_party/blink/renderer/platform/fonts/font_cache.h" -#include "third_party/blink/renderer/platform/fonts/generic_font_family_settings.h" -#include "third_party/blink/renderer/platform/graphics/image.h" -#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" -#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h" -#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h" -#include "third_party/blink/renderer/platform/instrumentation/histogram.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" -#include "third_party/blink/renderer/platform/instrumentation/use_counter.h" -#include "third_party/blink/renderer/platform/keyboard_codes.h" -#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" -#include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h" -#include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h" -#include "third_party/blink/renderer/platform/theme/web_theme_engine_helper.h" -#include "third_party/blink/renderer/platform/weborigin/known_ports.h" -#include "third_party/blink/renderer/platform/widget/widget_base.h" -#include "third_party/blink/renderer/platform/wtf/casting.h" -#include "third_party/icu/source/common/unicode/uscript.h" -#include "ui/base/ui_base_features.h" -#include "ui/gfx/geometry/skia_conversions.h" - -#if !BUILDFLAG(IS_MAC) -#include "skia/ext/legacy_display_globals.h" -#include "third_party/blink/public/platform/web_font_render_style.h" -#include "ui/gfx/font_render_params.h" -#endif - -#if BUILDFLAG(IS_WIN) -#include "third_party/blink/public/web/win/web_font_rendering.h" -#endif - -// Get rid of WTF's pow define so we can use std::pow. -#undef pow -#include // for std::pow - -#include "build/chromeos_buildflags.h" - -// The following constants control parameters for automated scaling of webpages -// (such as due to a double tap gesture or find in page etc.). These are -// experimentally determined. -static const int touchPointPadding = 32; -static const int nonUserInitiatedPointPadding = 11; -static const float minScaleDifference = 0.01f; -static const float doubleTapZoomContentDefaultMargin = 5; -static const float doubleTapZoomContentMinimumMargin = 2; -static constexpr base::TimeDelta kDoubleTapZoomAnimationDuration = - base::Milliseconds(250); -static const float doubleTapZoomAlreadyLegibleRatio = 1.2f; - -static constexpr base::TimeDelta kFindInPageAnimationDuration; - -// Constants for viewport anchoring on resize. -static const float viewportAnchorCoordX = 0.5f; -static const float viewportAnchorCoordY = 0; - -// Constants for zooming in on a focused text field. -static constexpr base::TimeDelta kScrollAndScaleAnimationDuration = - base::Milliseconds(200); -static const int minReadableCaretHeight = 16; -static const int minReadableCaretHeightForTextArea = 13; -static const float minScaleChangeToTriggerZoom = 1.5f; -static const float leftBoxRatio = 0.3f; -static const int caretPadding = 10; - -namespace blink { - -using mojom::blink::EffectiveConnectionType; - -// Historically, these values came from Webkit in -// WebKitLegacy/mac/WebView/WebView.mm (named MinimumZoomMultiplier and -// MaximumZoomMultiplier there). -const double WebView::kMinTextSizeMultiplier = 0.5; -const double WebView::kMaxTextSizeMultiplier = 3.0; - -// static -HashSet& WebViewImpl::AllInstances() { - DEFINE_STATIC_LOCAL(HashSet, all_instances, ()); - return all_instances; -} - -static bool g_should_use_external_popup_menus = false; - -void WebView::SetUseExternalPopupMenus(bool use_external_popup_menus) { - g_should_use_external_popup_menus = use_external_popup_menus; -} - -bool WebViewImpl::UseExternalPopupMenus() { - return g_should_use_external_popup_menus; -} - -namespace { - -class EmptyEventListener final : public NativeEventListener { - public: - void Invoke(ExecutionContext* execution_context, Event*) override {} -}; - -typedef void (*SetFontFamilyWrapper)(blink::WebSettings*, - const std::u16string&, - UScriptCode); - -void SetStandardFontFamilyWrapper(WebSettings* settings, - const std::u16string& font, - UScriptCode script) { - settings->SetStandardFontFamily(WebString::FromUTF16(font), script); -} - -void SetFixedFontFamilyWrapper(WebSettings* settings, - const std::u16string& font, - UScriptCode script) { - settings->SetFixedFontFamily(WebString::FromUTF16(font), script); -} - -void SetSerifFontFamilyWrapper(WebSettings* settings, - const std::u16string& font, - UScriptCode script) { - settings->SetSerifFontFamily(WebString::FromUTF16(font), script); -} - -void SetSansSerifFontFamilyWrapper(WebSettings* settings, - const std::u16string& font, - UScriptCode script) { - settings->SetSansSerifFontFamily(WebString::FromUTF16(font), script); -} - -void SetCursiveFontFamilyWrapper(WebSettings* settings, - const std::u16string& font, - UScriptCode script) { - settings->SetCursiveFontFamily(WebString::FromUTF16(font), script); -} - -void SetFantasyFontFamilyWrapper(WebSettings* settings, - const std::u16string& font, - UScriptCode script) { - settings->SetFantasyFontFamily(WebString::FromUTF16(font), script); -} - -void SetMathFontFamilyWrapper(WebSettings* settings, - const std::u16string& font, - UScriptCode script) { - settings->SetMathFontFamily(WebString::FromUTF16(font), script); -} - -// If |scriptCode| is a member of a family of "similar" script codes, returns -// the script code in that family that is used by WebKit for font selection -// purposes. For example, USCRIPT_KATAKANA_OR_HIRAGANA and USCRIPT_JAPANESE are -// considered equivalent for the purposes of font selection. WebKit uses the -// script code USCRIPT_KATAKANA_OR_HIRAGANA. So, if |scriptCode| is -// USCRIPT_JAPANESE, the function returns USCRIPT_KATAKANA_OR_HIRAGANA. WebKit -// uses different scripts than the ones in Chrome pref names because the version -// of ICU included on certain ports does not have some of the newer scripts. If -// |scriptCode| is not a member of such a family, returns |scriptCode|. -UScriptCode GetScriptForWebSettings(UScriptCode scriptCode) { - switch (scriptCode) { - case USCRIPT_HIRAGANA: - case USCRIPT_KATAKANA: - case USCRIPT_JAPANESE: - return USCRIPT_KATAKANA_OR_HIRAGANA; - case USCRIPT_KOREAN: - return USCRIPT_HANGUL; - default: - return scriptCode; - } -} - -void ApplyFontsFromMap(const web_pref::ScriptFontFamilyMap& map, - SetFontFamilyWrapper setter, - WebSettings* settings) { - for (auto& it : map) { - int32_t script = u_getPropertyValueEnum(UCHAR_SCRIPT, (it.first).c_str()); - if (script >= 0 && script < USCRIPT_CODE_LIMIT) { - UScriptCode code = static_cast(script); - (*setter)(settings, it.second, GetScriptForWebSettings(code)); - } - } -} - -void ApplyCommandLineToSettings(WebSettings* settings) { - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - - std::string touch_text_selection_strategy = - command_line.GetSwitchValueASCII(switches::kTouchTextSelectionStrategy); - if (touch_text_selection_strategy == - switches::kTouchTextSelectionStrategy_Character) { - settings->SetSelectionStrategy( - WebSettings::SelectionStrategyType::kCharacter); - } else if (touch_text_selection_strategy == - switches::kTouchTextSelectionStrategy_Direction) { - settings->SetSelectionStrategy( - WebSettings::SelectionStrategyType::kDirection); - } - - WebString network_quiet_timeout = WebString::FromUTF8( - command_line.GetSwitchValueASCII(switches::kNetworkQuietTimeout)); - if (!network_quiet_timeout.IsEmpty()) { - bool ok; - double network_quiet_timeout_seconds = - String(network_quiet_timeout).ToDouble(&ok); - if (ok) - settings->SetNetworkQuietTimeout(network_quiet_timeout_seconds); - } - - if (command_line.HasSwitch(switches::kBlinkSettings)) { - Vector blink_settings; - String command_line_settings = - command_line.GetSwitchValueASCII(switches::kBlinkSettings).c_str(); - command_line_settings.Split(",", blink_settings); - for (const String& setting : blink_settings) { - wtf_size_t pos = setting.find('='); - settings->SetFromStrings( - WebString(setting.Substring(0, pos)), - WebString(pos == kNotFound ? "" : setting.Substring(pos + 1))); - } - } -} - -ui::mojom::blink::WindowOpenDisposition NavigationPolicyToDisposition( - NavigationPolicy policy) { - switch (policy) { - case kNavigationPolicyDownload: - return ui::mojom::blink::WindowOpenDisposition::SAVE_TO_DISK; - case kNavigationPolicyCurrentTab: - return ui::mojom::blink::WindowOpenDisposition::CURRENT_TAB; - case kNavigationPolicyNewBackgroundTab: - return ui::mojom::blink::WindowOpenDisposition::NEW_BACKGROUND_TAB; - case kNavigationPolicyNewForegroundTab: - return ui::mojom::blink::WindowOpenDisposition::NEW_FOREGROUND_TAB; - case kNavigationPolicyNewWindow: - return ui::mojom::blink::WindowOpenDisposition::NEW_WINDOW; - case kNavigationPolicyNewPopup: - return ui::mojom::blink::WindowOpenDisposition::NEW_POPUP; - case kNavigationPolicyPictureInPicture: - return ui::mojom::blink::WindowOpenDisposition::NEW_PICTURE_IN_PICTURE; - } - NOTREACHED() << "Unexpected NavigationPolicy"; - return ui::mojom::blink::WindowOpenDisposition::IGNORE_ACTION; -} - -#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN) -SkFontHinting RendererPreferencesToSkiaHinting( - const blink::RendererPreferences& prefs) { -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) - if (!prefs.should_antialias_text) { - // When anti-aliasing is off, GTK maps all non-zero hinting settings to - // 'Normal' hinting so we do the same. Otherwise, folks who have 'Slight' - // hinting selected will see readable text in everything expect Chromium. - switch (prefs.hinting) { - case gfx::FontRenderParams::HINTING_NONE: - return SkFontHinting::kNone; - case gfx::FontRenderParams::HINTING_SLIGHT: - case gfx::FontRenderParams::HINTING_MEDIUM: - case gfx::FontRenderParams::HINTING_FULL: - return SkFontHinting::kNormal; - default: - NOTREACHED(); - return SkFontHinting::kNormal; - } - } -#endif - - switch (prefs.hinting) { - case gfx::FontRenderParams::HINTING_NONE: - return SkFontHinting::kNone; - case gfx::FontRenderParams::HINTING_SLIGHT: - return SkFontHinting::kSlight; - case gfx::FontRenderParams::HINTING_MEDIUM: - return SkFontHinting::kNormal; - case gfx::FontRenderParams::HINTING_FULL: - return SkFontHinting::kFull; - default: - NOTREACHED(); - return SkFontHinting::kNormal; - } -} -#endif // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN) - -} // namespace - -// WebView ---------------------------------------------------------------- - -WebView* WebView::Create( - WebViewClient* client, - bool is_hidden, - bool is_prerendering, - bool is_inside_portal, - absl::optional - fenced_frame_mode, - bool compositing_enabled, - bool widgets_never_composited, - WebView* opener, - CrossVariantMojoAssociatedReceiver - page_handle, - scheduler::WebAgentGroupScheduler& agent_group_scheduler, - const SessionStorageNamespaceId& session_storage_namespace_id, - absl::optional page_base_background_color, - const BrowsingContextGroupInfo& browsing_context_group_info) { - return WebViewImpl::Create( - client, - is_hidden ? mojom::blink::PageVisibilityState::kHidden - : mojom::blink::PageVisibilityState::kVisible, - is_prerendering, is_inside_portal, fenced_frame_mode, compositing_enabled, - widgets_never_composited, To(opener), std::move(page_handle), - agent_group_scheduler, session_storage_namespace_id, - std::move(page_base_background_color), browsing_context_group_info); -} - -WebViewImpl* WebViewImpl::Create( - WebViewClient* client, - mojom::blink::PageVisibilityState visibility, - bool is_prerendering, - bool is_inside_portal, - absl::optional - fenced_frame_mode, - bool compositing_enabled, - bool widgets_never_composited, - WebViewImpl* opener, - mojo::PendingAssociatedReceiver page_handle, - blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler, - const SessionStorageNamespaceId& session_storage_namespace_id, - absl::optional page_base_background_color, - const BrowsingContextGroupInfo& browsing_context_group_info) { - // Take a self-reference for WebViewImpl that is released by calling Close(), - // then return a raw pointer to the caller. - auto web_view = base::AdoptRef(new WebViewImpl( - client, visibility, is_prerendering, is_inside_portal, fenced_frame_mode, - compositing_enabled, widgets_never_composited, opener, - std::move(page_handle), agent_group_scheduler, - session_storage_namespace_id, std::move(page_base_background_color), - browsing_context_group_info)); - web_view->AddRef(); - return web_view.get(); -} - -size_t WebView::GetWebViewCount() { - return WebViewImpl::AllInstances().size(); -} - -void WebView::UpdateVisitedLinkState(uint64_t link_hash) { - Page::VisitedStateChanged(link_hash); -} - -void WebView::ResetVisitedLinkState(bool invalidate_visited_link_hashes) { - Page::AllVisitedStateChanged(invalidate_visited_link_hashes); -} - -void WebViewImpl::SetNoStatePrefetchClient( - WebNoStatePrefetchClient* no_state_prefetch_client) { - DCHECK(page_); - ProvideNoStatePrefetchClientTo(*page_, - MakeGarbageCollected( - *page_, no_state_prefetch_client)); -} - -void WebViewImpl::CloseWindowSoon() { - // Ask the RenderViewHost with a local main frame to initiate close. We - // could be called from deep in Javascript. If we ask the RenderViewHost to - // close now, the window could be closed before the JS finishes executing, - // thanks to nested message loops running and handling the resulting - // disconnecting `page_broadcast_`. So instead, post a message back to the - // message loop, which won't run until the JS is complete, and then the - // RouteCloseEvent/RequestClose request can be sent. - GetPage() - ->GetPageScheduler() - ->GetAgentGroupScheduler() - .DefaultTaskRunner() - ->PostTask(FROM_HERE, - WTF::BindOnce(&WebViewImpl::DoDeferredCloseWindowSoon, - weak_ptr_factory_.GetWeakPtr())); -} - -void WebViewImpl::DoDeferredCloseWindowSoon() { - // Have the browser process a close request. We should have either a - // |local_main_frame_host_remote_| or |remote_main_frame_host_remote_|. - // This method will not execute if Close has been called as WeakPtrs - // will be invalidated in Close. - if (GetPage()->MainFrame()->IsLocalFrame()) { - DCHECK(local_main_frame_host_remote_); - local_main_frame_host_remote_->RequestClose(); - } else { - DCHECK(remote_main_frame_host_remote_); - remote_main_frame_host_remote_->RouteCloseEvent(); - } -} - -WebViewImpl::WebViewImpl( - WebViewClient* client, - mojom::blink::PageVisibilityState visibility, - bool is_prerendering, - bool is_inside_portal, - absl::optional - fenced_frame_mode, - bool does_composite, - bool widgets_never_composited, - WebViewImpl* opener, - mojo::PendingAssociatedReceiver page_handle, - blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler, - const SessionStorageNamespaceId& session_storage_namespace_id, - absl::optional page_base_background_color, - const BrowsingContextGroupInfo& browsing_context_group_info) - : widgets_never_composited_(widgets_never_composited), - web_view_client_(client), - chrome_client_(MakeGarbageCollected(this)), - minimum_zoom_level_(PageZoomFactorToZoomLevel(kMinimumPageZoomFactor)), - maximum_zoom_level_(PageZoomFactorToZoomLevel(kMaximumPageZoomFactor)), - does_composite_(does_composite), - fullscreen_controller_(std::make_unique(this)), - page_base_background_color_( - page_base_background_color.value_or(SK_ColorWHITE)), - receiver_(this, - std::move(page_handle), - agent_group_scheduler.DefaultTaskRunner()), - session_storage_namespace_id_(session_storage_namespace_id), - web_agent_group_scheduler_(agent_group_scheduler) { - if (receiver_) { - // Typically, the browser process closes the corresponding peer handle - // to signal the renderer process to destroy `this`. In certain - // situations where the lifetime of `this` is not controlled by a - // corresponding browser-side `RenderViewHostImpl` (e.g. tests or - // printing), call `Close()` directly instead to delete `this`. - receiver_.set_disconnect_handler( - WTF::BindOnce(&WebViewImpl::MojoDisconnected, WTF::Unretained(this))); - } - if (!web_view_client_) - DCHECK(!does_composite_); - page_ = Page::CreateOrdinary(*chrome_client_, - opener ? opener->GetPage() : nullptr, - agent_group_scheduler.GetAgentGroupScheduler(), - browsing_context_group_info); - CoreInitializer::GetInstance().ProvideModulesToPage( - *page_, session_storage_namespace_id_); - - SetVisibilityState(visibility, /*is_initial_state=*/true); - page_->SetIsPrerendering(is_prerendering); - - // We pass this state to Page, but it's only used by the main frame in the - // page. - SetInsidePortal(is_inside_portal); - - if (fenced_frame_mode && features::IsFencedFramesEnabled()) { - page_->SetIsMainFrameFencedFrameRoot(); - page_->SetDeprecatedFencedFrameMode(*fenced_frame_mode); - } else { - // `fenced_frame_mode` should only be set if creating an MPArch - // fenced frame. - DCHECK(!fenced_frame_mode); - } - - // When not compositing, keep the Page in the loop so that it will paint all - // content into the root layer, as multiple layers can only be used when - // compositing them together later. - if (does_composite_) - page_->GetSettings().SetAcceleratedCompositingEnabled(true); - - dev_tools_emulator_ = MakeGarbageCollected(this); - - AllInstances().insert(this); - - resize_viewport_anchor_ = MakeGarbageCollected(*page_); - - // Ensure we have valid page scale constraints even if the embedder never - // changes defaults. - GetPageScaleConstraintsSet().ComputeFinalConstraints(); -} - -WebViewImpl::~WebViewImpl() { - DCHECK(!page_); -} - -WebDevToolsAgentImpl* WebViewImpl::MainFrameDevToolsAgentImpl() { - WebLocalFrameImpl* main_frame = MainFrameImpl(); - return main_frame ? main_frame->DevToolsAgentImpl() : nullptr; -} - -void WebViewImpl::SetTabKeyCyclesThroughElements(bool value) { - if (page_) - page_->SetTabKeyCyclesThroughElements(value); -} - -bool WebViewImpl::StartPageScaleAnimation(const gfx::Point& target_position, - bool use_anchor, - float new_scale, - base::TimeDelta duration) { - // PageScaleFactor is a property of the main frame only, and only exists when - // compositing. - DCHECK(MainFrameImpl()); - DCHECK(does_composite_); - - VisualViewport& visual_viewport = GetPage()->GetVisualViewport(); - DCHECK(visual_viewport.IsActiveViewport()); - - gfx::Point clamped_point = target_position; - if (!use_anchor) { - clamped_point = - visual_viewport.ClampDocumentOffsetAtScale(target_position, new_scale); - - // TODO(bokan): Why special case duration zero? PageScaleAnimation should - // work ok for that. - if (duration.is_zero()) { - SetPageScaleFactor(new_scale); - - LocalFrameView* view = MainFrameImpl()->GetFrameView(); - if (view && view->GetScrollableArea()) { - view->GetScrollableArea()->SetScrollOffset( - ScrollOffset(gfx::Vector2dF(clamped_point.OffsetFromOrigin())), - mojom::blink::ScrollType::kProgrammatic); - } - - return false; - } - } - if (use_anchor && new_scale == PageScaleFactor()) - return false; - - if (enable_fake_page_scale_animation_for_testing_) { - fake_page_scale_animation_target_position_ = target_position; - fake_page_scale_animation_use_anchor_ = use_anchor; - fake_page_scale_animation_page_scale_factor_ = new_scale; - } else { - MainFrameImpl()->FrameWidgetImpl()->StartPageScaleAnimation( - target_position, use_anchor, new_scale, duration); - } - return true; -} - -void WebViewImpl::EnableFakePageScaleAnimationForTesting(bool enable) { - enable_fake_page_scale_animation_for_testing_ = enable; - fake_page_scale_animation_target_position_ = gfx::Point(); - fake_page_scale_animation_use_anchor_ = false; - fake_page_scale_animation_page_scale_factor_ = 0; -} - -void WebViewImpl::AcceptLanguagesChanged() { - FontCache::AcceptLanguagesChanged( - String::FromUTF8(renderer_preferences_.accept_languages)); - - if (!GetPage()) - return; - - GetPage()->AcceptLanguagesChanged(); -} - -gfx::Rect WebViewImpl::WidenRectWithinPageBounds(const gfx::Rect& source, - int target_margin, - int minimum_margin) { - // Caller should guarantee that the main frame exists and is local. - DCHECK(MainFrame()); - DCHECK(MainFrame()->IsWebLocalFrame()); - gfx::Size max_size = MainFrame()->ToWebLocalFrame()->DocumentSize(); - gfx::PointF scroll_offset = MainFrame()->ToWebLocalFrame()->GetScrollOffset(); - - int left_margin = target_margin; - int right_margin = target_margin; - - const int absolute_source_x = source.x() + scroll_offset.x(); - if (left_margin > absolute_source_x) { - left_margin = absolute_source_x; - right_margin = std::max(left_margin, minimum_margin); - } - - const int maximum_right_margin = - max_size.width() - (source.width() + absolute_source_x); - if (right_margin > maximum_right_margin) { - right_margin = maximum_right_margin; - left_margin = std::min(left_margin, std::max(right_margin, minimum_margin)); - } - - const int new_width = source.width() + left_margin + right_margin; - const int new_x = source.x() - left_margin; - - DCHECK_GE(new_width, 0); - DCHECK_LE(scroll_offset.x() + new_x + new_width, max_size.width()); - - return gfx::Rect(new_x, source.y(), new_width, source.height()); -} - -float WebViewImpl::MaximumLegiblePageScale() const { - // Pages should be as legible as on desktop when at dpi scale, so no - // need to zoom in further when automatically determining zoom level - // (after double tap, find in page, etc), though the user should still - // be allowed to manually pinch zoom in further if they desire. - if (GetPage()) { - return maximum_legible_scale_ * - GetPage()->GetSettings().GetAccessibilityFontScaleFactor(); - } - return maximum_legible_scale_; -} - -void WebViewImpl::ComputeScaleAndScrollForBlockRect( - const gfx::Point& hit_point_in_root_frame, - const gfx::Rect& block_rect_in_root_frame, - float padding, - float default_scale_when_already_legible, - float& scale, - gfx::Point& scroll) { - DCHECK(GetPage()->GetVisualViewport().IsActiveViewport()); - scale = PageScaleFactor(); - scroll = gfx::Point(); - - gfx::Rect rect = block_rect_in_root_frame; - - if (!rect.IsEmpty()) { - float default_margin = doubleTapZoomContentDefaultMargin; - float minimum_margin = doubleTapZoomContentMinimumMargin; - // We want the margins to have the same physical size, which means we - // need to express them in post-scale size. To do that we'd need to know - // the scale we're scaling to, but that depends on the margins. Instead - // we express them as a fraction of the target rectangle: this will be - // correct if we end up fully zooming to it, and won't matter if we - // don't. - rect = WidenRectWithinPageBounds( - rect, static_cast(default_margin * rect.width() / size_.width()), - static_cast(minimum_margin * rect.width() / size_.width())); - // Fit block to screen, respecting limits. - scale = static_cast(size_.width()) / rect.width(); - scale = std::min(scale, MaximumLegiblePageScale()); - if (PageScaleFactor() < default_scale_when_already_legible) - scale = std::max(scale, default_scale_when_already_legible); - scale = ClampPageScaleFactorToLimits(scale); - } - - // FIXME: If this is being called for auto zoom during find in page, - // then if the user manually zooms in it'd be nice to preserve the - // relative increase in zoom they caused (if they zoom out then it's ok - // to zoom them back in again). This isn't compatible with our current - // double-tap zoom strategy (fitting the containing block to the screen) - // though. - - float screen_width = size_.width() / scale; - float screen_height = size_.height() / scale; - - // Scroll to vertically align the block. - if (rect.height() < screen_height) { - // Vertically center short blocks. - rect.Offset(0, -0.5 * (screen_height - rect.height())); - } else { - // Ensure position we're zooming to (+ padding) isn't off the bottom of - // the screen. - rect.set_y(std::max( - rect.y(), hit_point_in_root_frame.y() + padding - screen_height)); - } // Otherwise top align the block. - - // Do the same thing for horizontal alignment. - if (rect.width() < screen_width) { - rect.Offset(-0.5 * (screen_width - rect.width()), 0); - } else { - rect.set_x(std::max( - rect.x(), hit_point_in_root_frame.x() + padding - screen_width)); - } - scroll.set_x(rect.x()); - scroll.set_y(rect.y()); - - scale = ClampPageScaleFactorToLimits(scale); - scroll = MainFrameImpl()->GetFrameView()->RootFrameToDocument(scroll); - scroll = - GetPage()->GetVisualViewport().ClampDocumentOffsetAtScale(scroll, scale); -} - -static Node* FindLinkHighlightAncestor(Node* node) { - // Go up the tree to find the node that defines a mouse cursor style - while (node) { - const LinkHighlightCandidate type = node->IsLinkHighlightCandidate(); - if (type == LinkHighlightCandidate::kYes) - return node; - if (type == LinkHighlightCandidate::kNo) - return nullptr; - node = LayoutTreeBuilderTraversal::Parent(*node); - } - return nullptr; -} - -// This is for tap (link) highlight and is tested in -// link_highlight_impl_test.cc. -Node* WebViewImpl::BestTapNode( - const GestureEventWithHitTestResults& targeted_tap_event) { - TRACE_EVENT0("input", "WebViewImpl::bestTapNode"); - - Page* page = page_.Get(); - if (!page || !page->MainFrame()) - return nullptr; - - Node* best_touch_node = targeted_tap_event.GetHitTestResult().InnerNode(); - if (!best_touch_node) - return nullptr; - - // We might hit something like an image map that has no layoutObject on it - // Walk up the tree until we have a node with an attached layoutObject - while (!best_touch_node->GetLayoutObject()) { - best_touch_node = LayoutTreeBuilderTraversal::Parent(*best_touch_node); - if (!best_touch_node) - return nullptr; - } - - // Editable nodes should not be highlighted (e.g., ) - if (IsEditable(*best_touch_node)) - return nullptr; - - Node* hand_cursor_ancestor = FindLinkHighlightAncestor(best_touch_node); - // We show a highlight on tap only when the current node shows a hand cursor - if (!hand_cursor_ancestor) { - return nullptr; - } - - // We should pick the largest enclosing node with hand cursor set. We do this - // by first jumping up to the closest ancestor with hand cursor set. Then we - // locate the next ancestor up in the the tree and repeat the jumps as long as - // the node has hand cursor set. - do { - best_touch_node = hand_cursor_ancestor; - hand_cursor_ancestor = FindLinkHighlightAncestor( - LayoutTreeBuilderTraversal::Parent(*best_touch_node)); - } while (hand_cursor_ancestor); - - // This happens in cases like: - //
Text
. - // The text node inherits cursor: pointer and the div doesn't have a - // LayoutObject, so |best_touch_node| is the text node here. We should not - // return the text node because it can't have touch actions. - if (best_touch_node->IsTextNode()) - return nullptr; - - return best_touch_node; -} - -void WebViewImpl::EnableTapHighlightAtPoint( - const GestureEventWithHitTestResults& targeted_tap_event) { - DCHECK(MainFrameImpl()); - Node* touch_node = BestTapNode(targeted_tap_event); - GetPage()->GetLinkHighlight().SetTapHighlight(touch_node); - MainFrameWidget()->UpdateLifecycle(WebLifecycleUpdate::kAll, - DocumentUpdateReason::kTapHighlight); -} - -void WebViewImpl::AnimateDoubleTapZoom(const gfx::Point& point_in_root_frame, - const gfx::Rect& rect_to_zoom) { - DCHECK(MainFrameImpl()); - - float scale; - gfx::Point scroll; - - ComputeScaleAndScrollForBlockRect( - point_in_root_frame, rect_to_zoom, touchPointPadding, - MinimumPageScaleFactor() * doubleTapZoomAlreadyLegibleRatio, scale, - scroll); - - bool still_at_previous_double_tap_scale = - (PageScaleFactor() == double_tap_zoom_page_scale_factor_ && - double_tap_zoom_page_scale_factor_ != MinimumPageScaleFactor()) || - double_tap_zoom_pending_; - - bool scale_unchanged = fabs(PageScaleFactor() - scale) < minScaleDifference; - bool should_zoom_out = rect_to_zoom.IsEmpty() || scale_unchanged || - still_at_previous_double_tap_scale; - - bool is_animating; - - if (should_zoom_out) { - scale = MinimumPageScaleFactor(); - gfx::Point target_position = - MainFrameImpl()->GetFrameView()->RootFrameToDocument( - gfx::Point(point_in_root_frame.x(), point_in_root_frame.y())); - is_animating = StartPageScaleAnimation(target_position, true, scale, - kDoubleTapZoomAnimationDuration); - } else { - is_animating = StartPageScaleAnimation(scroll, false, scale, - kDoubleTapZoomAnimationDuration); - } - - // TODO(dglazkov): The only reason why we're using isAnimating and not just - // checking for layer_tree_view_->HasPendingPageScaleAnimation() is because of - // fake page scale animation plumbing for testing, which doesn't actually - // initiate a page scale animation. - if (is_animating) { - double_tap_zoom_page_scale_factor_ = scale; - double_tap_zoom_pending_ = true; - } -} - -void WebViewImpl::ZoomToFindInPageRect(const gfx::Rect& rect_in_root_frame) { - DCHECK(MainFrameImpl()); - - gfx::Rect block_bounds = - MainFrameImpl()->FrameWidgetImpl()->ComputeBlockBound( - gfx::Point(rect_in_root_frame.x() + rect_in_root_frame.width() / 2, - rect_in_root_frame.y() + rect_in_root_frame.height() / 2), - true); - - if (block_bounds.IsEmpty()) { - // Keep current scale (no need to scroll as x,y will normally already - // be visible). FIXME: Revisit this if it isn't always true. - return; - } - - float scale; - gfx::Point scroll; - - ComputeScaleAndScrollForBlockRect(rect_in_root_frame.origin(), block_bounds, - nonUserInitiatedPointPadding, - MinimumPageScaleFactor(), scale, scroll); - - StartPageScaleAnimation(scroll, false, scale, kFindInPageAnimationDuration); -} - -#if !BUILDFLAG(IS_MAC) -// Mac has no way to open a context menu based on a keyboard event. -WebInputEventResult WebViewImpl::SendContextMenuEvent() { - // The contextMenuController() holds onto the last context menu that was - // popped up on the page until a new one is created. We need to clear - // this menu before propagating the event through the DOM so that we can - // detect if we create a new menu for this event, since we won't create - // a new menu if the DOM swallows the event and the defaultEventHandler does - // not run. - GetPage()->GetContextMenuController().ClearContextMenu(); - - { - ContextMenuAllowedScope scope; - Frame* focused_frame = GetPage()->GetFocusController().FocusedOrMainFrame(); - auto* focused_local_frame = DynamicTo(focused_frame); - if (!focused_local_frame) - return WebInputEventResult::kNotHandled; - // Firefox reveal focus based on "keydown" event but not "contextmenu" - // event, we match FF. - if (Element* focused_element = - focused_local_frame->GetDocument()->FocusedElement()) - focused_element->scrollIntoViewIfNeeded(); - return focused_local_frame->GetEventHandler().ShowNonLocatedContextMenu( - nullptr, kMenuSourceKeyboard); - } -} -#else -WebInputEventResult WebViewImpl::SendContextMenuEvent() { - return WebInputEventResult::kNotHandled; -} -#endif - -WebPagePopupImpl* WebViewImpl::OpenPagePopup(PagePopupClient* client) { - DCHECK(client); - - // This guarantees there is never more than 1 PagePopup active at a time. - CancelPagePopup(); - DCHECK(!page_popup_); - - LocalFrame* opener_frame = client->OwnerElement().GetDocument().GetFrame(); - WebLocalFrameImpl* web_opener_frame = - WebLocalFrameImpl::FromFrame(opener_frame); - - mojo::PendingAssociatedRemote widget; - mojo::PendingAssociatedReceiver widget_receiver = - widget.InitWithNewEndpointAndPassReceiver(); - - mojo::PendingAssociatedRemote widget_host; - mojo::PendingAssociatedReceiver - widget_host_receiver = widget_host.InitWithNewEndpointAndPassReceiver(); - - mojo::PendingAssociatedRemote - popup_widget_host; - mojo::PendingAssociatedReceiver - popup_widget_host_receiver = - popup_widget_host.InitWithNewEndpointAndPassReceiver(); - - opener_frame->GetLocalFrameHostRemote().CreateNewPopupWidget( - std::move(popup_widget_host_receiver), std::move(widget_host_receiver), - std::move(widget)); - WebFrameWidgetImpl* opener_widget = web_opener_frame->LocalRootFrameWidget(); - - AgentGroupScheduler& agent_group_scheduler = - opener_frame->GetPage()->GetPageScheduler()->GetAgentGroupScheduler(); - // The returned WebPagePopup is self-referencing, so the pointer here is not - // an owning pointer. It is de-referenced by the PopupWidgetHost disconnecting - // and calling Close(). - page_popup_ = WebPagePopupImpl::Create( - std::move(popup_widget_host), std::move(widget_host), - std::move(widget_receiver), this, agent_group_scheduler, - opener_widget->GetOriginalScreenInfos(), client); - EnablePopupMouseWheelEventListener(web_opener_frame->LocalRoot()); - return page_popup_.get(); -} - -void WebViewImpl::CancelPagePopup() { - if (page_popup_) - page_popup_->Cancel(); -} - -void WebViewImpl::ClosePagePopup(PagePopup* popup) { - DCHECK(popup); - auto* popup_impl = To(popup); - DCHECK_EQ(page_popup_.get(), popup_impl); - if (page_popup_.get() != popup_impl) - return; - page_popup_->ClosePopup(); -} - -void WebViewImpl::CleanupPagePopup() { - page_popup_ = nullptr; - DisablePopupMouseWheelEventListener(); -} - -void WebViewImpl::UpdatePagePopup() { - if (page_popup_) - page_popup_->Update(); -} - -void WebViewImpl::EnablePopupMouseWheelEventListener( - WebLocalFrameImpl* local_root) { - DCHECK(!popup_mouse_wheel_event_listener_); - Document* document = local_root->GetDocument(); - DCHECK(document); - // We register an empty event listener, EmptyEventListener, so that mouse - // wheel events get sent to the WebView. - popup_mouse_wheel_event_listener_ = - MakeGarbageCollected(); - document->addEventListener(event_type_names::kMousewheel, - popup_mouse_wheel_event_listener_, false); - local_root_with_empty_mouse_wheel_listener_ = local_root; -} - -void WebViewImpl::DisablePopupMouseWheelEventListener() { - // TODO(kenrb): Concerns the same as in enablePopupMouseWheelEventListener. - // See https://crbug.com/566130 - DCHECK(popup_mouse_wheel_event_listener_); - Document* document = - local_root_with_empty_mouse_wheel_listener_->GetDocument(); - DCHECK(document); - // Document may have already removed the event listener, for instance, due - // to a navigation, but remove it anyway. - document->removeEventListener(event_type_names::kMousewheel, - popup_mouse_wheel_event_listener_.Release(), - false); - local_root_with_empty_mouse_wheel_listener_ = nullptr; -} - -LocalDOMWindow* WebViewImpl::PagePopupWindow() const { - return page_popup_ ? page_popup_->Window() : nullptr; -} - -Frame* WebViewImpl::FocusedCoreFrame() const { - Page* page = page_.Get(); - return page ? page->GetFocusController().FocusedOrMainFrame() : nullptr; -} - -// WebWidget ------------------------------------------------------------------ - -void WebViewImpl::Close() { - // Closership is a single relationship, so only 1 call to Close() should - // occur. - CHECK(page_); - DCHECK(AllInstances().Contains(this)); - AllInstances().erase(this); - - // Ensure if we have a page popup we cancel it immediately as we do not - // want page popups to re-enter WebViewImpl during our shutdown. - CancelPagePopup(); - - // Invalidate any weak ptrs as we are starting to shutdown. - weak_ptr_factory_.InvalidateWeakPtrs(); - receiver_.reset(); - - // Initiate shutdown for the entire frameset. This will cause a lot of - // notifications to be sent. This will detach all frames in this WebView's - // frame tree. - page_->WillBeDestroyed(); - page_.Clear(); - - if (web_view_client_) - web_view_client_->OnDestruct(); - - // Reset the delegate to prevent notifications being sent as we're being - // deleted. - web_view_client_ = nullptr; - - for (auto& observer : observers_) - observer.WebViewDestroyed(); - - Release(); // Balances a reference acquired in WebView::Create -} - -gfx::Size WebViewImpl::Size() { - return size_; -} - -void WebViewImpl::ResizeVisualViewport(const gfx::Size& new_size) { - GetPage()->GetVisualViewport().SetSize(new_size); - GetPage()->GetVisualViewport().ClampToBoundaries(); -} - -void WebViewImpl::DidFirstVisuallyNonEmptyPaint() { - DCHECK(MainFrameImpl()); - local_main_frame_host_remote_->DidFirstVisuallyNonEmptyPaint(); -} - -void WebViewImpl::UpdateICBAndResizeViewport( - const gfx::Size& visible_viewport_size) { - // We'll keep the initial containing block size from changing when the top - // controls hide so that the ICB will always be the same size as the - // viewport with the browser controls shown. - gfx::Size icb_size = size_; - if (GetBrowserControls().PermittedState() == - cc::BrowserControlsState::kBoth && - !GetBrowserControls().ShrinkViewport()) { - icb_size.Enlarge(0, -(GetBrowserControls().TotalHeight() - - GetBrowserControls().TotalMinHeight())); - } - - GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(icb_size); - - UpdatePageDefinedViewportConstraints(MainFrameImpl() - ->GetFrame() - ->GetDocument() - ->GetViewportData() - .GetViewportDescription()); - UpdateMainFrameLayoutSize(); - - GetPage()->GetVisualViewport().SetSize(visible_viewport_size); - - if (MainFrameImpl()->GetFrameView()) { - if (!MainFrameImpl()->GetFrameView()->NeedsLayout()) - resize_viewport_anchor_->ResizeFrameView(MainFrameSize()); - } - - // The boundaries are not properly established until after the frame view is - // also resized, as demonstrated by - // VisualViewportTest.TestBrowserControlsAdjustmentAndResize. - GetPage()->GetVisualViewport().ClampToBoundaries(); -} - -void WebViewImpl::UpdateBrowserControlsConstraint( - cc::BrowserControlsState constraint) { - cc::BrowserControlsState old_permitted_state = - GetBrowserControls().PermittedState(); - - GetBrowserControls().UpdateConstraintsAndState( - constraint, cc::BrowserControlsState::kBoth); - - // If the controls are going from a locked hidden to unlocked state, or vice - // versa, the ICB size needs to change but we can't rely on getting a - // WebViewImpl::resize since the top controls shown state may not have - // changed. - if ((old_permitted_state == cc::BrowserControlsState::kHidden && - constraint == cc::BrowserControlsState::kBoth) || - (old_permitted_state == cc::BrowserControlsState::kBoth && - constraint == cc::BrowserControlsState::kHidden)) { - UpdateICBAndResizeViewport(GetPage()->GetVisualViewport().Size()); - } -} - -void WebViewImpl::DidUpdateBrowserControls() { - // BrowserControls are a feature whereby the browser can introduce an - // interactable element [e.g. search box] that grows/shrinks in height as the - // user scrolls the web contents. - // - // This method is called by the BrowserControls class to let the compositor - // know that the browser controls have been updated. This is only relevant if - // the main frame is local because BrowserControls only affects the main - // frame's viewport, and are only affected by main frame scrolling. - // - // The relevant state is stored on the BrowserControls object even if the main - // frame is remote. If the main frame becomes local, the state will be - // restored by the first commit, since the state is checked in every call to - // ApplyScrollAndScale(). - WebLocalFrameImpl* main_frame = MainFrameImpl(); - if (!main_frame || !main_frame->IsOutermostMainFrame()) - return; - - WebFrameWidgetImpl* widget = main_frame->LocalRootFrameWidget(); - widget->SetBrowserControlsShownRatio(GetBrowserControls().TopShownRatio(), - GetBrowserControls().BottomShownRatio()); - widget->SetBrowserControlsParams(GetBrowserControls().Params()); - - VisualViewport& visual_viewport = GetPage()->GetVisualViewport(); - DCHECK(visual_viewport.IsActiveViewport()); - - { - // This object will save the current visual viewport offset w.r.t. the - // document and restore it when the object goes out of scope. It's - // needed since the browser controls adjustment will change the maximum - // scroll offset and we may need to reposition them to keep the user's - // apparent position unchanged. - ResizeViewportAnchor::ResizeScope resize_scope(*resize_viewport_anchor_); - - visual_viewport.SetBrowserControlsAdjustment( - GetBrowserControls().UnreportedSizeAdjustment()); - } -} - -BrowserControls& WebViewImpl::GetBrowserControls() { - return GetPage()->GetBrowserControls(); -} - -void WebViewImpl::ResizeViewWhileAnchored( - cc::BrowserControlsParams params, - const gfx::Size& visible_viewport_size) { - DCHECK(MainFrameImpl()); - - bool old_viewport_shrink = GetBrowserControls().ShrinkViewport(); - - GetBrowserControls().SetParams(params); - - if (old_viewport_shrink != GetBrowserControls().ShrinkViewport()) - MainFrameImpl()->GetFrameView()->DynamicViewportUnitsChanged(); - - { - // Avoids unnecessary invalidations while various bits of state in - // TextAutosizer are updated. - TextAutosizer::DeferUpdatePageInfo defer_update_page_info(GetPage()); - LocalFrameView* frame_view = MainFrameImpl()->GetFrameView(); - gfx::Size old_size = frame_view->Size(); - UpdateICBAndResizeViewport(visible_viewport_size); - gfx::Size new_size = frame_view->Size(); - frame_view->MarkFixedPositionObjectsForLayout( - old_size.width() != new_size.width(), - old_size.height() != new_size.height()); - } - - fullscreen_controller_->UpdateSize(); - - if (!scoped_defer_main_frame_update_) { - // Page scale constraints may need to be updated; running layout now will - // do that. - MainFrameWidget()->UpdateLifecycle(WebLifecycleUpdate::kLayout, - DocumentUpdateReason::kSizeChange); - } -} - -void WebViewImpl::ResizeWithBrowserControls( - const gfx::Size& new_size, - float top_controls_height, - float bottom_controls_height, - bool browser_controls_shrink_layout) { - ResizeWithBrowserControls( - new_size, new_size, - {top_controls_height, GetBrowserControls().TopMinHeight(), - bottom_controls_height, GetBrowserControls().BottomMinHeight(), - GetBrowserControls().AnimateHeightChanges(), - browser_controls_shrink_layout}); -} - -void WebViewImpl::ResizeWithBrowserControls( - const gfx::Size& main_frame_widget_size, - const gfx::Size& visible_viewport_size, - cc::BrowserControlsParams browser_controls_params) { - if (should_auto_resize_) { - // When auto-resizing only the viewport size comes from the browser, while - // the widget size is determined in the renderer. - ResizeVisualViewport(visible_viewport_size); - return; - } - - if (size_ == main_frame_widget_size && - GetPage()->GetVisualViewport().Size() == visible_viewport_size && - GetBrowserControls().Params() == browser_controls_params) - return; - - if (GetPage()->MainFrame() && !GetPage()->MainFrame()->IsLocalFrame()) { - // Viewport resize for a remote main frame does not require any - // particular action, but the state needs to reflect the correct size - // so that it can be used for initialization if the main frame gets - // swapped to a LocalFrame at a later time. - size_ = main_frame_widget_size; - GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(size_); - GetPage()->GetVisualViewport().SetSize(size_); - GetPage()->GetBrowserControls().SetParams(browser_controls_params); - return; - } - - WebLocalFrameImpl* main_frame = MainFrameImpl(); - if (!main_frame) - return; - - LocalFrameView* view = main_frame->GetFrameView(); - if (!view) - return; - - VisualViewport& visual_viewport = GetPage()->GetVisualViewport(); - - bool is_rotation = - GetPage()->GetSettings().GetMainFrameResizesAreOrientationChanges() && - size_.width() && ContentsSize().width() && - main_frame_widget_size.width() != size_.width() && - !fullscreen_controller_->IsFullscreenOrTransitioning(); - size_ = main_frame_widget_size; - - if (!main_frame->IsOutermostMainFrame()) { - // Anchoring should not be performed from embedded frames (not even - // portals) as anchoring should only be performed when the size/orientation - // is user controlled. - ResizeViewWhileAnchored(browser_controls_params, visible_viewport_size); - } else if (is_rotation) { - gfx::PointF viewport_anchor_coords(viewportAnchorCoordX, - viewportAnchorCoordY); - RotationViewportAnchor anchor(*view, visual_viewport, - viewport_anchor_coords, - GetPageScaleConstraintsSet()); - ResizeViewWhileAnchored(browser_controls_params, visible_viewport_size); - } else { - DCHECK(visual_viewport.IsActiveViewport()); - ResizeViewportAnchor::ResizeScope resize_scope(*resize_viewport_anchor_); - ResizeViewWhileAnchored(browser_controls_params, visible_viewport_size); - } - - // TODO(bokan): This will send a resize event even if the innerHeight on the - // page didn't change (e.g. virtual keyboard causes resize of only visual - // viewport). Lets remove this and have the frame send this event when its - // frame rect is resized (as noted by the ancient FIXME inside this method). - // https://crbug.com/1353728. - SendResizeEventForMainFrame(); -} - -void WebViewImpl::Resize(const gfx::Size& new_size) { - if (should_auto_resize_ || size_ == new_size) - return; - - ResizeWithBrowserControls(new_size, GetBrowserControls().TopHeight(), - GetBrowserControls().BottomHeight(), - GetBrowserControls().ShrinkViewport()); -} - -void WebViewImpl::SetScreenOrientationOverrideForTesting( - absl::optional orientation) { - screen_orientation_override_ = orientation; - - // Since we updated the override value, notify all widgets. - for (WebFrame* frame = MainFrame(); frame; frame = frame->TraverseNext()) { - if (frame->IsWebLocalFrame()) { - if (WebFrameWidgetImpl* widget = static_cast( - frame->ToWebLocalFrame()->FrameWidget())) { - widget->UpdateScreenInfo(widget->GetScreenInfos()); - } - } - } -} - -void WebViewImpl::SetWindowRectSynchronouslyForTesting( - const gfx::Rect& new_window_rect) { - web_widget_->SetWindowRectSynchronouslyForTesting(new_window_rect); -} - -absl::optional -WebViewImpl::ScreenOrientationOverride() { - return screen_orientation_override_; -} - -void WebViewImpl::DidEnterFullscreen() { - fullscreen_controller_->DidEnterFullscreen(); -} - -void WebViewImpl::DidExitFullscreen() { - fullscreen_controller_->DidExitFullscreen(); -} - -void WebViewImpl::SetMainFrameViewWidget(WebFrameWidgetImpl* widget) { - DCHECK(!widget || widget->ForMainFrame()); - web_widget_ = widget; -} - -void WebViewImpl::SetMouseOverURL(const KURL& url) { - mouse_over_url_ = url; - UpdateTargetURL(mouse_over_url_, focus_url_); -} - -void WebViewImpl::SetKeyboardFocusURL(const KURL& url) { - focus_url_ = url; - UpdateTargetURL(focus_url_, mouse_over_url_); -} - -WebFrameWidgetImpl* WebViewImpl::MainFrameViewWidget() { - return web_widget_; -} - -void WebViewImpl::PaintContent(cc::PaintCanvas* canvas, const gfx::Rect& rect) { - // This should only be used when compositing is not being used for this - // WebView, and it is painting into the recording of its parent. - DCHECK(!does_composite_); - // Non-composited WebViews always have a local main frame. - DCHECK(MainFrameImpl()); - - if (rect.IsEmpty()) - return; - - LocalFrameView& main_view = *MainFrameImpl()->GetFrame()->View(); - DCHECK(main_view.GetLayoutView()->GetDocument().Lifecycle().GetState() == - DocumentLifecycle::kPaintClean); - - auto* builder = MakeGarbageCollected(); - main_view.PaintOutsideOfLifecycleWithThrottlingAllowed( - builder->Context(), PaintFlag::kNoFlag, CullRect(rect)); - // Don't bother to save/restore here as the caller is expecting the canvas - // to be modified and take care of it. - canvas->clipRect(gfx::RectToSkRect(rect)); - builder->EndRecording(*canvas, main_view.GetLayoutView() - ->FirstFragment() - .LocalBorderBoxProperties() - .Unalias()); -} - -// static -void WebView::ApplyWebPreferences(const web_pref::WebPreferences& prefs, - WebView* web_view) { - WebViewImpl* web_view_impl = To(web_view); - WebSettings* settings = web_view->GetSettings(); - ApplyFontsFromMap(prefs.standard_font_family_map, - SetStandardFontFamilyWrapper, settings); - ApplyFontsFromMap(prefs.fixed_font_family_map, SetFixedFontFamilyWrapper, - settings); - ApplyFontsFromMap(prefs.serif_font_family_map, SetSerifFontFamilyWrapper, - settings); - ApplyFontsFromMap(prefs.sans_serif_font_family_map, - SetSansSerifFontFamilyWrapper, settings); - ApplyFontsFromMap(prefs.cursive_font_family_map, SetCursiveFontFamilyWrapper, - settings); - ApplyFontsFromMap(prefs.fantasy_font_family_map, SetFantasyFontFamilyWrapper, - settings); - ApplyFontsFromMap(prefs.math_font_family_map, SetMathFontFamilyWrapper, - settings); - settings->SetDefaultFontSize(prefs.default_font_size); - settings->SetDefaultFixedFontSize(prefs.default_fixed_font_size); - settings->SetMinimumFontSize(prefs.minimum_font_size); - settings->SetMinimumLogicalFontSize(prefs.minimum_logical_font_size); - settings->SetDefaultTextEncodingName( - WebString::FromASCII(prefs.default_encoding)); - settings->SetJavaScriptEnabled(prefs.javascript_enabled); - settings->SetWebSecurityEnabled(prefs.web_security_enabled); - settings->SetLoadsImagesAutomatically(prefs.loads_images_automatically); - settings->SetImagesEnabled(prefs.images_enabled); - settings->SetPluginsEnabled(prefs.plugins_enabled); - settings->SetDOMPasteAllowed(prefs.dom_paste_enabled); - settings->SetTextAreasAreResizable(prefs.text_areas_are_resizable); - settings->SetAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows); - settings->SetDownloadableBinaryFontsEnabled(prefs.remote_fonts_enabled); - settings->SetJavaScriptCanAccessClipboard( - prefs.javascript_can_access_clipboard); - settings->SetDNSPrefetchingEnabled(prefs.dns_prefetching_enabled); - blink::WebNetworkStateNotifier::SetSaveDataEnabled(prefs.data_saver_enabled); - settings->SetLocalStorageEnabled(prefs.local_storage_enabled); - settings->SetSyncXHRInDocumentsEnabled(prefs.sync_xhr_in_documents_enabled); - settings->SetTargetBlankImpliesNoOpenerEnabledWillBeRemoved( - prefs.target_blank_implies_no_opener_enabled_will_be_removed); - settings->SetAllowNonEmptyNavigatorPlugins( - prefs.allow_non_empty_navigator_plugins); - RuntimeEnabledFeatures::SetDatabaseEnabled(prefs.databases_enabled); - settings->SetShouldProtectAgainstIpcFlooding( - !prefs.disable_ipc_flooding_protection); - settings->SetHyperlinkAuditingEnabled(prefs.hyperlink_auditing_enabled); - settings->SetCookieEnabled(prefs.cookie_enabled); - settings->SetNavigateOnDragDrop(prefs.navigate_on_drag_drop); - settings->SetThreadedScrollingEnabled(prefs.threaded_scrolling_enabled); - - // By default, allow_universal_access_from_file_urls is set to false and thus - // we mitigate attacks from local HTML files by not granting file:// URLs - // universal access. Only test shell will enable this. - settings->SetAllowUniversalAccessFromFileURLs( - prefs.allow_universal_access_from_file_urls); - settings->SetAllowFileAccessFromFileURLs( - prefs.allow_file_access_from_file_urls); - - settings->SetWebGL1Enabled(prefs.webgl1_enabled); - settings->SetWebGL2Enabled(prefs.webgl2_enabled); - - // Enable WebGL errors to the JS console if requested. - settings->SetWebGLErrorsToConsoleEnabled( - prefs.webgl_errors_to_console_enabled); - - settings->SetHideScrollbars(prefs.hide_scrollbars); - - RuntimeEnabledFeatures::SetWebKitScrollbarStylingEnabled( - prefs.enable_webkit_scrollbar_styling); - - // Enable gpu-accelerated 2d canvas if requested on the command line. - RuntimeEnabledFeatures::SetAccelerated2dCanvasEnabled( - prefs.accelerated_2d_canvas_enabled); - - RuntimeEnabledFeatures::SetCanvas2dLayersEnabled( - prefs.canvas_2d_layers_enabled); - - // Disable antialiasing for 2d canvas if requested on the command line. - settings->SetAntialiased2dCanvasEnabled( - !prefs.antialiased_2d_canvas_disabled); - - // Disable antialiasing of clips for 2d canvas if requested on the command - // line. - settings->SetAntialiasedClips2dCanvasEnabled( - prefs.antialiased_clips_2d_canvas_enabled); - - // Tabs to link is not part of the settings. WebCore calls - // ChromeClient::tabsToLinks which is part of the glue code. - web_view_impl->SetTabsToLinks(prefs.tabs_to_links); - - DCHECK(!(web_view_impl->IsFencedFrameRoot() && - prefs.allow_running_insecure_content)); - settings->SetAllowRunningOfInsecureContent( - prefs.allow_running_insecure_content); - settings->SetDisableReadingFromCanvas(prefs.disable_reading_from_canvas); - settings->SetStrictMixedContentChecking(prefs.strict_mixed_content_checking); - - settings->SetStrictlyBlockBlockableMixedContent( - prefs.strictly_block_blockable_mixed_content); - - settings->SetStrictMixedContentCheckingForPlugin( - prefs.block_mixed_plugin_content); - - settings->SetStrictPowerfulFeatureRestrictions( - prefs.strict_powerful_feature_restrictions); - settings->SetAllowGeolocationOnInsecureOrigins( - prefs.allow_geolocation_on_insecure_origins); - settings->SetPasswordEchoEnabled(prefs.password_echo_enabled); - settings->SetShouldPrintBackgrounds(prefs.should_print_backgrounds); - settings->SetShouldClearDocumentBackground( - prefs.should_clear_document_background); - settings->SetEnableScrollAnimator(prefs.enable_scroll_animator); - settings->SetPrefersReducedMotion(prefs.prefers_reduced_motion); - - RuntimeEnabledFeatures::SetTouchEventFeatureDetectionEnabled( - prefs.touch_event_feature_detection_enabled); - settings->SetMaxTouchPoints(prefs.pointer_events_max_touch_points); - settings->SetAvailablePointerTypes(prefs.available_pointer_types); - settings->SetPrimaryPointerType(prefs.primary_pointer_type); - settings->SetAvailableHoverTypes(prefs.available_hover_types); - settings->SetPrimaryHoverType(prefs.primary_hover_type); - settings->SetOutputDeviceUpdateAbilityType( - prefs.output_device_update_ability_type); - settings->SetBarrelButtonForDragEnabled(prefs.barrel_button_for_drag_enabled); - - settings->SetEditingBehavior(prefs.editing_behavior); - - settings->SetSupportsMultipleWindows(prefs.supports_multiple_windows); - - settings->SetMainFrameClipsContent(!prefs.record_whole_document); - - RuntimeEnabledFeatures::SetStylusHandwritingEnabled( - prefs.stylus_handwriting_enabled); - - settings->SetSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled); - - settings->SetSpatialNavigationEnabled(prefs.spatial_navigation_enabled); - // Spatnav depends on KeyboardFocusableScrollers. The WebUI team has - // disabled KFS because they need more time to update their custom elements, - // crbug.com/907284. Meanwhile, we pre-ship KFS to spatnav users. - if (prefs.spatial_navigation_enabled) - RuntimeEnabledFeatures::SetKeyboardFocusableScrollersEnabled(true); - - settings->SetSelectionIncludesAltImageText(true); - - RuntimeEnabledFeatures::SetFakeNoAllocDirectCallForTestingEnabled( - prefs.fake_no_alloc_direct_call_for_testing_enabled); - - settings->SetV8CacheOptions(prefs.v8_cache_options); - - settings->SetImageAnimationPolicy(prefs.animation_policy); - - settings->SetPresentationRequiresUserGesture( - prefs.user_gesture_required_for_presentation); - - if (prefs.text_tracks_enabled) { - settings->SetTextTrackKindUserPreference( - WebSettings::TextTrackKindUserPreference::kCaptions); - } else { - settings->SetTextTrackKindUserPreference( - WebSettings::TextTrackKindUserPreference::kDefault); - } - settings->SetTextTrackBackgroundColor( - WebString::FromASCII(prefs.text_track_background_color)); - settings->SetTextTrackTextColor( - WebString::FromASCII(prefs.text_track_text_color)); - settings->SetTextTrackTextSize( - WebString::FromASCII(prefs.text_track_text_size)); - settings->SetTextTrackTextShadow( - WebString::FromASCII(prefs.text_track_text_shadow)); - settings->SetTextTrackFontFamily( - WebString::FromASCII(prefs.text_track_font_family)); - settings->SetTextTrackFontStyle( - WebString::FromASCII(prefs.text_track_font_style)); - settings->SetTextTrackFontVariant( - WebString::FromASCII(prefs.text_track_font_variant)); - settings->SetTextTrackMarginPercentage(prefs.text_track_margin_percentage); - settings->SetTextTrackWindowColor( - WebString::FromASCII(prefs.text_track_window_color)); - settings->SetTextTrackWindowRadius( - WebString::FromASCII(prefs.text_track_window_radius)); - - // Needs to happen before SetDefaultPageScaleLimits below since that'll - // recalculate the final page scale limits and that depends on this setting. - settings->SetShrinksViewportContentToFit( - prefs.shrinks_viewport_contents_to_fit); - - // Needs to happen before SetIgnoreViewportTagScaleLimits below. - web_view->SetDefaultPageScaleLimits(prefs.default_minimum_page_scale_factor, - prefs.default_maximum_page_scale_factor); - - settings->SetFullscreenSupported(prefs.fullscreen_supported); - settings->SetTextAutosizingEnabled(prefs.text_autosizing_enabled); - settings->SetDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled); - blink::WebNetworkStateNotifier::SetNetworkQualityWebHoldback( - static_cast( - prefs.network_quality_estimator_web_holdback)); - - settings->SetDontSendKeyEventsToJavascript( - prefs.dont_send_key_events_to_javascript); - settings->SetWebAppScope(WebString::FromASCII(prefs.web_app_scope.spec())); - -#if BUILDFLAG(IS_ANDROID) - settings->SetAllowCustomScrollbarInMainFrame(false); - settings->SetAccessibilityFontScaleFactor(prefs.font_scale_factor); - settings->SetDeviceScaleAdjustment(prefs.device_scale_adjustment); - web_view_impl->SetIgnoreViewportTagScaleLimits(prefs.force_enable_zoom); - settings->SetDefaultVideoPosterURL( - WebString::FromASCII(prefs.default_video_poster_url.spec())); - settings->SetSupportDeprecatedTargetDensityDPI( - prefs.support_deprecated_target_density_dpi); - settings->SetUseLegacyBackgroundSizeShorthandBehavior( - prefs.use_legacy_background_size_shorthand_behavior); - settings->SetWideViewportQuirkEnabled(prefs.wide_viewport_quirk); - settings->SetUseWideViewport(prefs.use_wide_viewport); - settings->SetForceZeroLayoutHeight(prefs.force_zero_layout_height); - settings->SetViewportMetaMergeContentQuirk( - prefs.viewport_meta_merge_content_quirk); - settings->SetViewportMetaNonUserScalableQuirk( - prefs.viewport_meta_non_user_scalable_quirk); - settings->SetViewportMetaZeroValuesQuirk( - prefs.viewport_meta_zero_values_quirk); - settings->SetClobberUserAgentInitialScaleQuirk( - prefs.clobber_user_agent_initial_scale_quirk); - settings->SetIgnoreMainFrameOverflowHiddenQuirk( - prefs.ignore_main_frame_overflow_hidden_quirk); - settings->SetReportScreenSizeInPhysicalPixelsQuirk( - prefs.report_screen_size_in_physical_pixels_quirk); - settings->SetShouldReuseGlobalForUnownedMainFrame( - prefs.reuse_global_for_unowned_main_frame); - settings->SetPreferHiddenVolumeControls(true); - settings->SetSpellCheckEnabledByDefault(prefs.spellcheck_enabled_by_default); - - RuntimeEnabledFeatures::SetVideoFullscreenOrientationLockEnabled( - prefs.video_fullscreen_orientation_lock_enabled); - RuntimeEnabledFeatures::SetVideoRotateToFullscreenEnabled( - prefs.video_rotate_to_fullscreen_enabled); - settings->SetEmbeddedMediaExperienceEnabled( - prefs.embedded_media_experience_enabled); - settings->SetImmersiveModeEnabled(prefs.immersive_mode_enabled); - settings->SetDoNotUpdateSelectionOnMutatingSelectionRange( - prefs.do_not_update_selection_on_mutating_selection_range); - RuntimeEnabledFeatures::SetCSSHexAlphaColorEnabled( - prefs.css_hex_alpha_color_enabled); - RuntimeEnabledFeatures::SetScrollTopLeftInteropEnabled( - prefs.scroll_top_left_interop_enabled); - RuntimeEnabledFeatures::SetAcceleratedSmallCanvasesEnabled( - !prefs.disable_accelerated_small_canvases); -#endif // BUILDFLAG(IS_ANDROID) - -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) - RuntimeEnabledFeatures::SetWebAuthEnabled(!prefs.disable_webauthn); -#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) - - settings->SetForceDarkModeEnabled(prefs.force_dark_mode_enabled); - - settings->SetAccessibilityAlwaysShowFocus(prefs.always_show_focus); - settings->SetAutoplayPolicy(prefs.autoplay_policy); - settings->SetRequireTransientActivationForGetDisplayMedia( - prefs.require_transient_activation_for_get_display_media); - settings->SetRequireTransientActivationForShowFileOrDirectoryPicker( - prefs.require_transient_activation_for_show_file_or_directory_picker); - settings->SetViewportEnabled(prefs.viewport_enabled); - settings->SetViewportMetaEnabled(prefs.viewport_meta_enabled); - settings->SetViewportStyle(prefs.viewport_style); - settings->SetAutoZoomFocusedEditableToLegibleScale( - prefs.auto_zoom_focused_editable_to_legible_scale); - - settings->SetLoadWithOverviewMode(prefs.initialize_at_minimum_page_scale); - settings->SetMainFrameResizesAreOrientationChanges( - prefs.main_frame_resizes_are_orientation_changes); - - settings->SetShowContextMenuOnMouseUp(prefs.context_menu_on_mouse_up); - settings->SetAlwaysShowContextMenuOnTouch( - prefs.always_show_context_menu_on_touch); - settings->SetSmoothScrollForFindEnabled(prefs.smooth_scroll_for_find_enabled); - - settings->SetHideDownloadUI(prefs.hide_download_ui); - - settings->SetPresentationReceiver(prefs.presentation_receiver); - - settings->SetMediaControlsEnabled(prefs.media_controls_enabled); - - settings->SetLowPriorityIframesThreshold( - static_cast( - prefs.low_priority_iframes_threshold)); - - settings->SetPictureInPictureEnabled(prefs.picture_in_picture_enabled && - ::features::UseSurfaceLayerForVideo()); - - settings->SetLazyLoadEnabled(prefs.lazy_load_enabled); - settings->SetPreferredColorScheme(prefs.preferred_color_scheme); - settings->SetPreferredContrast(prefs.preferred_contrast); - - settings->SetTouchDragDropEnabled(prefs.touch_drag_drop_enabled); - settings->SetTouchDragEndContextMenu(prefs.touch_dragend_context_menu); - settings->SetWebXRImmersiveArAllowed(prefs.webxr_immersive_ar_allowed); - settings->SetModalContextMenu(prefs.modal_context_menu); - -#if BUILDFLAG(IS_MAC) - web_view_impl->SetMaximumLegibleScale( - prefs.default_maximum_page_scale_factor); -#endif - -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) - RuntimeEnabledFeatures::SetMiddleClickAutoscrollEnabled(true); -#endif - - RuntimeEnabledFeatures::SetTranslateServiceEnabled( - prefs.translate_service_available); - -#if BUILDFLAG(IS_WIN) - if (web_view_impl->GetPage() && - base::FeatureList::IsEnabled(features::kPrewarmDefaultFontFamilies)) { - if (auto* prewarmer = WebFontRendering::GetFontPrewarmer()) { - GenericFontFamilySettings& font_settings = - web_view_impl->GetPage() - ->GetSettings() - .GetGenericFontFamilySettings(); - if (features::kPrewarmStandard.Get()) - prewarmer->PrewarmFamily(font_settings.Standard()); - if (features::kPrewarmFixed.Get()) - prewarmer->PrewarmFamily(font_settings.Fixed()); - if (features::kPrewarmSerif.Get()) - prewarmer->PrewarmFamily(font_settings.Serif()); - if (features::kPrewarmSansSerif.Get()) - prewarmer->PrewarmFamily(font_settings.SansSerif()); - if (features::kPrewarmCursive.Get()) - prewarmer->PrewarmFamily(font_settings.Cursive()); - if (features::kPrewarmFantasy.Get()) - prewarmer->PrewarmFamily(font_settings.Fantasy()); - } - } -#endif - - // Disabling the StrictMimetypeCheckForWorkerScriptsEnabled enterprise policy - // overrides the corresponding RuntimeEnabledFeature (via its Pref). - if (!prefs.strict_mime_type_check_for_worker_scripts_enabled) { - RuntimeEnabledFeatures::SetStrictMimeTypesForWorkersEnabled(false); - } -} - -void WebViewImpl::ThemeChanged() { - if (auto* page = GetPage()) - page->InvalidatePaint(); -} - -void WebViewImpl::EnterFullscreen(LocalFrame& frame, - const FullscreenOptions* options, - FullscreenRequestType request_type) { - fullscreen_controller_->EnterFullscreen(frame, options, request_type); -} - -void WebViewImpl::ExitFullscreen(LocalFrame& frame) { - fullscreen_controller_->ExitFullscreen(frame); -} - -void WebViewImpl::FullscreenElementChanged(Element* old_element, - Element* new_element, - const FullscreenOptions* options, - FullscreenRequestType request_type) { - fullscreen_controller_->FullscreenElementChanged(old_element, new_element, - options, request_type); -} - -bool WebViewImpl::HasHorizontalScrollbar() { - return MainFrameImpl() - ->GetFrameView() - ->LayoutViewport() - ->HorizontalScrollbar(); -} - -bool WebViewImpl::HasVerticalScrollbar() { - return MainFrameImpl()->GetFrameView()->LayoutViewport()->VerticalScrollbar(); -} - -void WebViewImpl::SetPageFocus(bool enable) { - page_->GetFocusController().SetFocused(enable); - if (enable) { - LocalFrame* focused_frame = page_->GetFocusController().FocusedFrame(); - if (focused_frame) { - Element* element = focused_frame->GetDocument()->FocusedElement(); - if (element && focused_frame->Selection() - .ComputeVisibleSelectionInDOMTreeDeprecated() - .IsNone()) { - // If the selection was cleared while the WebView was not - // focused, then the focus element shows with a focus ring but - // no caret and does respond to keyboard inputs. - focused_frame->GetDocument()->UpdateStyleAndLayoutTree(); - if (element->IsTextControl()) { - element->UpdateSelectionOnFocus(SelectionBehaviorOnFocus::kRestore); - } else if (IsEditable(*element)) { - // updateFocusAppearance() selects all the text of - // contentseditable DIVs. So we set the selection explicitly - // instead. Note that this has the side effect of moving the - // caret back to the beginning of the text. - Position position(element, 0); - focused_frame->Selection().SetSelectionAndEndTyping( - SelectionInDOMTree::Builder().Collapse(position).Build()); - } - } - } - } else { - CancelPagePopup(); - - LocalFrame* focused_frame = page_->GetFocusController().FocusedFrame(); - if (focused_frame) { - // Finish an ongoing composition to delete the composition node. - if (focused_frame->GetInputMethodController().HasComposition()) { - // TODO(editing-dev): The use of - // UpdateStyleAndLayout needs to be audited. - // See http://crbug.com/590369 for more details. - focused_frame->GetDocument()->UpdateStyleAndLayout( - DocumentUpdateReason::kFocus); - - focused_frame->GetInputMethodController().FinishComposingText( - InputMethodController::kKeepSelection); - } - } - } -} - -// WebView -------------------------------------------------------------------- - -WebSettingsImpl* WebViewImpl::SettingsImpl() { - if (!web_settings_) { - web_settings_ = std::make_unique( - &page_->GetSettings(), dev_tools_emulator_.Get()); - } - DCHECK(web_settings_); - return web_settings_.get(); -} - -WebSettings* WebViewImpl::GetSettings() { - return SettingsImpl(); -} - -WebString WebViewImpl::PageEncoding() const { - if (!page_) - return WebString(); - - auto* main_frame = DynamicTo(page_->MainFrame()); - if (!main_frame) - return WebString(); - - // FIXME: Is this check needed? - if (!main_frame->GetDocument()->Loader()) - return WebString(); - - return main_frame->GetDocument()->EncodingName(); -} - -WebFrame* WebViewImpl::MainFrame() { - Page* page = page_.Get(); - return WebFrame::FromCoreFrame(page ? page->MainFrame() : nullptr); -} - -const WebFrame* WebViewImpl::MainFrame() const { - Page* page = page_.Get(); - return WebFrame::FromCoreFrame(page ? page->MainFrame() : nullptr); -} - -WebLocalFrameImpl* WebViewImpl::MainFrameImpl() const { - Page* page = page_.Get(); - if (!page) - return nullptr; - return WebLocalFrameImpl::FromFrame(DynamicTo(page->MainFrame())); -} - -std::string WebViewImpl::GetNullFrameReasonForBug1139104() const { - Page* page = page_.Get(); - if (!page) - return "WebViewImpl::page"; - if (!page->MainFrame()) - return "WebViewImpl::page->MainFrame"; - LocalFrame* local_frame = DynamicTo(page->MainFrame()); - if (!local_frame) - return "WebViewImpl::local_frame"; - return WebLocalFrameImpl::GetNullFrameReasonForBug1139104(local_frame); -} - -void WebViewImpl::DidAttachLocalMainFrame() { - DCHECK(MainFrameImpl()); - DCHECK(!remote_main_frame_host_remote_); - - LocalFrame* local_frame = MainFrameImpl()->GetFrame(); - local_frame->WasAttachedAsLocalMainFrame(); - - local_frame->GetRemoteNavigationAssociatedInterfaces()->GetInterface( - local_main_frame_host_remote_.BindNewEndpointAndPassReceiver( - GetPage() - ->GetPageScheduler() - ->GetAgentGroupScheduler() - .DefaultTaskRunner())); - - auto& viewport = GetPage()->GetVisualViewport(); - if (does_composite_) { - // When attaching a local main frame, set up any state on the compositor. - MainFrameImpl()->FrameWidgetImpl()->SetBackgroundColor(BackgroundColor()); - MainFrameImpl()->FrameWidgetImpl()->SetPrefersReducedMotion( - web_preferences_.prefers_reduced_motion); - MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits( - viewport.Scale(), viewport.IsPinchGestureActive(), - MinimumPageScaleFactor(), MaximumPageScaleFactor()); - // Prevent main frame updates while the main frame is loading until enough - // progress is made and BeginMainFrames are explicitly asked for. - scoped_defer_main_frame_update_ = - MainFrameImpl()->FrameWidgetImpl()->DeferMainFrameUpdate(); - } - - // It's possible that at the time that `local_frame` attached its document it - // was provisional so it couldn't initialize the root scroller. Try again now - // that the frame has been attached; this is a no-op if the root scroller is - // already initialized. - if (viewport.IsActiveViewport()) { - DCHECK(local_frame->GetDocument()); - // DidAttachLocalMainFrame can be called before a new document is attached - // so ensure we don't try to initialize the root scroller on a stopped - // document. - if (local_frame->GetDocument()->IsActive()) - local_frame->View()->InitializeRootScroller(); - } -} - -void WebViewImpl::DidAttachRemoteMainFrame( - CrossVariantMojoAssociatedRemote< - mojom::blink::RemoteMainFrameHostInterfaceBase> main_frame_host, - CrossVariantMojoAssociatedReceiver< - mojom::blink::RemoteMainFrameInterfaceBase> main_frame) { - DCHECK(!MainFrameImpl()); - DCHECK(!local_main_frame_host_remote_); - // Note that we didn't DCHECK the `main_frame_host` and `main_frame`, because - // it's possible for those to be null, in case the remote main frame is a - // placeholder RemoteFrame that does not have any browser-side counterpart. - // This is possible when the WebView is created in preparation for a main - // frame LocalFrame <-> LocalFrame swap. See the comments in - // `AgentSchedulingGroup::CreateWebView()` for more details. - - RemoteFrame* remote_frame = DynamicTo(GetPage()->MainFrame()); - remote_frame->WasAttachedAsRemoteMainFrame(std::move(main_frame)); - - remote_main_frame_host_remote_.Bind(std::move(main_frame_host)); - - auto& viewport = GetPage()->GetVisualViewport(); - DCHECK(!viewport.IsActiveViewport()); - viewport.Reset(); -} - -void WebViewImpl::DidDetachLocalMainFrame() { - // The WebFrameWidget that generated the |scoped_defer_main_frame_update_| - // for a local main frame is going away. - scoped_defer_main_frame_update_ = nullptr; - local_main_frame_host_remote_.reset(); -} - -void WebViewImpl::DidDetachRemoteMainFrame() { - remote_main_frame_host_remote_.reset(); -} - -WebLocalFrame* WebViewImpl::FocusedFrame() { - Frame* frame = FocusedCoreFrame(); - // TODO(yabinh): focusedCoreFrame() should always return a local frame, and - // the following check should be unnecessary. - // See crbug.com/625068 - return WebLocalFrameImpl::FromFrame(DynamicTo(frame)); -} - -void WebViewImpl::SetFocusedFrame(WebFrame* frame) { - if (!frame) { - // Clears the focused frame if any. - Frame* focused_frame = FocusedCoreFrame(); - if (auto* focused_local_frame = DynamicTo(focused_frame)) - focused_local_frame->Selection().SetFrameIsFocused(false); - return; - } - LocalFrame* core_frame = To(frame)->GetFrame(); - core_frame->GetPage()->GetFocusController().SetFocusedFrame(core_frame); -} - -void WebViewImpl::FinishScrollFocusedEditableIntoView( - const gfx::RectF& caret_rect_in_root_frame, - mojom::blink::ScrollIntoViewParamsPtr params) { - DCHECK(MainFrameImpl()); - DCHECK(!IsFencedFrameRoot()); - DCHECK(!caret_rect_in_root_frame.IsEmpty()); - DCHECK(params->for_focused_editable); - - // Zoom if: - // (1) Zoom to legible scale is enabled (i.e. Android) - // (2) We're on a non-mobile-friendly page - // (3) The element doesn't explicitly block pinch-zoom gestures so the user - // can zoom back out. - bool zoom_into_legible_scale = - web_settings_->AutoZoomFocusedEditableToLegibleScale() && - !GetPage()->GetVisualViewport().ShouldDisableDesktopWorkarounds() && - params->for_focused_editable->can_zoom; - - // Reconstruct the editable element's absolute rect from the caret-relative - // location. - gfx::RectF editable_rect_in_root_frame = - scroll_into_view_util::FocusedEditableBoundsFromParams( - caret_rect_in_root_frame, params); - - DCHECK(!editable_rect_in_root_frame.IsEmpty()); - - float scale; - gfx::Point scroll; - bool need_animation = false; - ComputeScaleAndScrollForEditableElementRects( - gfx::ToEnclosedRect(editable_rect_in_root_frame), - gfx::ToEnclosedRect(caret_rect_in_root_frame), zoom_into_legible_scale, - scale, scroll, need_animation); - - if (need_animation) { - StartPageScaleAnimation(scroll, false, scale, - kScrollAndScaleAnimationDuration); - } -} - -void WebViewImpl::SmoothScroll(int target_x, - int target_y, - base::TimeDelta duration) { - gfx::Point target_position(target_x, target_y); - StartPageScaleAnimation(target_position, false, PageScaleFactor(), duration); -} - -void WebViewImpl::ComputeScaleAndScrollForEditableElementRects( - const gfx::Rect& element_bounds_in_root_frame, - const gfx::Rect& caret_bounds_in_root_frame, - bool zoom_into_legible_scale, - float& new_scale, - gfx::Point& new_scroll_position, - bool& need_animation) { - VisualViewport& visual_viewport = GetPage()->GetVisualViewport(); - - TopDocumentRootScrollerController& controller = - GetPage()->GlobalRootScrollerController(); - Node* root_scroller = controller.GlobalRootScroller(); - - gfx::Rect element_bounds_in_content; - gfx::Rect caret_bounds_in_content; - - // If the page has a non-default root scroller then we need to put the - // "in_content" coordinates into that scroller's coordinate space, rather - // than the root frame's. - if (root_scroller != MainFrameImpl()->GetFrame()->GetDocument() && - controller.RootScrollerArea()) { - ScrollOffset offset = controller.RootScrollerArea()->GetScrollOffset(); - - element_bounds_in_content = element_bounds_in_root_frame; - caret_bounds_in_content = caret_bounds_in_root_frame; - - element_bounds_in_content.Offset(gfx::ToFlooredVector2d(offset)); - caret_bounds_in_content.Offset(gfx::ToFlooredVector2d(offset)); - } else { - element_bounds_in_content = - MainFrameImpl()->GetFrameView()->RootFrameToDocument( - element_bounds_in_root_frame); - caret_bounds_in_content = - MainFrameImpl()->GetFrameView()->RootFrameToDocument( - caret_bounds_in_root_frame); - } - - if (!zoom_into_legible_scale) { - new_scale = PageScaleFactor(); - } else { - // Pick a scale which is reasonably readable. This is the scale at which - // the caret height will become minReadableCaretHeightForNode (adjusted - // for dpi and font scale factor). - const int min_readable_caret_height_for_node = - (element_bounds_in_content.height() >= - 2 * caret_bounds_in_content.height() - ? minReadableCaretHeightForTextArea - : minReadableCaretHeight) * - MainFrameImpl()->GetFrame()->PageZoomFactor(); - new_scale = ClampPageScaleFactorToLimits( - MaximumLegiblePageScale() * min_readable_caret_height_for_node / - caret_bounds_in_content.height()); - new_scale = std::max(new_scale, PageScaleFactor()); - } - const float delta_scale = new_scale / PageScaleFactor(); - - need_animation = false; - - // If we are at less than the target zoom level, zoom in. - if (delta_scale > minScaleChangeToTriggerZoom) - need_animation = true; - else - new_scale = PageScaleFactor(); - - ScrollableArea* root_viewport = - MainFrameImpl()->GetFrame()->View()->GetScrollableArea(); - - // If the caret is offscreen, then animate. - if (!root_viewport->VisibleContentRect().Contains(caret_bounds_in_content)) - need_animation = true; - - // If the box is partially offscreen and it's possible to bring it fully - // onscreen, then animate. - if (visual_viewport.VisibleRect().width() >= - element_bounds_in_content.width() && - visual_viewport.VisibleRect().height() >= - element_bounds_in_content.height() && - !root_viewport->VisibleContentRect().Contains(element_bounds_in_content)) - need_animation = true; - - if (!need_animation) - return; - - gfx::SizeF target_viewport_size(visual_viewport.Size()); - target_viewport_size.Scale(1 / new_scale); - - // TODO(bokan): The logic below is all tailored assuming LTR writing mode. - // Ideally, it'd perform its computations based on writing mode. - ScrollOffset scroll_offset; - if (element_bounds_in_content.width() <= target_viewport_size.width()) { - // Field is narrower than screen. Try to leave padding on left so field's - // label is visible, but it's more important to ensure entire field is - // onscreen. - int ideal_left_padding = target_viewport_size.width() * leftBoxRatio; - int max_left_padding_keeping_box_onscreen = - target_viewport_size.width() - element_bounds_in_content.width(); - scroll_offset.set_x(element_bounds_in_content.x() - - std::min(ideal_left_padding, - max_left_padding_keeping_box_onscreen)); - } else { - // Field is wider than screen. Try to left-align field, unless caret would - // be offscreen, in which case right-align the caret. - scroll_offset.set_x(std::max( - element_bounds_in_content.x(), - caret_bounds_in_content.x() + caret_bounds_in_content.width() + - caretPadding - target_viewport_size.width())); - } - if (element_bounds_in_content.height() <= target_viewport_size.height()) { - // Field is shorter than screen. Vertically center it. - scroll_offset.set_y( - element_bounds_in_content.y() - - (target_viewport_size.height() - element_bounds_in_content.height()) / - 2); - } else { - // Field is taller than screen. Try to top align field, unless caret would - // be offscreen, in which case bottom-align the caret. - scroll_offset.set_y(std::max( - element_bounds_in_content.y(), - caret_bounds_in_content.y() + caret_bounds_in_content.height() + - caretPadding - target_viewport_size.height())); - } - - // The output scroll will be used by the compositor so we must convert the - // scroll-origin relative (i.e. writing-mode dependent) ScrollOffset with a - // top-left relative scroll position. - new_scroll_position = - ToFlooredPoint(root_viewport->ScrollOffsetToPosition(scroll_offset)); -} - -void WebViewImpl::AdvanceFocus(bool reverse) { - GetPage()->GetFocusController().AdvanceFocus( - reverse ? mojom::blink::FocusType::kBackward - : mojom::blink::FocusType::kForward); -} - -double WebViewImpl::ZoomLevel() { - return zoom_level_; -} - -void WebViewImpl::PropagateZoomFactorToLocalFrameRoots(Frame* frame, - float zoom_factor) { - auto* local_frame = DynamicTo(frame); - if (local_frame && local_frame->IsLocalRoot()) { - if (Document* document = local_frame->GetDocument()) { - auto* plugin_document = DynamicTo(document); - if (!plugin_document || !plugin_document->GetPluginView()) { - local_frame->SetPageZoomFactor(zoom_factor); - } - } - } - - for (Frame* child = frame->Tree().FirstChild(); child; - child = child->Tree().NextSibling()) - PropagateZoomFactorToLocalFrameRoots(child, zoom_factor); -} - -double WebViewImpl::SetZoomLevel(double zoom_level) { - double old_zoom_level = zoom_level_; - if (zoom_level < minimum_zoom_level_) - zoom_level_ = minimum_zoom_level_; - else if (zoom_level > maximum_zoom_level_) - zoom_level_ = maximum_zoom_level_; - else - zoom_level_ = zoom_level; - - float zoom_factor = - zoom_factor_override_ - ? zoom_factor_override_ - : static_cast(PageZoomLevelToZoomFactor(zoom_level_)); - if (zoom_factor_for_device_scale_factor_) { - if (compositor_device_scale_factor_override_) { - page_->SetInspectorDeviceScaleFactorOverride( - zoom_factor_for_device_scale_factor_ / - compositor_device_scale_factor_override_); - - zoom_factor *= compositor_device_scale_factor_override_; - } else { - page_->SetInspectorDeviceScaleFactorOverride(1.0f); - zoom_factor *= zoom_factor_for_device_scale_factor_; - } - } - PropagateZoomFactorToLocalFrameRoots(page_->MainFrame(), zoom_factor); - - if (old_zoom_level != zoom_level_) { - for (auto& observer : observers_) - observer.OnZoomLevelChanged(); - CancelPagePopup(); - } - - return zoom_level_; -} - -float WebViewImpl::PageScaleFactor() const { - if (!GetPage()) - return 1; - - return GetPage()->GetVisualViewport().Scale(); -} - -float WebViewImpl::ClampPageScaleFactorToLimits(float scale_factor) const { - return GetPageScaleConstraintsSet().FinalConstraints().ClampToConstraints( - scale_factor); -} - -void WebViewImpl::SetVisualViewportOffset(const gfx::PointF& offset) { - DCHECK(GetPage()); - GetPage()->GetVisualViewport().SetLocation(offset); -} - -gfx::PointF WebViewImpl::VisualViewportOffset() const { - DCHECK(GetPage()); - return GetPage()->GetVisualViewport().VisibleRect().origin(); -} - -gfx::SizeF WebViewImpl::VisualViewportSize() const { - DCHECK(GetPage()); - return GetPage()->GetVisualViewport().VisibleRect().size(); -} - -void WebViewImpl::SetPageScaleFactorAndLocation(float scale_factor, - bool is_pinch_gesture_active, - const gfx::PointF& location) { - DCHECK(GetPage()); - - GetPage()->GetVisualViewport().SetScaleAndLocation( - ClampPageScaleFactorToLimits(scale_factor), is_pinch_gesture_active, - location); -} - -void WebViewImpl::SetPageScaleFactor(float scale_factor) { - DCHECK(GetPage()); - DCHECK(MainFrameImpl()); - - if (LocalFrame* frame = MainFrameImpl()->GetFrame()) { - frame->SetScaleFactor(scale_factor); - } -} - -void WebViewImpl::SetZoomFactorForDeviceScaleFactor( - float zoom_factor_for_device_scale_factor) { - DCHECK(does_composite_); - // We can't early-return here if these are already equal, because we may - // need to propagate the correct zoom factor to newly navigated frames. - zoom_factor_for_device_scale_factor_ = zoom_factor_for_device_scale_factor; - SetZoomLevel(zoom_level_); -} - -void WebViewImpl::SetPageLifecycleStateFromNewPageCommit( - mojom::blink::PageVisibilityState visibility, - mojom::blink::PagehideDispatch pagehide_dispatch) { - TRACE_EVENT0("navigation", - "WebViewImpl::SetPageLifecycleStateFromNewPageCommit"); - mojom::blink::PageLifecycleStatePtr state = - GetPage()->GetPageLifecycleState().Clone(); - state->visibility = visibility; - state->pagehide_dispatch = pagehide_dispatch; - SetPageLifecycleStateInternal(std::move(state), - /*page_restore_params=*/nullptr); -} - -void WebViewImpl::SetPageLifecycleState( - mojom::blink::PageLifecycleStatePtr state, - mojom::blink::PageRestoreParamsPtr page_restore_params, - SetPageLifecycleStateCallback callback) { - TRACE_EVENT0("navigation", "WebViewImpl::SetPageLifecycleState"); - SetPageLifecycleStateInternal(std::move(state), - std::move(page_restore_params)); - // Tell the browser that the lifecycle update was successful. - std::move(callback).Run(); -} - -// Returns true if this state update is for the page being restored from -// back-forward cache, causing the pageshow event to fire with persisted=true. -bool IsRestoredFromBackForwardCache( - const mojom::blink::PageLifecycleStatePtr& old_state, - const mojom::blink::PageLifecycleStatePtr& new_state) { - if (!old_state) - return false; - bool old_state_hidden = old_state->pagehide_dispatch != - mojom::blink::PagehideDispatch::kNotDispatched; - bool new_state_shown = new_state->pagehide_dispatch == - mojom::blink::PagehideDispatch::kNotDispatched; - // It's a pageshow but it can't be the initial pageshow since it was already - // hidden. So it must be a back-forward cache restore. - return old_state_hidden && new_state_shown; -} - -void WebViewImpl::SetPageLifecycleStateInternal( - mojom::blink::PageLifecycleStatePtr new_state, - mojom::blink::PageRestoreParamsPtr page_restore_params) { - Page* page = GetPage(); - if (!page) - return; - auto& old_state = page->GetPageLifecycleState(); - TRACE_EVENT2("navigation", "WebViewImpl::SetPageLifecycleStateInternal", - "old_state", old_state, "new_state", new_state); - - bool storing_in_bfcache = new_state->is_in_back_forward_cache && - !old_state->is_in_back_forward_cache; - bool restoring_from_bfcache = !new_state->is_in_back_forward_cache && - old_state->is_in_back_forward_cache; - bool hiding_page = - (new_state->visibility != mojom::blink::PageVisibilityState::kVisible) && - (old_state->visibility == mojom::blink::PageVisibilityState::kVisible); - bool showing_page = - (new_state->visibility == mojom::blink::PageVisibilityState::kVisible) && - (old_state->visibility != mojom::blink::PageVisibilityState::kVisible); - bool freezing_page = new_state->is_frozen && !old_state->is_frozen; - bool resuming_page = !new_state->is_frozen && old_state->is_frozen; - bool dispatching_pagehide = - (new_state->pagehide_dispatch != - mojom::blink::PagehideDispatch::kNotDispatched) && - !GetPage()->DispatchedPagehideAndStillHidden(); - bool dispatching_pageshow = - IsRestoredFromBackForwardCache(old_state, new_state); - bool eviction_changed = - new_state->eviction_enabled != old_state->eviction_enabled; - - if (dispatching_pagehide) { - RemoveFocusAndTextInputState(); - } - if (dispatching_pagehide) { - // Note that |dispatching_pagehide| is different than |hiding_page|. - // |dispatching_pagehide| will only be true when we're navigating away from - // a page, while |hiding_page| might be true in other cases too such as when - // the tab containing a page is backgrounded, and might be false even when - // we're navigating away from a page, if the page is already hidden. - DispatchPagehide(new_state->pagehide_dispatch); - } - if (hiding_page) { - SetVisibilityState(new_state->visibility, /*is_initial_state=*/false); - } - if (storing_in_bfcache) { - // TODO(https://crbug.com/1378279): Consider moving this to happen earlier - // and together with other page state updates so that the ordering is clear. - Scheduler()->SetPageBackForwardCached(new_state->is_in_back_forward_cache); - } - - if (freezing_page) { - // Notify all local frames that we are about to freeze. - for (WebFrame* frame = MainFrame(); frame; frame = frame->TraverseNext()) { - if (frame->IsWebLocalFrame()) { - frame->ToWebLocalFrame()->Client()->WillFreezePage(); - } - } - - // TODO(https://crbug.com/1378279): Consider moving this to happen earlier - // and together with other page state updates so that the ordering is clear. - SetPageFrozen(true); - } - - if (restoring_from_bfcache) { - DCHECK(page_restore_params); - // Update the history offset and length value, as pages that are kept in - // the back-forward cache do not get notified about updates on these - // values, so the currently saved value might be stale. - SetHistoryOffsetAndLength(page_restore_params->pending_history_list_offset, - page_restore_params->current_history_list_length); - } - if (eviction_changed) - HookBackForwardCacheEviction(new_state->eviction_enabled); - if (resuming_page) { - // TODO(https://crbug.com/1378279): Consider moving this to happen earlier - // and together with other page state updates so that the ordering is clear. - SetPageFrozen(false); - } - if (showing_page) { - SetVisibilityState(new_state->visibility, /*is_initial_state=*/false); - } - if (restoring_from_bfcache) { - DCHECK(dispatching_pageshow); - DCHECK(page_restore_params); - // Increment the navigation counter on the main frame and all nested frames - // in its frame tree. - // Navigation Id increment should happen before a - // BackForwardCacheRestoration instance is created which happens inside the - // DispatchPageshow method. - for (Frame* frame = page->MainFrame(); frame; - frame = frame->Tree().TraverseNext()) { - auto* local_frame = DynamicTo(frame); - if (local_frame && local_frame->View()) { - DCHECK(local_frame->DomWindow()); - local_frame->DomWindow()->GenerateNewNavigationId(); - } - } - - DispatchPersistedPageshow(page_restore_params->navigation_start); - - // TODO(https://crbug.com/1378279): Consider moving this to happen earlier - // and together with other page state updates so that the ordering is clear. - Scheduler()->SetPageBackForwardCached(new_state->is_in_back_forward_cache); - if (MainFrame()->IsWebLocalFrame()) { - LocalFrame* local_frame = To(page->MainFrame()); - probe::DidRestoreFromBackForwardCache(local_frame); - - if (base::FeatureList::IsEnabled( - blink::features::kRetriggerPreloadingOnBFCacheRestoration)) { - if (local_frame->IsOutermostMainFrame()) { - Document* document = local_frame->GetDocument(); - if (auto* document_rules = - DocumentSpeculationRules::FromIfExists(*document)) { - document_rules->DocumentRestoredFromBFCache(); - } - } - } - } - } - - // Make sure no TrackedFeaturesUpdate message is sent after the ACK - // TODO(carlscab): Do we really need to go through LocalFrame => - // platform/scheduler/ => LocalFrame to report the features? We can probably - // move SchedulerTrackedFeatures to core/ and remove the back and forth. - ReportActiveSchedulerTrackedFeatures(); - - // TODO(https://crbug.com/1378279): Consider moving this to happen earlier - // and together with other page state updates so that the ordering is clear. - GetPage()->SetPageLifecycleState(std::move(new_state)); - - // Notify all local frames that we've updated the page lifecycle state. - for (WebFrame* frame = MainFrame(); frame; frame = frame->TraverseNext()) { - if (frame->IsWebLocalFrame()) { - frame->ToWebLocalFrame()->Client()->DidSetPageLifecycleState(); - } - } - - UpdateViewTransitionState(restoring_from_bfcache, storing_in_bfcache, - page_restore_params); -} - -void WebViewImpl::UpdateViewTransitionState( - bool restoring_from_bfcache, - bool storing_in_bfcache, - const mojom::blink::PageRestoreParamsPtr& page_restore_params) { - // If we have view_transition_state, then we must be a main frame. - DCHECK(!page_restore_params || !page_restore_params->view_transition_state || - MainFrame()->IsWebLocalFrame()); - // We can't be both restoring and storing things. - DCHECK(!restoring_from_bfcache || !storing_in_bfcache); - - if (!MainFrame()->IsWebLocalFrame()) { - return; - } - LocalFrame* local_frame = To(GetPage()->MainFrame()); - DCHECK(local_frame); - - // When restoring from BFCache, start a transition if we have a view - // transition state. - if (restoring_from_bfcache && page_restore_params->view_transition_state) { - if (auto* document = local_frame->GetDocument()) { - ViewTransitionSupplement::CreateFromSnapshotForNavigation( - *document, std::move(*page_restore_params->view_transition_state)); - } - } - - // If we're storing the page in BFCache, abort any pending transitions. This - // is important since when we bring the page back from BFCache, we might - // attempt to create a transition and fail if there is one already happening. - // Note that even if we won't be creating a transition, it's harmless to abort - // the main frame transition when going into BFCache. - if (storing_in_bfcache) { - if (auto* document = local_frame->GetDocument()) { - ViewTransitionSupplement::AbortTransition(*document); - } - } -} - -void WebViewImpl::ReportActiveSchedulerTrackedFeatures() { - Page* page = GetPage(); - if (!page) - return; - - for (Frame* frame = page->MainFrame(); frame; - frame = frame->Tree().TraverseNext()) { - if (!frame->IsLocalFrame()) - continue; - auto* local_frame = DynamicTo(frame); - if (!local_frame->GetFrameScheduler()) - continue; - local_frame->GetFrameScheduler()->ReportActiveSchedulerTrackedFeatures(); - } -} - -void WebViewImpl::AudioStateChanged(bool is_audio_playing) { - GetPage()->GetPageScheduler()->AudioStateChanged(is_audio_playing); -} - -void WebViewImpl::RemoveFocusAndTextInputState() { - auto& focus_controller = GetPage()->GetFocusController(); - auto* focused_frame = focus_controller.FocusedFrame(); - if (!focused_frame) - return; - // Remove focus from the currently focused element and frame. - focus_controller.SetFocusedElement(nullptr, nullptr); - // Clear composing state, and make sure we send a TextInputState update. - // Note that the TextInputState itself is cleared when we clear the focus, - // but no updates to the browser will be triggered until the next animation - // frame, which won't happen if we're freezing the page. - if (auto* widget = static_cast( - focused_frame->GetWidgetForLocalRoot())) { - widget->FinishComposingText(false /* keep_selection */); - widget->UpdateTextInputState(); - } -} - -void WebViewImpl::DispatchPagehide( - mojom::blink::PagehideDispatch pagehide_dispatch) { - DCHECK_NE(pagehide_dispatch, mojom::blink::PagehideDispatch::kNotDispatched); - bool persisted = (pagehide_dispatch == - mojom::blink::PagehideDispatch::kDispatchedPersisted); - // Dispatch pagehide on all frames. - for (Frame* frame = GetPage()->MainFrame(); frame; - frame = frame->Tree().TraverseNext()) { - if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) { - frame->DomWindow()->ToLocalDOMWindow()->DispatchPagehideEvent( - persisted - ? PageTransitionEventPersistence::kPageTransitionEventPersisted - : PageTransitionEventPersistence:: - kPageTransitionEventNotPersisted); - } - } -} - -void WebViewImpl::DispatchPersistedPageshow(base::TimeTicks navigation_start) { - for (Frame* frame = GetPage()->MainFrame(); frame; - frame = frame->Tree().TraverseNext()) { - auto* local_frame = DynamicTo(frame); - // Record the metics. - if (local_frame && local_frame->View()) { - Document* document = local_frame->GetDocument(); - if (document) { - PaintTiming::From(*document).OnRestoredFromBackForwardCache(); - InteractiveDetector::From(*document)->OnRestoredFromBackForwardCache(); - } - DocumentLoader* loader = local_frame->Loader().GetDocumentLoader(); - if (loader) { - loader->GetTiming().SetBackForwardCacheRestoreNavigationStart( - navigation_start); - } - } - if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) { - auto pageshow_start_time = base::TimeTicks::Now(); - LocalDOMWindow* window = frame->DomWindow()->ToLocalDOMWindow(); - - window->DispatchPersistedPageshowEvent(navigation_start); - - if (RuntimeEnabledFeatures::NavigationIdEnabled(window)) { - auto pageshow_end_time = base::TimeTicks::Now(); - - WindowPerformance* performance = - DOMWindowPerformance::performance(*window); - DCHECK(performance); - - performance->AddBackForwardCacheRestoration( - navigation_start, pageshow_start_time, pageshow_end_time); - } - if (frame->IsOutermostMainFrame()) { - UMA_HISTOGRAM_BOOLEAN( - "BackForwardCache.MainFrameHasPageshowListenersOnRestore", - window->HasEventListeners(event_type_names::kPageshow)); - } - } - } -} - -void WebViewImpl::HookBackForwardCacheEviction(bool hook) { - DCHECK(GetPage()); - for (Frame* frame = GetPage()->MainFrame(); frame; - frame = frame->Tree().TraverseNext()) { - auto* local_frame = DynamicTo(frame); - if (!local_frame) - continue; - if (hook) - local_frame->HookBackForwardCacheEviction(); - else - local_frame->RemoveBackForwardCacheEviction(); - } -} - -void WebViewImpl::EnableAutoResizeMode(const gfx::Size& min_size, - const gfx::Size& max_size) { - should_auto_resize_ = true; - min_auto_size_ = min_size; - max_auto_size_ = max_size; - ConfigureAutoResizeMode(); -} - -void WebViewImpl::DisableAutoResizeMode() { - should_auto_resize_ = false; - ConfigureAutoResizeMode(); -} - -bool WebViewImpl::AutoResizeMode() { - return should_auto_resize_; -} - -void WebViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_window_size, - const gfx::Size& max_window_size) { - EnableAutoResizeMode(web_widget_->DIPsToCeiledBlinkSpace(min_window_size), - web_widget_->DIPsToCeiledBlinkSpace(max_window_size)); -} - -void WebViewImpl::DisableAutoResizeForTesting( - const gfx::Size& new_window_size) { - if (!should_auto_resize_) - return; - DisableAutoResizeMode(); - - // The |new_size| is empty when resetting auto resize in between tests. In - // this case the current size should just be preserved. - if (!new_window_size.IsEmpty()) { - web_widget_->Resize(web_widget_->DIPsToCeiledBlinkSpace(new_window_size)); - } -} - -void WebViewImpl::SetDefaultPageScaleLimits(float min_scale, float max_scale) { - dev_tools_emulator_->SetDefaultPageScaleLimits(min_scale, max_scale); -} - -void WebViewImpl::SetInitialPageScaleOverride( - float initial_page_scale_factor_override) { - PageScaleConstraints constraints = - GetPageScaleConstraintsSet().UserAgentConstraints(); - constraints.initial_scale = initial_page_scale_factor_override; - - if (constraints == GetPageScaleConstraintsSet().UserAgentConstraints()) - return; - - GetPageScaleConstraintsSet().SetNeedsReset(true); - GetPage()->SetUserAgentPageScaleConstraints(constraints); -} - -void WebViewImpl::SetMaximumLegibleScale(float maximum_legible_scale) { - maximum_legible_scale_ = maximum_legible_scale; -} - -void WebViewImpl::SetIgnoreViewportTagScaleLimits(bool ignore) { - PageScaleConstraints constraints = - GetPageScaleConstraintsSet().UserAgentConstraints(); - if (ignore) { - // Don't ignore the minimum limits in touchless mode to prevent wide - // loading elements from causing us to zoom pages out beyond their layout - // which is fairly common. - if (!RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) { - constraints.minimum_scale = - GetPageScaleConstraintsSet().DefaultConstraints().minimum_scale; - } - constraints.maximum_scale = - GetPageScaleConstraintsSet().DefaultConstraints().maximum_scale; - } else { - if (!RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) { - constraints.minimum_scale = -1; - } - constraints.maximum_scale = -1; - } - GetPage()->SetUserAgentPageScaleConstraints(constraints); -} - -gfx::Size WebViewImpl::MainFrameSize() { - // The frame size should match the viewport size at minimum scale, since the - // viewport must always be contained by the frame. - return gfx::ScaleToCeiledSize(size_, 1 / MinimumPageScaleFactor()); -} - -PageScaleConstraintsSet& WebViewImpl::GetPageScaleConstraintsSet() const { - return GetPage()->GetPageScaleConstraintsSet(); -} - -void WebViewImpl::RefreshPageScaleFactor() { - if (!MainFrame() || !GetPage() || !GetPage()->MainFrame() || - !GetPage()->MainFrame()->IsLocalFrame() || - !GetPage()->DeprecatedLocalMainFrame()->View()) - return; - UpdatePageDefinedViewportConstraints(MainFrameImpl() - ->GetFrame() - ->GetDocument() - ->GetViewportData() - .GetViewportDescription()); - GetPageScaleConstraintsSet().ComputeFinalConstraints(); - - float new_page_scale_factor = PageScaleFactor(); - if (GetPageScaleConstraintsSet().NeedsReset() && - GetPageScaleConstraintsSet().FinalConstraints().initial_scale != -1) { - new_page_scale_factor = - GetPageScaleConstraintsSet().FinalConstraints().initial_scale; - GetPageScaleConstraintsSet().SetNeedsReset(false); - } - SetPageScaleFactor(new_page_scale_factor); - - // The constraints may have changed above which affects the page scale limits, - // so we must update those even though SetPageScaleFactor() may do the same if - // the scale factor is changed. - if (does_composite_) { - auto& viewport = GetPage()->GetVisualViewport(); - MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits( - viewport.Scale(), viewport.IsPinchGestureActive(), - MinimumPageScaleFactor(), MaximumPageScaleFactor()); - } -} - -void WebViewImpl::UpdatePageDefinedViewportConstraints( - const ViewportDescription& description) { - if (!GetPage() || (!size_.width() && !size_.height())) - return; - // The viewport is a property of the main frame and its widget, so ignore it - // when the main frame is remote. - // TODO(danakj): Remove calls to this method from ChromeClient and DCHECK this - // instead. - if (!GetPage()->MainFrame()->IsLocalFrame()) - return; - - if (virtual_keyboard_mode_ != description.virtual_keyboard_mode) { - // TODO(bokan): This should handle portals. - DCHECK(MainFrameImpl()->IsOutermostMainFrame()); - virtual_keyboard_mode_ = description.virtual_keyboard_mode; - mojom::blink::LocalFrameHost& frame_host = - MainFrameImpl()->GetFrame()->GetLocalFrameHostRemote(); - - frame_host.SetVirtualKeyboardMode(virtual_keyboard_mode_); - } - - if (!GetSettings()->ViewportEnabled()) { - GetPageScaleConstraintsSet().ClearPageDefinedConstraints(); - UpdateMainFrameLayoutSize(); - return; - } - - Document* document = GetPage()->DeprecatedLocalMainFrame()->GetDocument(); - - Length default_min_width = - document->GetViewportData().ViewportDefaultMinWidth(); - if (default_min_width.IsAuto()) - default_min_width = Length::ExtendToZoom(); - - float old_initial_scale = - GetPageScaleConstraintsSet().PageDefinedConstraints().initial_scale; - GetPageScaleConstraintsSet().UpdatePageDefinedConstraints(description, - default_min_width); - - if (SettingsImpl()->ClobberUserAgentInitialScaleQuirk() && - GetPageScaleConstraintsSet().UserAgentConstraints().initial_scale != -1 && - GetPageScaleConstraintsSet().UserAgentConstraints().initial_scale <= 1) { - if (description.max_width == Length::DeviceWidth() || - (description.max_width.IsAuto() && - GetPageScaleConstraintsSet().PageDefinedConstraints().initial_scale == - 1.0f)) - SetInitialPageScaleOverride(-1); - } - - Settings& page_settings = GetPage()->GetSettings(); - GetPageScaleConstraintsSet().AdjustForAndroidWebViewQuirks( - description, default_min_width.IntValue(), - SettingsImpl()->SupportDeprecatedTargetDensityDPI(), - page_settings.GetWideViewportQuirkEnabled(), - page_settings.GetUseWideViewport(), - page_settings.GetLoadWithOverviewMode(), - SettingsImpl()->ViewportMetaNonUserScalableQuirk()); - float new_initial_scale = - GetPageScaleConstraintsSet().PageDefinedConstraints().initial_scale; - if (old_initial_scale != new_initial_scale && new_initial_scale != -1) { - GetPageScaleConstraintsSet().SetNeedsReset(true); - if (MainFrameImpl() && MainFrameImpl()->GetFrameView()) - MainFrameImpl()->GetFrameView()->SetNeedsLayout(); - } - - if (does_composite_) { - MainFrameImpl()->FrameWidgetImpl()->UpdateViewportDescription(description); - } - - UpdateMainFrameLayoutSize(); -} - -void WebViewImpl::UpdateMainFrameLayoutSize() { - if (should_auto_resize_ || !MainFrameImpl()) - return; - - LocalFrameView* view = MainFrameImpl()->GetFrameView(); - if (!view) - return; - - gfx::Size layout_size = size_; - - if (GetSettings()->ViewportEnabled()) - layout_size = GetPageScaleConstraintsSet().GetLayoutSize(); - - if (GetPage()->GetSettings().GetForceZeroLayoutHeight()) - layout_size.set_height(0); - - view->SetLayoutSize(layout_size); -} - -gfx::Size WebViewImpl::ContentsSize() const { - if (!GetPage()->MainFrame()->IsLocalFrame()) - return gfx::Size(); - auto* layout_view = - GetPage()->DeprecatedLocalMainFrame()->ContentLayoutObject(); - if (!layout_view) - return gfx::Size(); - return ToPixelSnappedRect(layout_view->DocumentRect()).size(); -} - -gfx::Size WebViewImpl::ContentsPreferredMinimumSize() { - DCHECK(page_->MainFrame()->IsLocalFrame()); - - auto* main_local_frame = DynamicTo(page_->MainFrame()); - Document* document = main_local_frame->GetDocument(); - if (!document || !document->GetLayoutView() || !document->documentElement() || - !document->documentElement()->GetLayoutBox()) - return gfx::Size(); - - // The preferred size requires an up-to-date layout tree. - DCHECK(!document->NeedsLayoutTreeUpdate() && - !document->View()->NeedsLayout()); - - // Needed for computing MinPreferredWidth. - FontCachePurgePreventer fontCachePurgePreventer; - // Already accounts for zoom. - int width_scaled = document->GetLayoutView()->ComputeMinimumWidth().Round(); - int height_scaled = - document->documentElement()->GetLayoutBox()->ScrollHeight().Round(); - return gfx::Size(width_scaled, height_scaled); -} - -void WebViewImpl::UpdatePreferredSize() { - // We don't always want to send the change messages over IPC, only if we've - // been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode| - // message. - if (!send_preferred_size_changes_ || !MainFrameImpl()) - return; - - if (!needs_preferred_size_update_) - return; - needs_preferred_size_update_ = false; - - gfx::Size size_in_dips = - MainFrameImpl()->LocalRootFrameWidget()->BlinkSpaceToFlooredDIPs( - gfx::Size(ContentsPreferredMinimumSize())); - - if (size_in_dips != preferred_size_in_dips_) { - preferred_size_in_dips_ = size_in_dips; - local_main_frame_host_remote_->ContentsPreferredSizeChanged(size_in_dips); - } -} - -void WebViewImpl::EnablePreferredSizeChangedMode() { - if (send_preferred_size_changes_) - return; - send_preferred_size_changes_ = true; - needs_preferred_size_update_ = true; - - // We need to ensure |UpdatePreferredSize| gets called. If a layout is needed, - // force an update here which will call |DidUpdateMainFrameLayout|. - if (MainFrameWidget()) { - MainFrameWidget()->UpdateLifecycle(WebLifecycleUpdate::kLayout, - DocumentUpdateReason::kSizeChange); - } - - // If a layout was not needed, |DidUpdateMainFrameLayout| will not be called. - // We explicitly update the preferred size here to ensure the preferred size - // notification is sent. - UpdatePreferredSize(); -} - -void WebViewImpl::Focus() { - if (GetPage()->MainFrame()->IsLocalFrame()) { - DCHECK(local_main_frame_host_remote_); - local_main_frame_host_remote_->FocusPage(); - } else { - DCHECK(remote_main_frame_host_remote_); - remote_main_frame_host_remote_->FocusPage(); - } -} - -void WebViewImpl::TakeFocus(bool reverse) { - if (GetPage()->MainFrame()->IsLocalFrame()) { - DCHECK(local_main_frame_host_remote_); - local_main_frame_host_remote_->TakeFocus(reverse); - } else { - DCHECK(remote_main_frame_host_remote_); - remote_main_frame_host_remote_->TakeFocus(reverse); - } -} - -void WebViewImpl::Show(const LocalFrameToken& opener_frame_token, - NavigationPolicy policy, - const gfx::Rect& requested_rect, - const gfx::Rect& adjusted_rect, - bool opened_by_user_gesture) { - // This is only called on local main frames. - DCHECK(local_main_frame_host_remote_); - DCHECK(web_widget_); - web_widget_->SetPendingWindowRect(adjusted_rect); - const WebWindowFeatures& web_window_features = page_->GetWindowFeatures(); - mojom::blink::WindowFeaturesPtr window_features = - mojom::blink::WindowFeatures::New(); - window_features->bounds = requested_rect; - window_features->has_x = web_window_features.x_set; - window_features->has_y = web_window_features.y_set; - window_features->has_width = web_window_features.width_set; - window_features->has_height = web_window_features.height_set; - window_features->is_popup = web_window_features.is_popup; - local_main_frame_host_remote_->ShowCreatedWindow( - opener_frame_token, NavigationPolicyToDisposition(policy), - std::move(window_features), opened_by_user_gesture, - WTF::BindOnce(&WebViewImpl::DidShowCreatedWindow, WTF::Unretained(this))); - - MainFrameDevToolsAgentImpl()->DidShowNewWindow(); -} - -void WebViewImpl::DidShowCreatedWindow() { - web_widget_->AckPendingWindowRect(); -} - -void WebViewImpl::SendWindowRectToMainFrameHost( - const gfx::Rect& bounds, - base::OnceClosure ack_callback) { - DCHECK(local_main_frame_host_remote_); - local_main_frame_host_remote_->SetWindowRect(bounds, std::move(ack_callback)); -} - -void WebViewImpl::DidAccessInitialMainDocument() { - DCHECK(local_main_frame_host_remote_); - local_main_frame_host_remote_->DidAccessInitialMainDocument(); -} - -void WebViewImpl::UpdateTargetURL(const WebURL& url, - const WebURL& fallback_url) { - KURL latest_url = KURL(url.IsEmpty() ? fallback_url : url); - if (latest_url == target_url_) - return; - - // Tell the browser to display a destination link. - if (target_url_status_ == TARGET_INFLIGHT || - target_url_status_ == TARGET_PENDING) { - // If we have a request in-flight, save the URL to be sent when we - // receive an ACK to the in-flight request. We can happily overwrite - // any existing pending sends. - pending_target_url_ = latest_url; - target_url_status_ = TARGET_PENDING; - } else { - // URLs larger than |kMaxURLChars| cannot be sent through IPC - - // see |ParamTraits|. - if (latest_url.GetString().length() > url::kMaxURLChars) - latest_url = KURL(); - SendUpdatedTargetURLToBrowser(latest_url); - target_url_ = latest_url; - target_url_status_ = TARGET_INFLIGHT; - } -} - -void WebViewImpl::SendUpdatedTargetURLToBrowser(const KURL& target_url) { - // Note: WTF::Unretained() usage below is safe, since `this` owns both - // `mojo::Remote` objects. - if (GetPage()->MainFrame()->IsLocalFrame()) { - DCHECK(local_main_frame_host_remote_); - local_main_frame_host_remote_->UpdateTargetURL( - target_url, WTF::BindOnce(&WebViewImpl::TargetURLUpdatedInBrowser, - WTF::Unretained(this))); - } else { - DCHECK(remote_main_frame_host_remote_); - remote_main_frame_host_remote_->UpdateTargetURL( - target_url, WTF::BindOnce(&WebViewImpl::TargetURLUpdatedInBrowser, - WTF::Unretained(this))); - } -} - -void WebViewImpl::TargetURLUpdatedInBrowser() { - // Check if there is a targeturl waiting to be sent. - if (target_url_status_ == TARGET_PENDING) - SendUpdatedTargetURLToBrowser(pending_target_url_); - - target_url_status_ = TARGET_NONE; -} - -float WebViewImpl::DefaultMinimumPageScaleFactor() const { - return GetPageScaleConstraintsSet().DefaultConstraints().minimum_scale; -} - -float WebViewImpl::DefaultMaximumPageScaleFactor() const { - return GetPageScaleConstraintsSet().DefaultConstraints().maximum_scale; -} - -float WebViewImpl::MinimumPageScaleFactor() const { - return GetPageScaleConstraintsSet().FinalConstraints().minimum_scale; -} - -float WebViewImpl::MaximumPageScaleFactor() const { - return GetPageScaleConstraintsSet().FinalConstraints().maximum_scale; -} - -void WebViewImpl::ResetScaleStateImmediately() { - GetPageScaleConstraintsSet().SetNeedsReset(true); -} - -void WebViewImpl::ResetScrollAndScaleState() { - GetPage()->GetVisualViewport().Reset(); - - auto* main_local_frame = DynamicTo(GetPage()->MainFrame()); - if (!main_local_frame) - return; - - if (LocalFrameView* frame_view = main_local_frame->View()) { - ScrollableArea* scrollable_area = frame_view->LayoutViewport(); - - if (!scrollable_area->GetScrollOffset().IsZero()) { - scrollable_area->SetScrollOffset(ScrollOffset(), - mojom::blink::ScrollType::kProgrammatic); - } - } - - if (Document* document = main_local_frame->GetDocument()) { - if (DocumentLoader* loader = document->Loader()) { - if (HistoryItem* item = loader->GetHistoryItem()) - item->ClearViewState(); - } - } - - GetPageScaleConstraintsSet().SetNeedsReset(true); -} - -void WebViewImpl::SendResizeEventForMainFrame() { - // FIXME: This is wrong. The LocalFrameView is responsible sending a - // resizeEvent as part of layout. Layout is also responsible for sending - // invalidations to the embedder. This method and all callers may be wrong. -- - // eseidel. - if (MainFrameImpl()->GetFrameView()) { - // Enqueues the resize event. - MainFrameImpl()->GetFrame()->GetDocument()->EnqueueResizeEvent(); - } - - // A resized main frame can change the page scale limits. - if (does_composite_) { - auto& viewport = GetPage()->GetVisualViewport(); - MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits( - viewport.Scale(), viewport.IsPinchGestureActive(), - MinimumPageScaleFactor(), MaximumPageScaleFactor()); - } -} - -void WebViewImpl::ConfigureAutoResizeMode() { - if (!MainFrameImpl() || !MainFrameImpl()->GetFrame() || - !MainFrameImpl()->GetFrame()->View()) - return; - - if (should_auto_resize_) { - MainFrameImpl()->GetFrame()->View()->EnableAutoSizeMode(min_auto_size_, - max_auto_size_); - } else { - MainFrameImpl()->GetFrame()->View()->DisableAutoSizeMode(); - } -} - -void WebViewImpl::SetCompositorDeviceScaleFactorOverride( - float device_scale_factor) { - if (compositor_device_scale_factor_override_ == device_scale_factor) - return; - compositor_device_scale_factor_override_ = device_scale_factor; - if (zoom_factor_for_device_scale_factor_) { - SetZoomLevel(ZoomLevel()); - return; - } -} - -void WebViewImpl::SetDeviceEmulationTransform(const gfx::Transform& transform) { - if (transform == device_emulation_transform_) - return; - device_emulation_transform_ = transform; - UpdateDeviceEmulationTransform(); -} - -gfx::Transform WebViewImpl::GetDeviceEmulationTransform() const { - return device_emulation_transform_; -} - -void WebViewImpl::EnableDeviceEmulation(const DeviceEmulationParams& params) { - web_widget_->EnableDeviceEmulation(params); -} - -void WebViewImpl::ActivateDevToolsTransform( - const DeviceEmulationParams& params) { - gfx::Transform device_emulation_transform = - dev_tools_emulator_->EnableDeviceEmulation(params); - SetDeviceEmulationTransform(device_emulation_transform); -} - -void WebViewImpl::DisableDeviceEmulation() { - web_widget_->DisableDeviceEmulation(); -} - -void WebViewImpl::DeactivateDevToolsTransform() { - dev_tools_emulator_->DisableDeviceEmulation(); - SetDeviceEmulationTransform(gfx::Transform()); -} - -void WebViewImpl::PerformCustomContextMenuAction(unsigned action) { - if (page_) { - page_->GetContextMenuController().CustomContextMenuItemSelected(action); - } -} - -void WebViewImpl::DidCloseContextMenu() { - LocalFrame* frame = page_->GetFocusController().FocusedFrame(); - if (frame) - frame->Selection().SetCaretBlinkingSuspended(false); -} - -SkColor WebViewImpl::BackgroundColor() const { - if (background_color_override_for_fullscreen_controller_) - return background_color_override_for_fullscreen_controller_.value(); - Page* page = page_.Get(); - if (!page) - return BaseBackgroundColor().Rgb(); - if (auto* main_local_frame = DynamicTo(page->MainFrame())) { - LocalFrameView* view = main_local_frame->View(); - if (view) - return view->DocumentBackgroundColor().Rgb(); - } - return BaseBackgroundColor().Rgb(); -} - -Color WebViewImpl::BaseBackgroundColor() const { - if (override_base_background_color_to_transparent_) - return Color::kTransparent; - // TODO(https://crbug.com/1351544): The base background color override should - // be an SkColor4f or a Color. - if (base_background_color_override_for_inspector_) { - return Color::FromSkColor( - base_background_color_override_for_inspector_.value()); - } - // Use the page background color if this is the WebView of the main frame. - if (MainFrameImpl()) - return Color::FromSkColor(page_base_background_color_); - return Color::kWhite; -} - -void WebViewImpl::SetPageBaseBackgroundColor(absl::optional color) { - SkColor new_color = color.value_or(SK_ColorWHITE); - if (page_base_background_color_ == new_color) - return; - page_base_background_color_ = new_color; - UpdateBaseBackgroundColor(); -} - -void WebViewImpl::SetBaseBackgroundColorOverrideTransparent( - bool override_to_transparent) { - DCHECK(does_composite_); - if (override_base_background_color_to_transparent_ == override_to_transparent) - return; - override_base_background_color_to_transparent_ = override_to_transparent; - UpdateBaseBackgroundColor(); -} - -void WebViewImpl::SetBaseBackgroundColorOverrideForInspector( - absl::optional optional_color) { - if (base_background_color_override_for_inspector_ == optional_color) - return; - base_background_color_override_for_inspector_ = optional_color; - UpdateBaseBackgroundColor(); -} - -void WebViewImpl::UpdateBaseBackgroundColor() { - if (MainFrameImpl()) { - // Force lifecycle update to ensure we're good to call - // LocalFrameView::setBaseBackgroundColor(). - MainFrameImpl()->GetFrame()->View()->UpdateAllLifecyclePhasesExceptPaint( - DocumentUpdateReason::kBaseColor); - } - - Color color = BaseBackgroundColor(); - if (auto* local_frame = DynamicTo(page_->MainFrame())) { - LocalFrameView* view = local_frame->View(); - view->UpdateBaseBackgroundColorRecursively(color); - } -} - -void WebViewImpl::UpdateFontRenderingFromRendererPrefs() { -#if !BUILDFLAG(IS_MAC) - skia::LegacyDisplayGlobals::SetCachedPixelGeometry( - gfx::FontRenderParams::SubpixelRenderingToSkiaPixelGeometry( - renderer_preferences_.subpixel_rendering)); -#if BUILDFLAG(IS_WIN) - // Cache the system font metrics in blink. - WebFontRendering::SetMenuFontMetrics( - WebString::FromUTF16(renderer_preferences_.menu_font_family_name), - renderer_preferences_.menu_font_height); - WebFontRendering::SetSmallCaptionFontMetrics( - WebString::FromUTF16( - renderer_preferences_.small_caption_font_family_name), - renderer_preferences_.small_caption_font_height); - WebFontRendering::SetStatusFontMetrics( - WebString::FromUTF16(renderer_preferences_.status_font_family_name), - renderer_preferences_.status_font_height); - WebFontRendering::SetAntialiasedTextEnabled( - renderer_preferences_.should_antialias_text); - WebFontRendering::SetLCDTextEnabled( - renderer_preferences_.subpixel_rendering != - gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE); -#else - WebFontRenderStyle::SetHinting( - RendererPreferencesToSkiaHinting(renderer_preferences_)); - WebFontRenderStyle::SetAutoHint(renderer_preferences_.use_autohinter); - WebFontRenderStyle::SetUseBitmaps(renderer_preferences_.use_bitmaps); - WebFontRenderStyle::SetAntiAlias(renderer_preferences_.should_antialias_text); - WebFontRenderStyle::SetSubpixelRendering( - renderer_preferences_.subpixel_rendering != - gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE); - WebFontRenderStyle::SetSubpixelPositioning( - renderer_preferences_.use_subpixel_positioning); -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. -#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \ - !BUILDFLAG(IS_ANDROID) - if (!renderer_preferences_.system_font_family_name.empty()) { - WebFontRenderStyle::SetSystemFontFamily(blink::WebString::FromUTF8( - renderer_preferences_.system_font_family_name)); - } -#endif // (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && - // !BUILDFLAG(IS_ANDROID) -#endif // BUILDFLAG(IS_WIN) -#endif // !BUILDFLAG(IS_MAC) -} - -void WebViewImpl::ActivatePrerenderedPage( - mojom::blink::PrerenderPageActivationParamsPtr - prerender_page_activation_params, - ActivatePrerenderedPageCallback callback) { - TRACE_EVENT0("navigation", "WebViewImpl::ActivatePrerenderedPage"); - - // From here all new documents will have prerendering false. - GetPage()->SetIsPrerendering(false); - - // Collect local documents. This is because we are about to run the - // prerenderchange event and post-prerendering activation steps on each - // document, which could mutate the frame tree and make iteration over it - // complicated. - HeapVector> child_frame_documents; - Member main_frame_document; - if (auto* local_frame = DynamicTo(GetPage()->MainFrame())) { - main_frame_document = local_frame->GetDocument(); - } - - for (Frame* frame = GetPage()->MainFrame(); frame; - frame = frame->Tree().TraverseNext()) { - if (auto* local_frame = DynamicTo(frame)) { - if (local_frame->GetDocument() != main_frame_document) { - child_frame_documents.push_back(local_frame->GetDocument()); - } - } - } - - // A null `activation_start` is sent to the WebViewImpl that does not host the - // main frame, in which case we expect that it does not have any documents - // since cross-origin documents are not loaded during prerendering. - DCHECK((!main_frame_document && child_frame_documents.size() == 0) || - !prerender_page_activation_params->activation_start.is_null()); - // We also only send view_transition_state to the main frame. - DCHECK(main_frame_document || - !prerender_page_activation_params->view_transition_state); - - if (main_frame_document) { - main_frame_document->ActivateForPrerendering( - *prerender_page_activation_params); - prerender_page_activation_params->view_transition_state.reset(); - } - - // While the spec says to post a task on the networking task source for each - // document, we don't post a task here for simplicity. This allows dispatching - // the event on all documents without a chance for other IPCs from the browser - // to arrive in the intervening time, resulting in an unclear state. - for (auto& document : child_frame_documents) { - document->ActivateForPrerendering(*prerender_page_activation_params); - } - - std::move(callback).Run(); -} - -void WebViewImpl::SetInsidePortal(bool inside_portal) { - GetPage()->SetInsidePortal(inside_portal); - - // We may not have created the frame widget yet but that's ok because it'll - // be created with this value correctly initialized. This can also be null if - // the main frame is remote. - if (web_widget_) - web_widget_->SetIsNestedMainFrameWidget(inside_portal); -} - -void WebViewImpl::RegisterRendererPreferenceWatcher( - CrossVariantMojoRemote - watcher) { - renderer_preference_watchers_.Add(std::move(watcher)); -} - -void WebViewImpl::SetRendererPreferences( - const RendererPreferences& preferences) { - UpdateRendererPreferences(preferences); -} - -const RendererPreferences& WebViewImpl::GetRendererPreferences() const { - return renderer_preferences_; -} - -void WebViewImpl::UpdateRendererPreferences( - const RendererPreferences& preferences) { - std::string old_accept_languages = renderer_preferences_.accept_languages; - renderer_preferences_ = preferences; - - for (auto& watcher : renderer_preference_watchers_) - watcher->NotifyUpdate(renderer_preferences_); - - WebThemeEngineHelper::DidUpdateRendererPreferences(preferences); - UpdateFontRenderingFromRendererPrefs(); - - blink::SetCaretBlinkInterval( - renderer_preferences_.caret_blink_interval.has_value() - ? renderer_preferences_.caret_blink_interval.value() - : base::Milliseconds( - mojom::blink::kDefaultCaretBlinkIntervalInMilliseconds)); - -#if defined(USE_AURA) - if (renderer_preferences_.use_custom_colors) { - SetFocusRingColor(renderer_preferences_.focus_ring_color); - SetSelectionColors(renderer_preferences_.active_selection_bg_color, - renderer_preferences_.active_selection_fg_color, - renderer_preferences_.inactive_selection_bg_color, - renderer_preferences_.inactive_selection_fg_color); - ThemeChanged(); - } -#endif - - if (renderer_preferences_.use_custom_colors) { - SetFocusRingColor(renderer_preferences_.focus_ring_color); - } - - if (old_accept_languages != renderer_preferences_.accept_languages) - AcceptLanguagesChanged(); - - GetSettings()->SetCaretBrowsingEnabled( - renderer_preferences_.caret_browsing_enabled); - -#if BUILDFLAG(IS_OZONE) - GetSettings()->SetSelectionClipboardBufferAvailable( - renderer_preferences_.selection_clipboard_buffer_available); -#endif // BUILDFLAG(IS_OZONE) - - SetExplicitlyAllowedPorts( - renderer_preferences_.explicitly_allowed_network_ports); -} - -void WebViewImpl::SetHistoryOffsetAndLength(int32_t history_offset, - int32_t history_length) { - // -1 <= history_offset < history_length <= kMaxSessionHistoryEntries. - DCHECK_LE(-1, history_offset); - DCHECK_LT(history_offset, history_length); - DCHECK_LE(history_length, kMaxSessionHistoryEntries); - - history_list_offset_ = history_offset; - history_list_length_ = history_length; -} - -void WebViewImpl::SetHistoryListFromNavigation( - int32_t history_offset, - absl::optional history_length) { - if (!history_length.has_value()) { - history_list_offset_ = history_offset; - return; - } - - SetHistoryOffsetAndLength(history_offset, *history_length); -} - -void WebViewImpl::IncreaseHistoryListFromNavigation() { - // Advance our offset in session history, applying the length limit. - // There is now no forward history. - history_list_offset_ = - std::min(history_list_offset_ + 1, kMaxSessionHistoryEntries - 1); - history_list_length_ = history_list_offset_ + 1; -} - -int32_t WebViewImpl::HistoryBackListCount() const { - return std::max(history_list_offset_, 0); -} - -int32_t WebViewImpl::HistoryForwardListCount() const { - return history_list_length_ - HistoryBackListCount() - 1; -} - -void WebViewImpl::SetWebPreferences( - const web_pref::WebPreferences& preferences) { - UpdateWebPreferences(preferences); -} - -const web_pref::WebPreferences& WebViewImpl::GetWebPreferences() { - return web_preferences_; -} - -void WebViewImpl::UpdateWebPreferences( - const blink::web_pref::WebPreferences& preferences) { - web_preferences_ = preferences; - - if (IsFencedFrameRoot()) { - // The main frame of a fenced frame should not behave like a top level - // frame in terms of viewport behavior. i.e. It shouldn't allow zooming, - // either explicitly or to fit content, and it should not interpret the - // viewport tag. Text autosizing is disabled since it is only - // determined by the outermost page and having the outermost page pass - // it into the fenced frame can create a communication channel. - web_preferences_.viewport_enabled = false; - web_preferences_.viewport_meta_enabled = false; - web_preferences_.default_minimum_page_scale_factor = 1.f; - web_preferences_.default_maximum_page_scale_factor = 1.f; - web_preferences_.shrinks_viewport_contents_to_fit = false; - web_preferences_.main_frame_resizes_are_orientation_changes = false; - web_preferences_.text_autosizing_enabled = false; - - // Insecure content should not be allowed in a fenced frame. - web_preferences_.allow_running_insecure_content = false; - -#if BUILDFLAG(IS_ANDROID) - // Reusing the global for unowned main frame is only used for - // Android WebView. Since this is a fenced frame it is not the - // outermost main frame so we can safely disable this feature. - web_preferences_.reuse_global_for_unowned_main_frame = false; -#endif - } - - if (MainFrameImpl()) { - MainFrameImpl()->FrameWidgetImpl()->SetPrefersReducedMotion( - web_preferences_.prefers_reduced_motion); - } - - ApplyWebPreferences(web_preferences_, this); - ApplyCommandLineToSettings(SettingsImpl()); -} - -void WebViewImpl::AddObserver(WebViewObserver* observer) { - observers_.AddObserver(observer); -} - -void WebViewImpl::RemoveObserver(WebViewObserver* observer) { - observers_.RemoveObserver(observer); -} - -void WebViewImpl::SetIsActive(bool active) { - if (GetPage()) - GetPage()->GetFocusController().SetActive(active); -} - -bool WebViewImpl::IsActive() const { - return GetPage() ? GetPage()->GetFocusController().IsActive() : false; -} - -void WebViewImpl::SetWindowFeatures(const WebWindowFeatures& features) { - page_->SetWindowFeatures(features); -} - -void WebViewImpl::SetOpenedByDOM() { - page_->SetOpenedByDOM(); -} - -void WebViewImpl::DidCommitLoad(bool is_new_navigation, - bool is_navigation_within_page) { - if (!is_navigation_within_page) { - if (web_widget_) - web_widget_->ResetMeaningfulLayoutStateForMainFrame(); - - if (is_new_navigation) - GetPageScaleConstraintsSet().SetNeedsReset(true); - } - - // Give the visual viewport's scroll layer its initial size. - GetPage()->GetVisualViewport().MainFrameDidChangeSize(); -} - -void WebViewImpl::DidCommitCompositorFrameForLocalMainFrame() { - for (auto& observer : observers_) - observer.DidCommitCompositorFrame(); -} - -void WebViewImpl::ResizeAfterLayout() { - DCHECK(MainFrameImpl()); - - if (!web_view_client_) - return; - - if (should_auto_resize_) { - LocalFrameView* view = MainFrameImpl()->GetFrame()->View(); - gfx::Size frame_size = view->Size(); - if (frame_size != size_) { - size_ = frame_size; - - GetPage()->GetVisualViewport().SetSize(size_); - GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(size_); - - web_view_client_->DidAutoResize(size_); - web_widget_->DidAutoResize(size_); - SendResizeEventForMainFrame(); - } - } - - if (does_composite_ && GetPageScaleConstraintsSet().ConstraintsDirty()) - RefreshPageScaleFactor(); - - resize_viewport_anchor_->ResizeFrameView(MainFrameSize()); -} - -void WebViewImpl::MainFrameLayoutUpdated() { - DCHECK(MainFrameImpl()); - if (!web_view_client_) - return; - - for (auto& observer : observers_) - observer.DidUpdateMainFrameLayout(); - needs_preferred_size_update_ = true; -} - -void WebViewImpl::DidChangeContentsSize() { - auto* local_frame = DynamicTo(GetPage()->MainFrame()); - if (!local_frame) - return; - - LocalFrameView* view = local_frame->View(); - - int vertical_scrollbar_width = 0; - if (view && view->LayoutViewport()) { - Scrollbar* vertical_scrollbar = view->LayoutViewport()->VerticalScrollbar(); - if (vertical_scrollbar && !vertical_scrollbar->IsOverlayScrollbar()) - vertical_scrollbar_width = vertical_scrollbar->Width(); - } - - GetPageScaleConstraintsSet().DidChangeContentsSize( - ContentsSize(), vertical_scrollbar_width, PageScaleFactor()); -} - -void WebViewImpl::PageScaleFactorChanged() { - // This is called from the VisualViewport which only is used to control the - // page scale/scroll viewport for a local main frame, and only when - // compositing as PageScaleFactor doesn't exist otherwise. - DCHECK(MainFrameImpl()); - DCHECK(does_composite_); - - GetPageScaleConstraintsSet().SetNeedsReset(false); - // Set up the compositor and inform the browser of the PageScaleFactor, - // which is tracked per-view. - auto& viewport = GetPage()->GetVisualViewport(); - DCHECK(viewport.IsActiveViewport()); - MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits( - viewport.Scale(), viewport.IsPinchGestureActive(), - MinimumPageScaleFactor(), MaximumPageScaleFactor()); - - local_main_frame_host_remote_->ScaleFactorChanged(viewport.Scale()); - - if (dev_tools_emulator_->HasViewportOverride()) { - // TODO(bokan): Can HasViewportOverride be set on a nested main frame? If - // not, we can enforce that when setting it and DCHECK IsOutermostMainFrame - // instead. - if (MainFrameImpl()->IsOutermostMainFrame()) { - gfx::Transform device_emulation_transform = - dev_tools_emulator_->OutermostMainFrameScrollOrScaleChanged(); - SetDeviceEmulationTransform(device_emulation_transform); - } - } -} - -void WebViewImpl::OutermostMainFrameScrollOffsetChanged() { - DCHECK(MainFrameImpl()); - DCHECK(MainFrameImpl()->IsOutermostMainFrame()); - if (dev_tools_emulator_->HasViewportOverride()) { - gfx::Transform device_emulation_transform = - dev_tools_emulator_->OutermostMainFrameScrollOrScaleChanged(); - SetDeviceEmulationTransform(device_emulation_transform); - } -} - -void WebViewImpl::TextAutosizerPageInfoChanged( - const mojom::blink::TextAutosizerPageInfo& page_info) { - DCHECK(MainFrameImpl()); - local_main_frame_host_remote_->TextAutosizerPageInfoChanged( - page_info.Clone()); -} - -void WebViewImpl::SetBackgroundColorOverrideForFullscreenController( - absl::optional optional_color) { - DCHECK(does_composite_); - - background_color_override_for_fullscreen_controller_ = optional_color; - if (MainFrameImpl()) { - MainFrameImpl()->FrameWidgetImpl()->SetBackgroundColor(BackgroundColor()); - } -} - -void WebViewImpl::SetZoomFactorOverride(float zoom_factor) { - zoom_factor_override_ = zoom_factor; - SetZoomLevel(ZoomLevel()); -} - -Element* WebViewImpl::FocusedElement() const { - LocalFrame* frame = page_->GetFocusController().FocusedFrame(); - if (!frame) - return nullptr; - - Document* document = frame->GetDocument(); - if (!document) - return nullptr; - - return document->FocusedElement(); -} - -WebHitTestResult WebViewImpl::HitTestResultForTap( - const gfx::Point& tap_point_window_pos, - const gfx::Size& tap_area) { - auto* main_frame = DynamicTo(page_->MainFrame()); - if (!main_frame) - return HitTestResult(); - - WebGestureEvent tap_event(WebInputEvent::Type::kGestureTap, - WebInputEvent::kNoModifiers, base::TimeTicks::Now(), - WebGestureDevice::kTouchscreen); - // GestureTap is only ever from a touchscreen. - tap_event.SetPositionInWidget(gfx::PointF(tap_point_window_pos)); - tap_event.data.tap.tap_count = 1; - tap_event.data.tap.width = tap_area.width(); - tap_event.data.tap.height = tap_area.height(); - - WebGestureEvent scaled_event = - TransformWebGestureEvent(MainFrameImpl()->GetFrameView(), tap_event); - - HitTestResult result = - main_frame->GetEventHandler() - .HitTestResultForGestureEvent( - scaled_event, HitTestRequest::kReadOnly | HitTestRequest::kActive) - .GetHitTestResult(); - - result.SetToShadowHostIfInRestrictedShadowRoot(); - return result; -} - -void WebViewImpl::SetTabsToLinks(bool enable) { - tabs_to_links_ = enable; -} - -bool WebViewImpl::TabsToLinks() const { - return tabs_to_links_; -} - -void WebViewImpl::DidChangeRootLayer(bool root_layer_exists) { - // The Layer is removed when the main frame's `Document` changes. It also is - // removed when the whole `LocalFrame` goes away, in which case we don't - // need to DeferMainFrameUpdate() as we will do so if a local MainFrame is - // attached in the future. - if (!MainFrameImpl()) { - DCHECK(!root_layer_exists); - return; - } - if (root_layer_exists) { - if (!device_emulation_transform_.IsIdentity()) - UpdateDeviceEmulationTransform(); - } else { - // When the document in an already-attached main frame is being replaced by - // a navigation then DidChangeRootLayer(false) will be called. Since we are - // navigating, defer BeginMainFrames until the new document is ready for - // them. - // - // TODO(crbug.com/936696): This should not be needed once we always swap - // frames when swapping documents. - scoped_defer_main_frame_update_ = - MainFrameImpl()->FrameWidgetImpl()->DeferMainFrameUpdate(); - } -} - -void WebViewImpl::InvalidateContainer() { - // This is only for non-composited WebViewPlugin. - if (!does_composite_ && web_view_client_) - web_view_client_->InvalidateContainer(); -} - -void WebViewImpl::ApplyViewportChanges(const ApplyViewportChangesArgs& args) { - // TODO(https://crbug.com/1160652): Figure out if Page is null. - CHECK(page_); - - VisualViewport& visual_viewport = GetPage()->GetVisualViewport(); - DCHECK(visual_viewport.IsActiveViewport()); - - // Store the desired offsets the visual viewport before setting the top - // controls ratio since doing so will change the bounds and move the - // viewports to keep the offsets valid. The compositor may have already - // done that so we don't want to double apply the deltas here. - gfx::PointF visual_viewport_offset = visual_viewport.VisibleRect().origin(); - visual_viewport_offset.Offset(args.inner_delta.x(), args.inner_delta.y()); - - GetBrowserControls().SetShownRatio( - GetBrowserControls().TopShownRatio() + args.top_controls_delta, - GetBrowserControls().BottomShownRatio() + args.bottom_controls_delta); - - SetPageScaleFactorAndLocation(PageScaleFactor() * args.page_scale_delta, - args.is_pinch_gesture_active, - visual_viewport_offset); - - if (args.page_scale_delta != 1) { - double_tap_zoom_pending_ = false; - } - - elastic_overscroll_ += args.elastic_overscroll_delta; - UpdateBrowserControlsConstraint(args.browser_controls_constraint); - - if (args.scroll_gesture_did_end) { - // TODO(https://crbug.com/1160652): Figure out if MainFrameImpl is null. - CHECK(MainFrameImpl()); - MainFrameImpl()->GetFrame()->GetEventHandler().MarkHoverStateDirty(); - } -} - -Node* WebViewImpl::FindNodeFromScrollableCompositorElementId( - cc::ElementId element_id) const { - if (!GetPage()) - return nullptr; - - if (element_id == GetPage()->GetVisualViewport().GetScrollElementId()) { - // Return the Document in this case since the window.visualViewport DOM - // object is not a node. - if (MainFrameImpl()) - return MainFrameImpl()->GetDocument(); - } - - if (!GetPage()->GetScrollingCoordinator()) - return nullptr; - ScrollableArea* scrollable_area = - GetPage() - ->GetScrollingCoordinator() - ->ScrollableAreaWithElementIdInAllLocalFrames(element_id); - if (!scrollable_area || !scrollable_area->GetLayoutBox()) - return nullptr; - - return scrollable_area->GetLayoutBox()->GetNode(); -} - -void WebViewImpl::UpdateDeviceEmulationTransform() { - if (GetPage()->GetVisualViewport().IsActiveViewport()) - GetPage()->GetVisualViewport().SetNeedsPaintPropertyUpdate(); - - if (auto* main_frame = MainFrameImpl()) { - // When the device emulation transform is updated, to avoid incorrect - // scales and fuzzy raster from the compositor, force all content to - // pick ideal raster scales. - // TODO(wjmaclean): This is only done on the main frame's widget currently, - // it should update all local frames. - main_frame->FrameWidgetImpl()->SetNeedsRecalculateRasterScales(); - - // Device emulation transform also affects the overriding visible rect - // which is used as the overflow rect of the main frame layout view. - if (auto* view = main_frame->GetFrameView()) - view->SetNeedsPaintPropertyUpdate(); - } -} - -PageScheduler* WebViewImpl::Scheduler() const { - DCHECK(GetPage()); - return GetPage()->GetPageScheduler(); -} - -void WebViewImpl::SetVisibilityState( - mojom::blink::PageVisibilityState visibility_state, - bool is_initial_state) { - DCHECK(GetPage()); - GetPage()->SetVisibilityState(visibility_state, is_initial_state); - GetPage()->GetPageScheduler()->SetPageVisible( - visibility_state == mojom::blink::PageVisibilityState::kVisible); - // Notify observers of the change. - if (!is_initial_state) { - for (auto& observer : observers_) - observer.OnPageVisibilityChanged(visibility_state); - } -} - -mojom::blink::PageVisibilityState WebViewImpl::GetVisibilityState() { - DCHECK(GetPage()); - return GetPage()->GetVisibilityState(); -} - -LocalFrame* WebViewImpl::FocusedLocalFrameInWidget() const { - if (!MainFrameImpl()) - return nullptr; - - auto* focused_frame = To(FocusedCoreFrame()); - if (focused_frame->LocalFrameRoot() != MainFrameImpl()->GetFrame()) - return nullptr; - return focused_frame; -} - -void WebViewImpl::SetPageFrozen(bool frozen) { - Scheduler()->SetPageFrozen(frozen); -} - -WebFrameWidget* WebViewImpl::MainFrameWidget() { - return web_widget_; -} - -void WebViewImpl::AddAutoplayFlags(int32_t value) { - page_->AddAutoplayFlags(value); -} - -void WebViewImpl::ClearAutoplayFlags() { - page_->ClearAutoplayFlags(); -} - -int32_t WebViewImpl::AutoplayFlagsForTest() { - return page_->AutoplayFlags(); -} - -gfx::Size WebViewImpl::GetPreferredSizeForTest() { - return preferred_size_in_dips_; -} - -void WebViewImpl::StopDeferringMainFrameUpdate() { - scoped_defer_main_frame_update_ = nullptr; -} - -void WebViewImpl::SetDeviceColorSpaceForTesting( - const gfx::ColorSpace& color_space) { - web_widget_->SetDeviceColorSpaceForTesting(color_space); -} - -const SessionStorageNamespaceId& WebViewImpl::GetSessionStorageNamespaceId() { - CHECK(!session_storage_namespace_id_.empty()); - return session_storage_namespace_id_; -} - -bool WebViewImpl::IsFencedFrameRoot() const { - return GetPage()->IsMainFrameFencedFrameRoot(); -} - -void WebViewImpl::MojoDisconnected() { - // This IPC can be called from re-entrant contexts. We can't destroy a - // RenderViewImpl while references still exist on the stack, so we dispatch a - // non-nestable task. This method is called exactly once by the browser - // process, and is used to release ownership of the corresponding - // RenderViewImpl instance. https://crbug.com/1000035. - GetPage()->GetAgentGroupScheduler().DefaultTaskRunner()->PostNonNestableTask( - FROM_HERE, WTF::BindOnce(&WebViewImpl::Close, WTF::Unretained(this))); -} - -void WebViewImpl::CreateRemoteMainFrame( - const RemoteFrameToken& frame_token, - const absl::optional& opener_frame_token, - mojom::blink::FrameReplicationStatePtr replicated_state, - bool is_loading, - const base::UnguessableToken& devtools_frame_token, - mojom::blink::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces, - mojom::blink::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) { - blink::WebFrame* opener = nullptr; - if (opener_frame_token) - opener = WebFrame::FromFrameToken(*opener_frame_token); - // Create a top level WebRemoteFrame. - WebRemoteFrameImpl::CreateMainFrame( - this, frame_token, is_loading, devtools_frame_token, opener, - std::move(remote_frame_interfaces->frame_host), - std::move(remote_frame_interfaces->frame_receiver), - std::move(replicated_state)); - // Root frame proxy has no ancestors to point to their RenderWidget. - - // The WebRemoteFrame created here was already attached to the Page as its - // main frame, so we can call WebView's DidAttachRemoteMainFrame(). - DidAttachRemoteMainFrame( - std::move(remote_main_frame_interfaces->main_frame_host), - std::move(remote_main_frame_interfaces->main_frame)); -} - -scheduler::WebAgentGroupScheduler& WebViewImpl::GetWebAgentGroupScheduler() { - return web_agent_group_scheduler_; -} - -void WebViewImpl::UpdatePageBrowsingContextGroup( - const BrowsingContextGroupInfo& browsing_context_group_info) { - Page* page = GetPage(); - CHECK(page); - - page->UpdateBrowsingContextGroup(browsing_context_group_info); -} - -} // namespace blink diff --git a/src/tools/cfi/ignores.txt b/src/tools/cfi/ignores.txt index d57aa2f2..b1c788cc 100644 --- a/src/tools/cfi/ignores.txt +++ b/src/tools/cfi/ignores.txt @@ -1,7 +1,21 @@ -# Copyright RobRich999 +# Copyright RobRich999 and Alex313031 # This file defines which warnings should be ignored while running clang's # control flow integrity sanitizer, as run by the cfi_flags build target. +# ***If you think you need to add an entry here, read this comment first.*** +# +# Generally prefer to add an attribute to whichever function needs it, instead +# of adding entries to this file. This can be done in the Chromium codebase +# using the NO_SANITIZE macro, e.g. +# +# NO_SANITIZE("cfi-unrelated-cast") +# +# or outside of Chromium using the no_sanitize attribute directly (potentially +# with guards against non-Clang compilers; see the definition of NO_SANITIZE in +# Chromium), e.g. +# +# __attribute__((no_sanitize("cfi-unrelated-cast"))) + [cfi-unrelated-cast|cfi-derived-cast] # e.g. RolloverProtectedTickClock @@ -245,6 +259,10 @@ fun:*GlobalHandles*PostGarbageCollectionProcessing* fun:*InvokeAccessorGetterCallback* +# XNNPACK casts incorrect function signature to pthreadpool task type. +src:*third_party/pthreadpool/src/src/fastpath.c +src:*third_party/pthreadpool/src/src/portable-api.c + ######### Uncategorized src:*native_client/* diff --git a/src/ui/gtk/native_theme_gtk.cc b/src/ui/gtk/native_theme_gtk.cc index bd593f60..68b66d6a 100644 --- a/src/ui/gtk/native_theme_gtk.cc +++ b/src/ui/gtk/native_theme_gtk.cc @@ -48,8 +48,7 @@ SkBitmap GetWidgetBitmap(const gfx::Size& size, CairoSurface surface(bitmap); cairo_t* cr = surface.cairo(); - double opacity = 1; - GtkStyleContextGet(context, "opacity", &opacity, nullptr); + double opacity = GetOpacityFromContext(context); if (opacity < 1) cairo_push_group(cr);
$i18n{application_label}