M117 stage 7

This commit is contained in:
Alexander Frick 2023-10-08 10:45:40 -05:00
parent 68235158ca
commit 1bf95e7e4d
34 changed files with 803 additions and 5706 deletions

View File

@ -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

View File

@ -42,24 +42,30 @@ namespace media {
namespace {
template <typename T>
class SupplementalProfileCache {
public:
void UpdateCache(const base::flat_set<media::VideoCodecProfile>& profiles) {
void UpdateCache(const base::flat_set<T>& 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<media::VideoCodecProfile> profiles_ GUARDED_BY(profiles_lock_);
base::flat_set<T> profiles_ GUARDED_BY(profiles_lock_);
};
SupplementalProfileCache* GetSupplementalProfileCache() {
static base::NoDestructor<SupplementalProfileCache> cache;
SupplementalProfileCache<VideoCodecProfile>* GetSupplementalProfileCache() {
static base::NoDestructor<SupplementalProfileCache<VideoCodecProfile>> cache;
return cache.get();
}
SupplementalProfileCache<AudioType>* GetSupplementalAudioTypeCache() {
static base::NoDestructor<SupplementalProfileCache<AudioType>> 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<AudioType>& types) {
GetSupplementalAudioTypeCache()->UpdateCache(types);
}
} // namespace media

View File

@ -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<media::VideoCodecProfile>& 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<media::VideoCodecProfile> profiles_ GUARDED_BY(profiles_lock_);
};
SupplementalProfileCache* GetSupplementalProfileCache() {
static base::NoDestructor<SupplementalProfileCache> 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<media::VideoCodecProfile>& profiles) {
GetSupplementalProfileCache()->UpdateCache(profiles);
}
} // namespace media

View File

@ -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<uint8_t> 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<AVCodecContext, ScopedPtrAVFreeContext>
AVStreamToAVCodecContext(const AVStream* stream) {
std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> 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<AVCodecContext, ScopedPtrAVFreeContext> 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<uint8_t*>(
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<AVCodecContext, ScopedPtrAVFreeContext> 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<int32_t*>(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<uint8_t> 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<AVMasteringDisplayMetadata*>(side_data.data);
gfx::HdrMetadataSmpteSt2086 smpte_st_2086;
if (metadata->has_primaries) {
smpte_st_2086.primaries = {
static_cast<float>(av_q2d(metadata->display_primaries[0][0])),
static_cast<float>(av_q2d(metadata->display_primaries[0][1])),
static_cast<float>(av_q2d(metadata->display_primaries[1][0])),
static_cast<float>(av_q2d(metadata->display_primaries[1][1])),
static_cast<float>(av_q2d(metadata->display_primaries[2][0])),
static_cast<float>(av_q2d(metadata->display_primaries[2][1])),
static_cast<float>(av_q2d(metadata->white_point[0])),
static_cast<float>(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<uint8_t*>(
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

View File

@ -190,6 +190,7 @@
<DL><p>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:chrome/android/java/;bpv=1" ADD_DATE="1661397969" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">java - Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:chrome/android/BUILD.gn;bpv=1" ADD_DATE="1661403168" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">BUILD.gn - Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:chrome/android/chrome_public_apk_tmpl.gni;bpv=1" ADD_DATE="1661403168" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">chrome_public_apk_tmpl.gni - Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:chrome/browser/ui/android/strings/android_chrome_strings.grd;bpv=1" ADD_DATE="1662075000" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">android_chrome_strings.grd - Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:ui/gtk/native_theme_gtk.cc;l=1;bpv=1" ADD_DATE="1662209503" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">native_theme_gtk.cc - Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:components/version_ui/resources/about_version.html;bpv=1" ADD_DATE="1662210918" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">about_version.html - Chromium Code Search</A>
@ -213,7 +214,6 @@
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:chrome/browser/feed/android/java/res/layout/new_tab_page_feed_v2_expandable_header.xml;bpv=1" ADD_DATE="1691750085" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">new_tab_page_feed_v2_expandable_header.xml - Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:chrome/browser/feed/android/java/res/layout/new_tab_page_multi_feed_header.xml;bpv=1" ADD_DATE="1691750109" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">new_tab_page_multi_feed_header.xml - Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:components/feed/core/shared_prefs/pref_names.cc;bpv=1" ADD_DATE="1691750173" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">pref_names.cc - Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromium/chromium/src/+/refs/tags/117.0.5938.157:third_party/blink/renderer/core/exported/web_view_impl.cc;bpv=1" ADD_DATE="1691825544" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">web_view_impl.cc - Chromium Code Search</A>
</DL><p>
<DT><A HREF="https://source.chromium.org/" ADD_DATE="1661054752" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">Chromium Code Search</A>
<DT><A HREF="https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/overlays/overlay-amd64-generic/;bpv=1" ADD_DATE="1661054752" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVQ4jW1TXWwUZRQ955ufnZ3dlm4VpE2Q+lND1cSQYDBaKY2VEkUFa1d9K4laBROEIg+mDfvkg5Bu9MWoD/hkTJdqJBFCMRENEqONRkMbIiWGWn5SjWw7OzO7szPf9UFCCnrebu7JuTc55xA3QURYKkEtXw7+1gDm0mDWBtMm+GcAnb+P0VI+lw4fTIp7C6O7dU3nlKFyisxp0TmDRpMmmyDSCqLY96D1HUQIUsxrd9nfD3VrHDbDTi/ENi5V/TCdtmlQ0Y60dmwANNXT0HpodEx+2kNUb/4e45PSUhBR/1lcw6Gvf3fGf4gmJn6NBgGgUBBFAHj+vepdKSvp2r5m/pPu7juqA4fEOTcXvhaG2KAMVjOp5MjJ4eynBOTIz7Vnzs5Jcfoiej9+1TlHAHjyneArKrl/XcVtnQLcS/A/b23J9DzUBgQRcPo84JX90VOF7JCIGFsOBLMCTB/dl3lc9b+7uA1O+jHb4OuFAvVl+oOtLZmekc1JbUc36nt7pb6zK0mslL2n6+3wUZJJyuIuOm7Ps8Xyc8qP3Q+TMDj+2W73MABUatK5vg26vcVQf3navOqL+Ui7kay53dJeEG8AgPE33PEkDI6HSfZ9BRFAQJF/LSVYDSIQEBiKsE0lsRaGNSiTEl43X4SAQKWN8GUj427qG/XyAJB15IvTM+CJKW04FuoiEpd+1Grmj8BvzPIYAGwten2mm9mUsauDBIAnDvgnAHQMrHZX5/NMOguLBy07NXTPKhvVGnDhb0BH3pvfDjcelDExnpoNLormmS/3uT0KAFY0xDs2dhiLqXZsBoBThca9QK1z8mxlZPpCZZeq+2dMqi2AcGYtzOZG9dayrHoFACgiJCkTU9FAJZCtCxX7he3dvCFl60b8ta6lh2/T2Rdf2oam3gc4f2MXRLi7NOd0tq34iFS/aNFHIwBhJLGVSLRqZd3rWNYQfj+L5igOdb6YvoISNEC5LgBSDk9G6ynYScgVrbGgFMsQKSdiLIhIWSe6rGifzz/M8H/bCABjU2L781BeOCMrK5FcvfNeuexB8M1J7N+/MSEpS/n/AGH0clblBN69AAAAAElFTkSuQmCC">overlay-amd64-generic - Chromium Code Search</A>

View File

@ -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 &&

View File

@ -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) {

View File

@ -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)" ]
}

View File

@ -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.

View File

@ -204,6 +204,11 @@ CHAR_LIMIT guidelines:
<messages fallback_to_english="true">
<!-- NOTE: Generic strings used across multiple features belong in //components/browser_ui/strings/android. -->
<!-- Cookie Controls -->
<message name="IDS_COOKIE_CONTROLS_IPH_MESSAGE" desc="In-context Product Help - Appears right under the page info icon to highlight the Cookie Controls entrypoint.">
Site not working? Third-party cookies are blocked
</message>
<!-- Main Preferences -->
<message name="IDS_PREFS_SECTION_BASICS" desc='Title of "Basics" section of preferences. [CHAR_LIMIT=32]'>
Basics
@ -521,12 +526,6 @@ CHAR_LIMIT guidelines:
<message name="IDS_AUTOFILL_DESCRIBE_LOCAL_COPY" desc="Text label that describes a Wallet credit card which has been copied to the local Thorium instance.">
Copied to Thorium
</message>
<message name="IDS_AUTOFILL_PAYMENTS_AUTHENTICATOR_SELECTION_DIALOG_TITLE" desc="Title for the dialog where the user selects an authenticator from a list of options.">
Verify your card
</message>
<message name="IDS_AUTOFILL_PAYMENTS_AUTHENTICATOR_SELECTION_DIALOG_HEADER" desc="Header for the dialog where the user selects an authenticator from a list of options.">
Your bank wants to confirm it\u2019s you.
</message>
<message name="IDS_AUTOFILL_PAYMENTS_AUTHENTICATOR_SELECTION_DIALOG_FOOTER" desc="Footer for the dialog where the user selects an authenticator from a list of options.">
Not seeing your current info? Please contact your bank to update it.
</message>
@ -557,6 +556,10 @@ CHAR_LIMIT guidelines:
<message name="IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_OFF_BUTTON_LABEL" desc="Label shown on the button that the user clicks on to unenroll from virtual cards.">
Turn off
</message>
<!-- TODO(crbug.com/1425882): Use finalized string.-->
<message translateable="false" name="IDS_AUTOFILL_OPTIONS_TITLE" desc="Description below switch toggling the use of third-party autofill in Thorium." formatter_data="android_java">
Autofill Options
</message>
<!-- Payment Request section preview strings -->
<message name="IDS_PAYMENT_REQUEST_PAYMENT_METHODS_PREVIEW" desc="This is a snippet of a payment method a user has saved to Thorium, plus an indication of the number of additional payment methods the user has saved.
@ -582,11 +585,11 @@ CHAR_LIMIT guidelines:
</message>
<!-- Password Manager -->
<message name="IDS_PASSWORD_SETTINGS_TITLE" desc="Title for the settings screen with saved passwords and the header for the list of saved passwords in that screen. [CHAR_LIMIT=32]">
<message name="IDS_PASSWORD_LIST_TITLE" desc="Title for a list of saved passwords, e.g. the list of passwords displayed in Thorium > Settings > Password Manager. [CHAR_LIMIT=32]">
Passwords
</message>
<message name="IDS_PASSWORD_SETTINGS_TITLE_GPM" desc="Title for the settings menu item leading to the Password Manager UI surface. This allows users to e.g. manage their saved passwords, toggle saving and auto-sign-in on/off, etc. The NEW label is displayed until the user clicks on this menu item at least once. [CHAR_LIMIT=32]">
Password Manager <ph name="BEGIN_NEW">&lt;new&gt;</ph>New<ph name="END_NEW">&lt;/new&gt;</ph>
<message name="IDS_PASSWORD_MANAGER_SETTINGS_TITLE" desc="Title for the settings menu item leading to the Password Manager UI surface. This allows users to e.g. manage their saved passwords, toggle saving and auto-sign-in on/off, etc. [CHAR_LIMIT=32]">
Password Manager
</message>
<message name="IDS_PASSWORD_SETTINGS_SAVE_PASSWORDS" desc="Title for the checkbox toggling whether passwords are saved or not. [CHAR_LIMIT=32]">
Save passwords
@ -600,6 +603,12 @@ CHAR_LIMIT guidelines:
<message name="IDS_PASSWORDS_LEAK_DETECTION_SWITCH_TITLE" desc="Title for the switch toggling whether Thorium should check that entered credentials have been part of a leak.">
Warn you if passwords are exposed in a data breach
</message>
<message name="IDS_PASSWORDS_LEAK_DETECTION_SWITCH_TITLE_UPDATED" desc="Title for the switch toggling whether Thorium should check that entered credentials have been part of a leak.">
Warn you if a password was compromised in a data breach
</message>
<message name="IDS_PASSWORDS_LEAK_DETECTION_SWITCH_SUMMARY" desc="Summary for the switch toggling whether Thorium should check that entered credentials have been part of a leak.">
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 cant be read by anyone, including Google.
</message>
<message name="IDS_PASSWORDS_CHECK_TITLE" desc="Title for the check passwords button which allows to check whether the user's passwords have been compromised.">
Check passwords
</message>
@ -739,7 +748,7 @@ CHAR_LIMIT guidelines:
Were changing how passwords are saved on this device
</message>
<message name="IDS_PASSWORD_MIGRATION_WARNING_SUBTITLE" desc="The subtitle of the password migration warning sheet." formatter_data="android_java">
Your lists of saved passwords for Thorium and Thorium <ph name="ERROR_DESCRIPTION">%1$s<ex>Dev</ex></ph> will merge after version 121. Youll 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 <ph name="CHROME_CHANNEL">%1$s<ex>Thorium Dev</ex></ph> will be merged and can be used in both apps.
</message>
<message name="IDS_PASSWORD_MIGRATION_WARNING_ACKNOWLEDGE" desc="The text on the button that acknowledges the password migration warning.">
Got it
@ -763,7 +772,7 @@ CHAR_LIMIT guidelines:
Export &amp; delete passwords saved to this device
</message>
<message name="IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT_SUBTITLE" desc="The subtitle that explaint the password export option in the password migration warning sheet.">
All passwords will be downloaded on your device and removed from Thorium <ph name="CHROME_CHANNEL">%1$s<ex>Dev</ex></ph>
All passwords will be downloaded on your device and removed from <ph name="CHROME_CHANNEL">%1$s<ex>Thorium Dev</ex></ph>
</message>
<message name="IDS_PASSWORD_MIGRATION_WARNING_NEXT" desc="The text for the next button in the password migration warning sheet. It starts one of the flows offered on the sheet.">
Next
@ -774,12 +783,27 @@ CHAR_LIMIT guidelines:
<message name="IDS_EXPORTED_PASSWORDS_DELETION_DIALOG_TITLE" desc="The title of the dialog that offers to delete passwords from Google Password Manager." formatter_data="android_java">
Delete passwords from Google Password Manager?
</message>
<message name="IDS_EXPORTED_PASSWORDS_DELETION_IN_PROGRESS_TITLE" desc="The title of the progress bar that is visible while the passwords are being deleted." formatter_data="android_java">
Deleting
</message>
<message name="IDS_PASSWORDS_EXPORT_IN_PROGRESS_TITLE" desc="The title of the progress bar that is visible while the passwords are being exported." formatter_data="android_java">
Exporting
</message>
<message name="IDS_EXPORTED_PASSWORDS_DELETION_DIALOG_TEXT" desc="The text that describes the option to delete the passwords that were just exported." formatter_data="android_java">
Your passwords will be deleted from Google Password Manager for Thorium <ph name="CHROME_CHANNEL">%1$s<ex>Dev</ex></ph>. You will keep the passwords file you just downloaded.
Your passwords will be deleted from Google Password Manager for <ph name="CHROME_CHANNEL">%1$s<ex>Thorium Dev</ex></ph>. You will keep the passwords file you just downloaded.
</message>
<message name="IDS_EXPORTED_PASSWORDS_DELETE_BUTTON" desc="The text on the button that confirms the action of deleting the passwords that were exported." formatter_data="android_java">
Delete passwords
</message>
<message name="IDS_CHROME_CHANNEL_NAME_CANARY" desc="The Thorium channel name for canary channel">
Thorium Canary
</message>
<message name="IDS_CHROME_CHANNEL_NAME_DEV" desc="The Thorium channel name for dev channel">
Thorium Dev
</message>
<message name="IDS_CHROME_CHANNEL_NAME_BETA" desc="The Thorium channel name for beta channel">
Thorium Beta
</message>
<!-- Lock Screen Fragment -->
<message name="IDS_LOCKSCREEN_DESCRIPTION_COPY" desc="When a user attempts to copy a password for a particular website into clipboard in Thorium's settings, Thorium launches a lock screen to verify the user's identity and displays the following explanation.">
@ -1197,10 +1221,10 @@ Private state tokens improve privacy on the web and cant be used to find out
You can block sites you dont want. Thorium also auto-deletes sites from the list that are older than 30 days. <ph name="BEGIN_LINK">&lt;link&gt;</ph>Learn more<ph name="END_LINK">&lt;/link&gt;</ph>
</message>
<message name="IDS_SETTINGS_FLEDGE_PAGE_CURRENT_SITES_DESCRIPTION_DISABLED" desc="1 of 3 possible descriptions that appear beneath the 'Sites' title. If this setting is off, no sites appear. The link opens a dialog box that provides more information about Site-suggested ads.">
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
</message>
<message name="IDS_SETTINGS_FLEDGE_PAGE_CURRENT_SITES_DESCRIPTION_EMPTY" desc="1 of 3 possible descriptions that appear beneath the 'Sites' title. This setting could be on but no topics appear in the list. This text explains why.">
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
</message>
<message name="IDS_SETTINGS_FLEDGE_PAGE_SEE_ALL_SITES_LABEL" desc="Text that serves as a button. Because the list of sites might be long, we only show the most recent sites. This button allows the user to browse all sites (because sites are auto-deleted every 4 weeks, the list is never older than 4 weeks).">
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
</message>
<message name="IDS_CLEAR_COOKIES_AND_SITE_DATA_SUMMARY_BASIC" desc="A summary for the 'Cookies and site data' option in the 'Clear Browsing Data' screen, explaining that deleting cookies and site data will sign the user out of most websites.">
Signs you out of most sites.
Signs you out of most sites
</message>
<message name="IDS_CLEAR_COOKIES_AND_SITE_DATA_SUMMARY_BASIC_SIGNED_IN" desc="A summary for the 'Cookies and site data' option in the 'Clear Browsing Data' screen, explaining that deleting cookies and site data will sign the user out of most websites but you Google sign in will stay.">
Signs you out of most sites. You won't be signed out of your Google Account.
</message>
<message name="IDS_CLEAR_BROWSING_HISTORY_SUMMARY" desc="A text for the basic tab explaining browsing history.">
Clears history, including in the search box.
Clears history, including in the search box
</message>
<message name="IDS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNCED_NO_LINK" desc="A text for the basic tab explaining browsing history for users with history sync. This version is shown when the link to MyActivity is displayed separately.">
Clears history from all synced devices.
Clears history from all synced devices
</message>
<message name="IDS_CLEAR_SEARCH_HISTORY_LINK" desc="Text informing the user that they can clear search history and other data using MyActivity.">
<ph name="BEGIN_LINK1">&lt;link1&gt;</ph>Search history<ph name="END_LINK1">&lt;/link1&gt;</ph> and <ph name="BEGIN_LINK2">&lt;link2&gt;</ph>other forms of activity<ph name="END_LINK2">&lt;/link2&gt;</ph> may be saved in your Google Account when youre 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
<message name="IDS_CLEAR_BROWSING_DATA_TAB_PERIOD_TITLE" desc="Label of the dropdown that selects the time range for which browsing data will be deleted.">
Time range
</message>
<message name="IDS_CLEAR_BROWSING_DATA_TAB_PERIOD_15_MINUTES" desc="The option to delete browsing data from the last 15 minutes.">
Last 15 minutes
</message>
<message name="IDS_CLEAR_BROWSING_DATA_TAB_PERIOD_HOUR" desc="The option to delete browsing data from the last hour.">
Last hour
</message>
@ -1700,6 +1727,9 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_SUMMARY" desc="Summary for Safe Browsing standard protection mode.">
Standard protection against websites, downloads, and extensions that are known to be dangerous.
</message>
<message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_SUMMARY_UPDATED" desc="Summary for Safe Browsing standard protection mode.">
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.
</message>
<message name="IDS_SAFE_BROWSING_NO_PROTECTION_TITLE" desc="Title for Safe Browsing no protection mode. [CHAR_LIMIT=32]">
No protection (not recommended)
</message>
@ -1731,6 +1761,9 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_SUBTITLE" desc="Subtitle for Safe Browsing standard protection mode.">
Standard protection:
</message>
<message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_SUBTITLE_UPDATED" desc="Subtitle for Safe Browsing standard protection mode.">
Standard protection
</message>
<message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_BULLET_ONE" desc="First bullet point under the Safe Browsing standard protection mode.">
Detects and warns you about dangerous events when they happen.
</message>
@ -1740,6 +1773,9 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_EXTENDED_REPORTING_TITLE" desc="Title for Safe Browsing extended reporting.">
Help improve security on the web
</message>
<message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_EXTENDED_REPORTING_TITLE_UPDATED" desc="Title for Safe Browsing extended reporting.">
Help improve security on the web for everyone
</message>
<message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_EXTENDED_REPORTING_SUMMARY" desc="Summary for Safe Browsing extended reporting.">
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.
</message>
@ -1795,9 +1831,6 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_LANGUAGES_ITEM_OPTION_OFFER_TO_TRANSLATE" desc="Option in language item menu. User can click the 'Offer to translate' option to toggle whether they want Thorium to translate pages in this language. [CHAR_LIMIT=32]">
Offer to translate
</message>
<message name="IDS_LANGUAGES_EXPLICIT_ASK_TITLE" desc="Title of the dialog that explicitly asks the user which languages they can read.">
What languages do you read?
</message>
<message name="IDS_LANGUAGES_SRP_TITLE" desc="Title of the dialog that explicitly asks the user what language they want Thorium on Android to be in.">
Pick Thoriums language
</message>
@ -2149,7 +2182,12 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_NTP_RECENT_TABS_SYNC_PROMO_INSTRUCTIONS" desc="Information about sync displayed on the NTP when the user has signed in on mobile but not on desktop">
Tabs that you've opened in Thorium on your other devices will appear here.
</message>
<message name="IDS_RECENT_TABS_NO_TABS_EMPTY_STATE" desc="Text appearing on an empty recent tab page that indicates that recently closed tabs will appear here">
Youll find your recent tabs here
</message>
<message name="IDS_RECENT_TABS_SIGN_IN_ON_OTHER_DEVICES" desc="Text appearing on an empty recent tab page that indicates user can see tabs from other devices here">
To see your tabs from wherever you use Thorium, sign in on all your devices
</message>
<message name="IDS_SEARCH_AND_BROWSE_CATEGORY" desc="Category to show the search and browse improvement toggle. [CHAR_LIMIT=32]">
Search and browse
</message>
@ -2431,6 +2469,10 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Translate…
</message>
<message name="IDS_MENU_LISTEN_TO_THIS_PAGE" desc="Menu item for making the browser read out the page's text in spoken audio form. [CHAR_LIMIT=27]">
Listen to this page
</message>
<message name="IDS_MENU_PRINT" desc="Menu item for printing the current page. [CHAR_LIMIT=27]">
Print…
</message>
@ -3000,10 +3042,10 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Thorium First Run Experience
</message>
<message name="IDS_LIGHTWEIGHT_FRE_ASSOCIATED_APP_TOS" desc="Message explaining that use of Thorium is governed by Thorium's terms of service.">
<ph name="APP_NAME">%1$s<ex>Google Maps</ex></ph> will open in Thorium. By continuing, you agree to the <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Google Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph>, and the <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Thorium and ThoriumOS Additional Terms of Service<ph name="END_LINK2">&lt;/LINK2&gt;</ph>.
<ph name="APP_NAME">%1$s<ex>Google Maps</ex></ph> will open in Thorium. By continuing, you agree to the <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Google Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph>, and the <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Google Thorium and ThoriumOS Additional Terms of Service<ph name="END_LINK2">&lt;/LINK2&gt;</ph>.
</message>
<message name="IDS_LIGHTWEIGHT_FRE_ASSOCIATED_APP_TOS_AND_PRIVACY_CHILD_ACCOUNT" desc="Message explaining that use of Thorium is governed by Thorium's terms of service, and the Google Privacy Policy.">
<ph name="APP_NAME">%1$s<ex>Google Maps</ex></ph> will open in Thorium. By continuing, you agree to the <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Google Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph>, and the <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Thorium and ThoriumOS Additional Terms of Service<ph name="END_LINK2">&lt;/LINK2&gt;</ph>. The <ph name="BEGIN_LINK3">&lt;LINK3&gt;</ph>Privacy Policy<ph name="END_LINK3">&lt;/LINK3&gt;</ph> also applies.
<ph name="APP_NAME">%1$s<ex>Google Maps</ex></ph> will open in Thorium. By continuing, you agree to the <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Google Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph>, and the <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Google Thorium and ThoriumOS Additional Terms of Service<ph name="END_LINK2">&lt;/LINK2&gt;</ph>. The <ph name="BEGIN_LINK3">&lt;LINK3&gt;</ph>Privacy Policy<ph name="END_LINK3">&lt;/LINK3&gt;</ph> also applies.
</message>
<message name="IDS_FRE_ACCEPT_CONTINUE" desc="Text for first page accept and continue button [CHAR_LIMIT=20]">
Accept &amp; continue
@ -3081,16 +3123,16 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Your info is secured with a profile lock
</message>
<message name="IDS_DEVICE_LOCK_DESCRIPTION" desc="Text description explaining that a profile lock is required for automotive devices to protect data privacy. 'Sync' is short for synchronization.">
To sync your info and keep your data secure in the car, you must create a profile lock. Youll 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. Youll use a code or password every time you enter the car.
</message>
<message name="IDS_DEVICE_LOCK_THROUGH_SETTINGS_DESCRIPTION" desc="Text description explaining that a profile lock is required for automotive devices to protect data privacy, and that such a lock can be created in the device's security settings. 'Sync' is short for synchronization.">
To sync your info and keep your data secure in the car, you must create a profile lock in your security settings. Youll 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. Youll use a code or password every time you enter the car.
</message>
<message name="IDS_DEVICE_LOCK_EXISTING_LOCK_DESCRIPTION" desc="Text description explaining to users who have already set an existing lock that a profile lock is required for automotive devices to protect data privacy. 'Sync' is short for synchronization.">
Your profile lock keeps your info secure in the car, including synced passwords, payments and more.
</message>
<message name="IDS_DEVICE_LOCK_NOTICE" desc="Notice appearing on the profile lock page informing users that data saved on Thorium will be erased if they remove the profile lock from the device.">
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.
</message>
<message name="IDS_DEVICE_LOCK_CREATE_LOCK_BUTTON" desc="Text for the button that navigates the user to create a profile lock on the device.">
Create a profile lock
@ -3145,6 +3187,12 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_SIGNIN_ACCOUNT_PICKER_DIALOG_TITLE" desc="The title for the dialog that shows the list of accounts on the device and asks the user to select one of these accounts. [CHAR_LIMIT=27]">
Choose an account
</message>
<message name="IDS_SIGNIN_ACCOUNT_PICKER_DESCRIPTION_WITH_EMAIL" is_accessibility_with_no_ui="true" desc="The content description for the account picker. Opens the 'Choose an account' dialog.">
Choose an account. Currently selected <ph name="EMAIL">%1$s<ex>john.doe@example.com</ex></ph>.
</message>
<message name="IDS_SIGNIN_ACCOUNT_PICKER_DESCRIPTION" is_accessibility_with_no_ui="true" desc="The content description for the account picker. Opens the 'Choose an account' dialog. Used when the user's email cannot be displayed.">
Choose an account.
</message>
<message name="IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_TITLE_FOR_SEND_TAB_TO_SELF" desc="The title for the bottom sheet that shows the list of accounts on the device and asks the user to select one of these accounts, when send-tab-to-self triggered the UI. [CHAR_LIMIT=27]">
Sign in to Thorium
</message>
@ -3541,6 +3589,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_PREFERENCE_TRANSLATE" desc="Title name for the translate option in the preference.">
Translate
</message>
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_PREFERENCE_READ_ALOUD" desc="Title name for the read aloud option in the preference.">
Listen to this page
</message>
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_PREFERENCE_BASED_ON_YOUR_USAGE" desc="Title name for the based on your usage option in the preference.">
Based on your usage
</message>
@ -3565,10 +3616,13 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_TRANSLATE_IPH" desc="An in-product-help message for the voice search button.">
Quickly translate this page. To edit this shortcut, touch and hold.
</message>
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_READ_ALOUD_IPH" desc="An in-product-help message for the Listen to this page button.">
Listen to this page. To edit this shortcut, touch and hold.
</message>
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_NEW_TAB_IPH_SETTINGS" desc="An in-product-help message for the new tab button referring to toolbar settings.">
Quickly open a new tab. To edit this shortcut, go to Settings.
</message>
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_SHARE_IPH_SETTINGS" desc="An in-product-help message for the share button referring to toolbar settings.">
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_SHARE_IPH_SETTINGS" desc="An in-product-help message for the share button referring to toolbar settings.">
Quickly share this page. To edit this shortcut, go to Settings.
</message>
<message name="IDS_ADAPTIVE_TOOLBAR_BUTTON_VOICE_SEARCH_IPH_SETTINGS" desc="An in-product-help message for the voice search button referring to toolbar settings.">
@ -3633,8 +3687,8 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_MENU_HISTORY" desc="Menu item for opening the history page. [CHAR_LIMIT=27]">
History
</message>
<message name="IDS_MENU_QUICK_DELETE" desc="Menu item for quick delete functionality that allows users to quickly delete their last 15 minutes browsing data. [CHAR_LIMIT=27]">
Delete last 15 minutes
<message name="IDS_MENU_QUICK_DELETE" desc="Menu item for quick delete functionality that allows users to delete their browsing data. [CHAR_LIMIT=27]">
Clear browsing data
</message>
<message name="IDS_MENU_DOWNLOADS" desc="Menu item for opening the downloads page. [CHAR_LIMIT=27]">
Downloads
@ -3887,6 +3941,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_SORT_BY_OLDEST" desc="Option in the bookmarks manager to sort by newest. [CHAR_LIMIT=24]">
Sort by oldest
</message>
<message name="IDS_SORT_BY_LAST_OPENED" desc="Option in the bookmarks manager to sort by last opened. [CHAR_LIMIT=24]">
Sort by last opened
</message>
<message name="IDS_SORT_BY_ALPHA" desc="Option in the bookmarks manager to sort alphabetically. A and Z should be substituted with the first/last letter in the localized language. [CHAR_LIMIT=24]">
Sort by A to Z
</message>
@ -3902,6 +3959,15 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_CREATE_NEW_FOLDER" desc="Option in the bookmarks manager to show the create a new folder in the current context. [CHAR_LIMIT=24]">
Create new folder
</message>
<message name="IDS_FOLDER_PICKER_ROOT" desc="Toolbar title for when the user is selecting a folder and the current selected folder is the root.">
Move to\u2026
</message>
<message name="IDS_FOLDER_PICKER_MOVE_HERE" desc="Button the user clicks to move the given bookmark (or folder) to the selected folder.">
Move here
</message>
<message name="IDS_FOLDER_PICKER_CANCEL" desc="Button the user clicks to cancel the move action.">
Cancel
</message>
<!-- Read later strings -->
<message name="IDS_READING_LIST_READ" desc="The header for the read section in the reading list UI.">
@ -4048,9 +4114,6 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_RDS_SITE_SETTINGS_GENERIC_IPH_TEXT_MOBILE" desc="Message on the generic text bubble shown to educate the user about using the desktop site site-level setting to switch to mobile mode.">
You can request the mobile site for <ph name="HOST_NAME">%1$s<ex>www.example.com</ex></ph>
</message>
<message name="IDS_RDS_SITE_SETTINGS_SPECIFIC_IPH_TEXT" desc="Message on the text bubble shown on specific websites more functional in desktop mode to educate the user about using the desktop site site-level setting.">
Switch to desktop site for a better view of this site
</message>
<!-- Accessibility -->
@ -4079,6 +4142,12 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Incognito mode
</message>
<message name="IDS_TABSWITCHER_NO_TABS_EMPTY_STATE" desc="Text appearing on an empty tab switcher that indicates that tabs opened will appear here.">
Youll find your tabs here
</message>
<message name="IDS_TABSWITCHER_NO_TABS_OPEN_TO_VISIT_DIFFERENT_PAGES" desc="Text appearing on an empty tab switcher that indicates that users can open tabs here to visit different pages.">
Open tabs to visit different pages at the same time
</message>
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_TABSWITCHER_TOGGLE_DEFAULT" desc="Placeholder content description for the button that enters or leaves the tab switcher.">
Switch or close tabs
</message>
@ -4086,13 +4155,13 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Manage account
</message>
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_IDENTITY_DISC_WITH_NAME_AND_EMAIL" desc="The content description for a toolbar button displaying user profile picture. Tapping on this button navigates to 'Sync and Google services' page in settings">
Signed in as <ph name="USER_NAME">%1$s<ex>Peter Parker</ex></ph>. <ph name="USER_EMAIL">%2$s<ex>peter.parker@gmail.com</ex></ph>. Button. Opens settings.
Signed in as <ph name="USER_NAME">%1$s<ex>Peter Parker</ex></ph>. <ph name="USER_EMAIL">%2$s<ex>peter.parker@gmail.com</ex></ph>. Opens settings.
</message>
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_IDENTITY_DISC_WITH_NAME" desc="The content description for a toolbar button displaying user profile picture, for users who don't have a readable email address. Tapping on this button navigates to 'Sync and Google services' page in settings">
Signed in as <ph name="USER_NAME">%s<ex>Bruce Wayne</ex></ph>. Button. Opens settings.
Signed in as <ph name="USER_NAME">%s<ex>Bruce Wayne</ex></ph>. Opens settings.
</message>
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_SIGNED_OUT_IDENTITY_DISC" desc="The content description for a toolbar button displaying the signed-out avatar. Tapping on this button navigates to 'Turn on Sync' page in settings">
Signed out. Button. Opens dialog to sign in and turn on sync.
Signed out. Opens dialog to sign in and turn on sync.
</message>
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_HOME" desc="Content description for the home button.">
Home
@ -4334,6 +4403,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_PAGE_INSIGHTS_SHEET_CLOSED" desc="Accessibility string read when the page insights sheet is closed.">
Page insights bottom sheet is closed
</message>
<message name="IDS_PAGE_INSIGHTS_HUB_TITLE_TEXT" desc="The title of Page Insights Sheet.">
Related Insights
</message>
<!-- WebFeed -->
<message name="IDS_WEB_FEED_FOLLOW_LOADING_DESCRIPTION" desc="The content description of the loading spinner after the user presses Follow and is waiting for a response.">
@ -4558,7 +4630,7 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Tab and window shortcuts
</message>
<message name="IDS_KEYBOARD_SHORTCUT_CHROME_FEATURE_GROUP_HEADER" desc="A text label that appears above a list of shortcuts that are related to the Thorium app features. This group is part of several groups of keyboard shortcuts all shown in a dialog.">
Thorium feature shortcuts
Google Thorium feature shortcuts
</message>
<message name="IDS_KEYBOARD_SHORTCUT_WEBPAGE_GROUP_HEADER" desc="A text label that appears above a list of shortcuts that are related to manipulation of the current tab window. This group is part of several groups of keyboard shortcuts all shown in a dialog.">
Webpage shortcuts
@ -5012,7 +5084,7 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_CABLEV2_ACTIVITY_TITLE"
desc="The label of the Activity for using your phone as a security key. A 'security key' in this context is generally a small USB device that is used for logging into websites. This feature allows Thorium on an Android phone to act as a security key. A user may see it in Android permissions prompts (see screenshot).">
Thorium as a Security Key
Google Thorium as a Security Key
</message>
<message name="IDS_CABLEV2_REGISTRATION_SUCCEEDED"
@ -5464,10 +5536,10 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Save up to 60% data
</message>
<message name="IDS_CHROME_REENGAGEMENT_NOTIFICATION_2_DESCRIPTION" desc="The body text of a notification shown to suggest that users use Thorium. Users probably have not opened Thorium in a while. Promotes data savings.">
Use Lite mode on Thorium
Use Lite mode on Google Thorium
</message>
<message name="IDS_CHROME_REENGAGEMENT_NOTIFICATION_3_TITLE" desc="The title of a notification shown to suggest that users use Thorium. Users probably have not opened Thorium in a while.">
Alex313031 recommends Thorium
Google recommends Thorium
</message>
<message name="IDS_CHROME_REENGAGEMENT_NOTIFICATION_3_DESCRIPTION" desc="The title of a notification shown to suggest that users use Thorium. Users probably have not opened Thorium in a while. Promotes data savings and relevant news.">
Save up to 60% data, read today's news
@ -5581,6 +5653,12 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_ACCOUNT_SELECTION_SHEET_CLOSED" desc="Accessibility string read when the Account Selection bottom sheet showing a list of the user's accounts is closed." is_accessibility_with_no_ui="true">
Sign in bottom sheet is closed.
</message>
<message name="IDS_IDP_SIGNIN_STATUS_MISMATCH_DIALOG_BODY" desc="Body for mismatch dialog which is shown to prompt the user to sign in to a website using an account from an identity provider." translateable="false">
You can use your <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE">%1$s<ex>idp.com</ex></ph> account on this site. To continue, sign in to <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE">%1$s<ex>idp.com</ex></ph>.
</message>
<message name="IDS_IDP_SIGNIN_STATUS_MISMATCH_DIALOG_CONTINUE" desc="Title of the button that allows the user to continue with signing in to an account from an identity provider." translateable="false">
Continue
</message>
<message name="IDS_VERIFY_SHEET_TITLE_AUTO_REAUTHN" desc="Header for verify sheet for auto re-authentication.">
Signing you in…
</message>
@ -5698,24 +5776,6 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_PRICE_DROP_SPOTTED_IPH" desc="This text appears in the IPH when a user opens a new tab page and an item in any of their open tabs has a price drop.">
Price drop spotted
</message>
<!-- Restore Custom Tab strings -->
<message name="IDS_RESTORE_CUSTOM_TAB_TITLE" desc="Appears in pop-up message title when the previous Custom Tab session a user engaged with can be restored.">
Resume your last task?
</message>
<message name="IDS_RESTORE_CUSTOM_TAB_DESCRIPTION" desc="Appears in pop-up message description when the previous Custom Tab session a user engaged with can be restored and in pop-up which gives the option to undo that restoration.">
Easily continue where you left off
</message>
<message name="IDS_RESTORE_CUSTOM_TAB_BUTTON_TEXT" desc="Appears as pop-up message button text to direct the user to restore a previously engaged with Custom Tab session.">
Restore
</message>
<message name="IDS_UNDO_RESTORATION_TITLE" desc="Appears in pop-up message title when a Custom Tab session is restored, giving the user the option to undo the restoration.">
Task resumed
</message>
<message name="IDS_UNDO_RESTORATION_BUTTON_TEXT" desc="Appears in pop-up message button text when a Custom Tab session is restored, giving the user the option to undo the restoration.">
Undo
</message>
<!-- Partial Custom Tab accessibility -->
<message name="IDS_ACCESSIBILITY_PARTIAL_CUSTOM_TAB_BOTTOM_SHEET" desc="Content description for partial custom tab of bottom sheet type">
Bottom sheet
@ -5728,24 +5788,65 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
</message>
<!-- Quick Delete strings -->
<message name="IDS_QUICK_DELETE_DIALOG_TITLE" desc="Title of the dialog when asking users to confirm deleting the last 15 minutes of browsing data.">
Delete last 15 minutes?
<message name="IDS_QUICK_DELETE_DIALOG_TITLE" desc="Title of the dialog when asking users to confirm deleting browsing data.">
Clear browsing data
</message>
<message name="IDS_QUICK_DELETE_DIALOG_DESCRIPTION" desc="Description of the dialog when asking users to confirm deleting the last 15 minutes of browsing data.">
History from the last 15 minutes will be deleted:
</message>
<message name="IDS_QUICK_DELETE_DIALOG_TABS_CLOSED_TEXT" desc="Text indicating that the tabs which a user recently used to visit a website within 15 minutes would be closed.">
<message name="IDS_QUICK_DELETE_DIALOG_TABS_CLOSED_TEXT" desc="Text indicating that the tabs which a user recently used to visit a website within the specified time range would be closed.">
{NUM_TABS, plural, =1 {1 tab on this device} other {# tabs on this device}}
</message>
<message name="IDS_QUICK_DELETE_DIALOG_ZERO_TABS_CLOSED_ALL_TIME_TEXT" desc="Text indicating that no tabs would be closed.">
No tabs on this device
</message>
<message name="IDS_QUICK_DELETE_DIALOG_ZERO_TABS_CLOSED_TEXT" desc="Text indicating that no tabs within the specified time range would be closed.">
No tabs from the <ph name="TIME_PERIOD">%1$s<ex>last 15 minutes</ex></ph>
</message>
<message name="IDS_QUICK_DELETE_DIALOG_BROWSING_HISTORY_DOMAIN_COUNT_TEXT" desc="This text would start by mentioning the last visited domain, and, then followed by showing the count of other unique domains that the user has visited. For example: if a user visits/revisits facebook.com, followed by figma.com, within the specified time range, then this text would say 'figma.com + 1 site'.">
{DOMAIN_COUNT, plural,
=1 {+ 1 site}
other {+ # sites}}
</message>
<message name="IDS_QUICK_DELETE_DIALOG_ZERO_BROWSING_HISTORY_DOMAIN_COUNT_ALL_TIME_TEXT" desc="Text indicating that no websites were visited from the beginning of time.">
No sites
</message>
<message name="IDS_QUICK_DELETE_DIALOG_ZERO_BROWSING_HISTORY_DOMAIN_COUNT_TEXT" desc="Text indicating that no websites were visited within the specified time range.">
No sites from the <ph name="TIME_PERIOD">%1$s<ex>last 15 minutes</ex></ph>
</message>
<message name="IDS_QUICK_DELETE_DIALOG_BROWSING_HISTORY_SECONDARY_TEXT" desc="Secondary text for browsing history item for syncing users, indicating that there could be more domains on other devices that the user has visited within the specified time range, which would be deleted from history.">
More on synced devices
</message>
<message name="IDS_QUICK_DELETE_DIALOG_COOKIES_CACHE_AND_OTHER_SITE_DATA_TEXT" desc="Text indicating that browsing data like cookies, cache, and other site data would be deleted.">
Cookies, cache, and other site data
</message>
<message name="IDS_QUICK_DELETE_DIALOG_SEARCH_HISTORY_DISAMBIGUATION_TEXT" desc="Text for signed in users only in the Quick Delete dialog, that is shown when the user clicks on 'Delete last 15 minutes' option in the three dots menu, informing signed in users that search history and other forms of Activity saved in their Google account will not be deleted.">
<message name="IDS_QUICK_DELETE_DIALOG_SEARCH_HISTORY_DISAMBIGUATION_TEXT" desc="Text for signed in users only in the Quick Delete dialog, that is shown when the user clicks on 'Clear browsing data' option in the three dots menu, informing signed in users that search history and other forms of Activity saved in their Google account will not be deleted.">
<ph name="BEGIN_LINK1">&lt;link1&gt;</ph>Search history<ph name="END_LINK1">&lt;/link1&gt;</ph> and <ph name="BEGIN_LINK2">&lt;link2&gt;</ph>other forms of activity<ph name="END_LINK2">&lt;/link2&gt;</ph> may be saved in your Google Account
</message>
<message name="IDS_QUICK_DELETE_SNACKBAR_MESSAGE" desc="Text inside the snackbar which is shown once the user confirms deletion via the 'Delete last 15 minutes' option present inside the three dots menu.">
<message name="IDS_QUICK_DELETE_DIALOG_MORE_OPTIONS_BUTTON_TEXT" desc="Text inside the more options button which redirects users to the advanced page of 'Clear Browsing Data' where the users can customize more deletion options.">
More options
</message>
<message name="IDS_QUICK_DELETE_DIALOG_DATA_PENDING" desc="Text that is shown when data in the dialog is being fetched.">
Calculating...
</message>
<message name="IDS_QUICK_DELETE_SNACKBAR_MESSAGE" desc="Text inside the snackbar which is shown once the user confirms deletion via the 'Clear browsing data' option present inside the three dots menu.">
<ph name="TIME_PERIOD">%1$s<ex>Last 15 minutes</ex></ph> deleted
</message>
<message name="IDS_QUICK_DELETE_SNACKBAR_ALL_TIME_MESSAGE" desc="Text inside the snackbar which is shown once the user confirms deletion via the 'Clear browsing data' option present inside the three dots menu.">
Deleted
</message>
<message name="IDS_QUICK_DELETE_TIME_PERIOD_15_MINUTES" desc="The option to delete browsing data from the last 15 minutes.">
last 15 minutes
</message>
<message name="IDS_QUICK_DELETE_TIME_PERIOD_HOUR" desc="The option to delete browsing data from the last hour.">
last hour
</message>
<message name="IDS_QUICK_DELETE_TIME_PERIOD_24_HOURS" desc="The option to delete browsing data from the last 24 hours.">
last 24 hours
</message>
<message name="IDS_QUICK_DELETE_TIME_PERIOD_7_DAYS" desc="The option to delete browsing data from the last seven days.">
last 7 days
</message>
<message name="IDS_QUICK_DELETE_TIME_PERIOD_FOUR_WEEKS" desc="The option to delete browsing data from the last 4 weeks.">
last 4 weeks
</message>
<!-- Password generation bottom sheet -->
<message name="IDS_PASSWORD_GENERATION_BOTTOM_SHEET_CONTENT_DESCRIPTION" desc="Accessibility string read when the bottom sheet is opened. It describes that the bottom sheet proposes a generated password to be automatically filled into the sign up form and saved to the Password Manager.">
@ -5769,6 +5870,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_PASSWORD_GENERATION_BOTTOM_SHEET_DISMISS_BUTTON" desc="Appears on the button, which reflects that the user has rejected the proposed generated password and decided to continue with creating their own password.">
Create my own
</message>
<message name="IDS_PLEASE_WAIT_PROGRESS_MESSAGE" desc='Message on the progress dialog used when waiting for an operation to complete.'>
Please wait…
</message>
</messages>
</release>
</grit>

View File

@ -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.

View File

@ -138,7 +138,7 @@ class BrowserRootView : public views::internal::RootView {
std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner);
// The BrowserView.
raw_ptr<BrowserView, DanglingUntriaged> browser_view_ = nullptr;
raw_ptr<BrowserView, AcrossTasksDanglingUntriaged> browser_view_ = nullptr;
// Used to calculate partial offsets in scrolls that occur for a smooth
// scroll device.

View File

@ -138,7 +138,7 @@ class TabStyleHighlightPathGenerator : public views::HighlightPathGenerator {
}
private:
const raw_ptr<TabStyleViews, DanglingUntriaged> tab_style_views_;
const raw_ptr<TabStyleViews, AcrossTasksDanglingUntriaged> 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<views::ViewTargeter>(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();

View File

@ -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;
};

View File

@ -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<int> fill_id,
int y_inset) const;
void PaintTabBackgroundWithImages(
gfx::Canvas* canvas,
absl::optional<int> active_tab_fill_id,
absl::optional<int> inactive_tab_fill_id) const;
void PaintTabBackgroundFill(gfx::Canvas* canvas,
TabActive active,
bool paint_hover_effect,
TabStyle::TabSelectionState selection_state,
bool hovered,
absl::optional<int> 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<int> 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<int> 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<int> active_tab_fill_id,
absl::optional<int> 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<uint8_t>(throb_value * 0xff),
const float opacity = GetCurrentActiveOpacity();
if (opacity > 0) {
canvas->SaveLayerAlpha(base::ClampRound<uint8_t>(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<tab_groups::TabGroupId> 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<float>(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<int> fill_id,
int y_inset) const {
void GM2TabStyleViews::PaintTabBackground(
gfx::Canvas* canvas,
TabStyle::TabSelectionState selection_state,
bool hovered,
absl::optional<int> 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<SkColor> 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<int> fill_id,
int y_inset) const {
void GM2TabStyleViews::PaintTabBackgroundFill(
gfx::Canvas* canvas,
TabStyle::TabSelectionState selection_state,
bool hovered,
absl::optional<int> 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);
}

View File

@ -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;

View File

@ -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<URLID, VisitID> 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<int64_t> local_navigation_id,
absl::optional<std::u16string> title,
absl::optional<base::TimeDelta> visit_duration,
absl::optional<std::string> originator_cache_guid,
@ -1391,6 +1401,7 @@ std::pair<URLID, VisitID> 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<URLID, VisitID> 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<VisitID>& visit_ids,
const ClusterVisit::InteractionState interaction_state) {
TRACE_EVENT0("browser", "HistoryBackend::UpdateVisitsInteractionState");
if (!db_) {
return;
}
db_->UpdateVisitsInteractionState(visit_ids, interaction_state);
}
std::vector<Cluster> HistoryBackend::GetMostRecentClusters(
base::Time inclusive_min_time,
base::Time exclusive_max_time,
@ -3521,12 +3546,14 @@ void HistoryBackend::NotifyFaviconsChanged(const std::set<GURL>& 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<int64_t> 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,

View File

@ -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;
}

View File

@ -65,6 +65,7 @@ about:version template page
</if>
<div id="company"><a target="_blank" rel="noopener" href="https://github.com/Alex313031/Thorium">$i18n{company}</a></div>
<div id="copyright">$i18n{copyright}</div>
<if expr="not is_android and not is_ios">
<br/>
<!-- Thorium Mascot. -->
<picture title="Thorium Mascot">
@ -76,6 +77,16 @@ about:version template page
media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)">
<img alt="Thorium Mascot" src="chrome://theme/IDR_PRODUCT_MASCOT">
</picture>
</if>
<if expr="is_ios or is_android">
<br/>
<!-- Thorium Mascot. -->
<picture title="Thorium Mascot">
<source srcset="images/thorium_mascot.png" media="(prefers-color-scheme: dark)">
<source srcset="images/thorium_mascot.png" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)">
<img alt="Thorium Mascot" src="images/thorium_mascot.png">
</picture>
</if>
</div>
<table id="inner" cellpadding="0" cellspacing="0" border="0">
<tr><td class="label">$i18n{application_label}</td>

View File

@ -42,24 +42,30 @@ namespace media {
namespace {
template <typename T>
class SupplementalProfileCache {
public:
void UpdateCache(const base::flat_set<media::VideoCodecProfile>& profiles) {
void UpdateCache(const base::flat_set<T>& 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<media::VideoCodecProfile> profiles_ GUARDED_BY(profiles_lock_);
base::flat_set<T> profiles_ GUARDED_BY(profiles_lock_);
};
SupplementalProfileCache* GetSupplementalProfileCache() {
static base::NoDestructor<SupplementalProfileCache> cache;
SupplementalProfileCache<VideoCodecProfile>* GetSupplementalProfileCache() {
static base::NoDestructor<SupplementalProfileCache<VideoCodecProfile>> cache;
return cache.get();
}
SupplementalProfileCache<AudioType>* GetSupplementalAudioTypeCache() {
static base::NoDestructor<SupplementalProfileCache<AudioType>> 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<AudioType>& types) {
GetSupplementalAudioTypeCache()->UpdateCache(types);
}
} // namespace media

File diff suppressed because it is too large Load Diff

View File

@ -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/*

View File

@ -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);