focus-mode: Add OAuth consent and free trials view for YTM
This CL will add an OAuth consent view and a 3 months free trials view for the YouTube Music sound section view. Bug: b/359225463, b/362610166 Test: Manual Change-Id: I7dc2bf3d331b217a882d12b3cdb660b2d41a691b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5846430 Reviewed-by: Richard Chui <richui@chromium.org> Reviewed-by: Rushan Suleymanov <rushans@google.com> Commit-Queue: Hongyu Long <hongyulong@chromium.org> Cr-Commit-Position: refs/heads/main@{#1355976}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
73e6709a0b
commit
0020d95e37
ash
ash_strings.grd
ash_strings_grd
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_FREE_TRIAL_BUTTON.png.sha1IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_FREE_TRIAL_LABEL.png.sha1IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_LEARN_MORE_BUTTON.png.sha1IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_NON_PREMIUM_LABEL.png.sha1IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_BUTTON.png.sha1IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_LABEL.png.sha1
constants
public
system
chrome
browser
sync
ui
common
tools/metrics/histograms/metadata/sync
@@ -817,11 +817,23 @@ Style notes:
|
|||||||
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_MEDIA_CONTROLS_SOURCE_TITLE" desc="The source title shown in the media controls if a focus mode playlist is selected and playing.">
|
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_MEDIA_CONTROLS_SOURCE_TITLE" desc="The source title shown in the media controls if a focus mode playlist is selected and playing.">
|
||||||
<ph name="PLAYLIST_TYPE">$1<ex>Focus sounds</ex></ph> ᐧ <ph name="PLAYLIST_TITLE">$2<ex>Nature</ex></ph>
|
<ph name="PLAYLIST_TYPE">$1<ex>Focus sounds</ex></ph> ᐧ <ph name="PLAYLIST_TITLE">$2<ex>Nature</ex></ph>
|
||||||
</message>
|
</message>
|
||||||
|
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_LABEL" desc="The text on the label used for showing a text to mention the user the focus panel will access the YouTube Music for personalized music.">
|
||||||
|
For personalized focus playlists, allow access to YouTube Music
|
||||||
|
</message>
|
||||||
|
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_BUTTON" desc="The text on the get started button.">
|
||||||
|
Get started
|
||||||
|
</message>
|
||||||
|
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_FREE_TRIAL_LABEL" desc="The text on the label used for showing a text to mention the user to get three months free trial of YouTube Music premium.">
|
||||||
|
Stay on track with personalized focus playlists. Get YouTube Music and YouTube, ad-free, with 3 months of YouTube Premium at no cost.
|
||||||
|
</message>
|
||||||
|
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_FREE_TRIAL_BUTTON" desc="The text on the free trial button.">
|
||||||
|
Get perk
|
||||||
|
</message>
|
||||||
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_NON_PREMIUM_LABEL" desc="The text on the label used for showing a text to mention the user without a premium account for YouTube Music.">
|
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_NON_PREMIUM_LABEL" desc="The text on the label used for showing a text to mention the user without a premium account for YouTube Music.">
|
||||||
For personalized playlists and more focus music, try YouTube Music Premium
|
To listen to music ad-free and enjoy personalized focus music, try YouTube Music Premium
|
||||||
</message>
|
</message>
|
||||||
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_LEARN_MORE_BUTTON" desc="The text on the learn more button.">
|
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_LEARN_MORE_BUTTON" desc="The text on the learn more button.">
|
||||||
Learn more
|
Get Music Premium
|
||||||
</message>
|
</message>
|
||||||
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OFFLINE_LABEL_ONE" desc="The text shown to the user in the first line of the sounds view when they are offline.">
|
<message name="IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OFFLINE_LABEL_ONE" desc="The text shown to the user in the first line of the sounds view when they are offline.">
|
||||||
You're offline.
|
You're offline.
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
4867c4d599a4434f40507b63369b5a52b46cc4f8
|
@@ -0,0 +1 @@
|
|||||||
|
76dec517aa261da6643a4d1f3692291b4ad08c5d
|
@@ -1 +1 @@
|
|||||||
f3c0aa0fefb84d77795f5b28c635b84afde6e1a3
|
6e0a382db28731d280e7dd613bce630c7668b9c3
|
@@ -1 +1 @@
|
|||||||
011ac826b4ff366e81ebfd8aa8384288d9dc1c04
|
4d3f8c4653e723d52c18df19d5a6d667f26d3482
|
1
ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_BUTTON.png.sha1
Normal file
1
ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_BUTTON.png.sha1
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2602d2139da529e1cbd0e96c51fb3b47f00c2769
|
1
ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_LABEL.png.sha1
Normal file
1
ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_LABEL.png.sha1
Normal file
@@ -0,0 +1 @@
|
|||||||
|
f25ac9233056f22745796375a4f354ab97f73768
|
@@ -2259,6 +2259,14 @@ inline constexpr char kFocusModeDeviceId[] = "ash.focus_mode.device_id";
|
|||||||
// An string enum pref containing the enabled sound types.
|
// An string enum pref containing the enabled sound types.
|
||||||
inline constexpr char kFocusModeSoundsEnabled[] =
|
inline constexpr char kFocusModeSoundsEnabled[] =
|
||||||
"ash.focus_mode.sounds_enabled";
|
"ash.focus_mode.sounds_enabled";
|
||||||
|
// A boolean pref of whether the focus panel shows the OAuth consent screen for
|
||||||
|
// YouTube Music.
|
||||||
|
inline constexpr char kFocusModeYTMDisplayOAuthConsent[] =
|
||||||
|
"ash.focus_mode.youtube_music.oauth";
|
||||||
|
// A boolean pref of whether the focus panel shows the view to let the user know
|
||||||
|
// a 3 months free trial for YouTube Music.
|
||||||
|
inline constexpr char kFocusModeYTMDisplayFreeTrial[] =
|
||||||
|
"ash.focus_mode.youtube_music.free_trial";
|
||||||
|
|
||||||
// An integer pref that holds enum value of current demo mode configuration.
|
// An integer pref that holds enum value of current demo mode configuration.
|
||||||
// Values are defined by DemoSession::DemoModeConfig enum.
|
// Values are defined by DemoSession::DemoModeConfig enum.
|
||||||
|
@@ -222,6 +222,7 @@ class ASH_PUBLIC_EXPORT SystemTrayClient {
|
|||||||
|
|
||||||
// Shows a page about premium plans.
|
// Shows a page about premium plans.
|
||||||
virtual void ShowYouTubeMusicPremiumPage() = 0;
|
virtual void ShowYouTubeMusicPremiumPage() = 0;
|
||||||
|
virtual void ShowChromebookPerksYouTubePage() = 0;
|
||||||
|
|
||||||
// Shows settings related to keyboards.
|
// Shows settings related to keyboards.
|
||||||
virtual void ShowKeyboardSettings() = 0;
|
virtual void ShowKeyboardSettings() = 0;
|
||||||
|
@@ -210,6 +210,10 @@ void TestSystemTrayClient::ShowYouTubeMusicPremiumPage() {
|
|||||||
++show_youtube_music_premium_page_count_;
|
++show_youtube_music_premium_page_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestSystemTrayClient::ShowChromebookPerksYouTubePage() {
|
||||||
|
++show_chromebook_perks_youtube_page_count_;
|
||||||
|
}
|
||||||
|
|
||||||
void TestSystemTrayClient::ShowKeyboardSettings() {
|
void TestSystemTrayClient::ShowKeyboardSettings() {
|
||||||
++show_keyboard_settings_count_;
|
++show_keyboard_settings_count_;
|
||||||
}
|
}
|
||||||
|
@@ -86,6 +86,7 @@ class ASH_PUBLIC_EXPORT TestSystemTrayClient : public SystemTrayClient {
|
|||||||
void ShowTouchpadSettings() override;
|
void ShowTouchpadSettings() override;
|
||||||
void ShowRemapKeysSubpage(int device_id) override;
|
void ShowRemapKeysSubpage(int device_id) override;
|
||||||
void ShowYouTubeMusicPremiumPage() override;
|
void ShowYouTubeMusicPremiumPage() override;
|
||||||
|
void ShowChromebookPerksYouTubePage() override;
|
||||||
void ShowKeyboardSettings() override;
|
void ShowKeyboardSettings() override;
|
||||||
void ShowPointingStickSettings() override;
|
void ShowPointingStickSettings() override;
|
||||||
void ShowNearbyShareSettings() override;
|
void ShowNearbyShareSettings() override;
|
||||||
@@ -228,6 +229,10 @@ class ASH_PUBLIC_EXPORT TestSystemTrayClient : public SystemTrayClient {
|
|||||||
return show_youtube_music_premium_page_count_;
|
return show_youtube_music_premium_page_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int show_chromebook_perks_youtube_page_count() const {
|
||||||
|
return show_chromebook_perks_youtube_page_count_;
|
||||||
|
}
|
||||||
|
|
||||||
int show_keyboard_settings_count() const {
|
int show_keyboard_settings_count() const {
|
||||||
return show_keyboard_settings_count_;
|
return show_keyboard_settings_count_;
|
||||||
}
|
}
|
||||||
@@ -281,6 +286,7 @@ class ASH_PUBLIC_EXPORT TestSystemTrayClient : public SystemTrayClient {
|
|||||||
int show_touchpad_settings_count_ = 0;
|
int show_touchpad_settings_count_ = 0;
|
||||||
int show_remap_keys_subpage_count_ = 0;
|
int show_remap_keys_subpage_count_ = 0;
|
||||||
int show_youtube_music_premium_page_count_ = 0;
|
int show_youtube_music_premium_page_count_ = 0;
|
||||||
|
int show_chromebook_perks_youtube_page_count_ = 0;
|
||||||
int show_keyboard_settings_count_ = 0;
|
int show_keyboard_settings_count_ = 0;
|
||||||
int show_pointing_stick_settings_count_ = 0;
|
int show_pointing_stick_settings_count_ = 0;
|
||||||
int show_nearby_share_settings_count_ = 0;
|
int show_nearby_share_settings_count_ = 0;
|
||||||
|
@@ -201,6 +201,14 @@ void FocusModeController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
|
|||||||
prefs::kFocusModeSoundSection,
|
prefs::kFocusModeSoundSection,
|
||||||
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
|
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
|
||||||
|
|
||||||
|
// Prefs for YouTube Music.
|
||||||
|
registry->RegisterBooleanPref(
|
||||||
|
prefs::kFocusModeYTMDisplayOAuthConsent, /*default_value=*/true,
|
||||||
|
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
|
||||||
|
registry->RegisterBooleanPref(
|
||||||
|
prefs::kFocusModeYTMDisplayFreeTrial, /*default_value=*/true,
|
||||||
|
user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
|
||||||
|
|
||||||
// Pref is device-local and should never be synced.
|
// Pref is device-local and should never be synced.
|
||||||
registry->RegisterStringPref(prefs::kFocusModeDeviceId, "");
|
registry->RegisterStringPref(prefs::kFocusModeDeviceId, "");
|
||||||
|
|
||||||
|
@@ -607,6 +607,52 @@ void FocusModeSoundsController::ReportYouTubeMusicPlayback(
|
|||||||
youtube_music_delegate_->ReportPlayback(playback_data);
|
youtube_music_delegate_->ReportPlayback(playback_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FocusModeSoundsController::ShouldDisplayYouTubeMusicOAuth() const {
|
||||||
|
if (PrefService* active_user_prefs =
|
||||||
|
Shell::Get()->session_controller()->GetActivePrefService()) {
|
||||||
|
return active_user_prefs->GetBoolean(
|
||||||
|
prefs::kFocusModeYTMDisplayOAuthConsent);
|
||||||
|
}
|
||||||
|
CHECK_IS_TEST();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FocusModeSoundsController::SavePrefForDisplayYouTubeMusicOAuth() {
|
||||||
|
if (PrefService* active_user_prefs =
|
||||||
|
Shell::Get()->session_controller()->GetActivePrefService()) {
|
||||||
|
active_user_prefs->SetBoolean(prefs::kFocusModeYTMDisplayOAuthConsent,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FocusModeSoundsController::ShouldDisplayYouTubeMusicFreeTrial() const {
|
||||||
|
if (PrefService* active_user_prefs =
|
||||||
|
Shell::Get()->session_controller()->GetActivePrefService()) {
|
||||||
|
return active_user_prefs->GetBoolean(prefs::kFocusModeYTMDisplayFreeTrial);
|
||||||
|
}
|
||||||
|
CHECK_IS_TEST();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FocusModeSoundsController::SavePrefForDisplayYouTubeMusicFreeTrial() {
|
||||||
|
if (PrefService* active_user_prefs =
|
||||||
|
Shell::Get()->session_controller()->GetActivePrefService()) {
|
||||||
|
active_user_prefs->SetBoolean(prefs::kFocusModeYTMDisplayFreeTrial, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FocusModeSoundsController::IsMinorUser() {
|
||||||
|
// `ChromeFocusModeDelegate::IsMinorUser` doesn't work in browsertest, since
|
||||||
|
// it always returns true. `can_use_manta_service()` is
|
||||||
|
// `signin::Tribool::kUnknown`.
|
||||||
|
if (is_minor_user_for_testing_.has_value()) {
|
||||||
|
CHECK_IS_TEST();
|
||||||
|
return is_minor_user_for_testing_.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
return FocusModeController::Get()->delegate()->IsMinorUser();
|
||||||
|
}
|
||||||
|
|
||||||
void FocusModeSoundsController::SetIsMinorUserForTesting(bool is_minor_user) {
|
void FocusModeSoundsController::SetIsMinorUserForTesting(bool is_minor_user) {
|
||||||
CHECK_IS_TEST();
|
CHECK_IS_TEST();
|
||||||
is_minor_user_for_testing_ = is_minor_user;
|
is_minor_user_for_testing_ = is_minor_user;
|
||||||
@@ -712,17 +758,12 @@ void FocusModeSoundsController::OnPrefChanged() {
|
|||||||
Shell::Get()->session_controller()->GetActivePrefService();
|
Shell::Get()->session_controller()->GetActivePrefService();
|
||||||
enabled_sound_sections_ = ReadSoundSectionPolicy(active_user_prefs);
|
enabled_sound_sections_ = ReadSoundSectionPolicy(active_user_prefs);
|
||||||
|
|
||||||
// `ChromeFocusModeDelegate::IsMinorUser` doesn't work in browsertest, since
|
// TODO: If we want to block the whole YTM section, we should make changes
|
||||||
// it always returns true. `can_use_manta_service()` is
|
// here. And remove the calls to `FocusModeSoundsController::IsMinorUser()` in
|
||||||
// `signin::Tribool::kUnknown`.
|
// `FocusModeSoundsView`.
|
||||||
const bool is_minor_user =
|
|
||||||
is_minor_user_for_testing_.has_value()
|
|
||||||
? is_minor_user_for_testing_.value()
|
|
||||||
: FocusModeController::Get()->delegate()->IsMinorUser();
|
|
||||||
|
|
||||||
// Hide the YTM sound section if the flag isn't enabled or if the user is
|
// Hide the YTM sound section if the flag isn't enabled.
|
||||||
// considered a minor user.
|
if (!features::IsFocusModeYTMEnabled()) {
|
||||||
if (!features::IsFocusModeYTMEnabled() || is_minor_user) {
|
|
||||||
enabled_sound_sections_.erase(focus_mode_util::SoundType::kYouTubeMusic);
|
enabled_sound_sections_.erase(focus_mode_util::SoundType::kYouTubeMusic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -162,6 +162,11 @@ class ASH_EXPORT FocusModeSoundsController
|
|||||||
void ReportYouTubeMusicPlayback(
|
void ReportYouTubeMusicPlayback(
|
||||||
const youtube_music::PlaybackData& playback_data);
|
const youtube_music::PlaybackData& playback_data);
|
||||||
|
|
||||||
|
bool ShouldDisplayYouTubeMusicOAuth() const;
|
||||||
|
void SavePrefForDisplayYouTubeMusicOAuth();
|
||||||
|
bool ShouldDisplayYouTubeMusicFreeTrial() const;
|
||||||
|
void SavePrefForDisplayYouTubeMusicFreeTrial();
|
||||||
|
|
||||||
void set_soundscape_playlists_for_testing(
|
void set_soundscape_playlists_for_testing(
|
||||||
std::vector<std::unique_ptr<Playlist>> soundscape_playlists) {
|
std::vector<std::unique_ptr<Playlist>> soundscape_playlists) {
|
||||||
soundscape_playlists_.swap(soundscape_playlists);
|
soundscape_playlists_.swap(soundscape_playlists);
|
||||||
@@ -182,6 +187,7 @@ class ASH_EXPORT FocusModeSoundsController
|
|||||||
simulate_playback_for_testing_ = true;
|
simulate_playback_for_testing_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsMinorUser();
|
||||||
void SetIsMinorUserForTesting(bool is_minor_user);
|
void SetIsMinorUserForTesting(bool is_minor_user);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "ash/public/cpp/system_tray_client.h"
|
#include "ash/public/cpp/system_tray_client.h"
|
||||||
#include "ash/resources/vector_icons/vector_icons.h"
|
#include "ash/resources/vector_icons/vector_icons.h"
|
||||||
|
#include "ash/session/session_controller_impl.h"
|
||||||
#include "ash/shell.h"
|
#include "ash/shell.h"
|
||||||
#include "ash/strings/grit/ash_strings.h"
|
#include "ash/strings/grit/ash_strings.h"
|
||||||
#include "ash/style/error_message_toast.h"
|
#include "ash/style/error_message_toast.h"
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
#include "ash/system/focus_mode/focus_mode_controller.h"
|
#include "ash/system/focus_mode/focus_mode_controller.h"
|
||||||
#include "ash/system/focus_mode/focus_mode_detailed_view.h"
|
#include "ash/system/focus_mode/focus_mode_detailed_view.h"
|
||||||
#include "ash/system/focus_mode/focus_mode_util.h"
|
#include "ash/system/focus_mode/focus_mode_util.h"
|
||||||
|
#include "ash/system/focus_mode/sounds/focus_mode_sounds_controller.h"
|
||||||
#include "ash/system/focus_mode/sounds/playlist_view.h"
|
#include "ash/system/focus_mode/sounds/playlist_view.h"
|
||||||
#include "ash/system/focus_mode/sounds/sound_section_view.h"
|
#include "ash/system/focus_mode/sounds/sound_section_view.h"
|
||||||
#include "ash/system/model/system_tray_model.h"
|
#include "ash/system/model/system_tray_model.h"
|
||||||
@@ -31,6 +33,7 @@
|
|||||||
#include "ui/views/accessibility/view_accessibility.h"
|
#include "ui/views/accessibility/view_accessibility.h"
|
||||||
#include "ui/views/controls/label.h"
|
#include "ui/views/controls/label.h"
|
||||||
#include "ui/views/layout/box_layout_view.h"
|
#include "ui/views/layout/box_layout_view.h"
|
||||||
|
#include "ui/views/view.h"
|
||||||
#include "ui/views/view_class_properties.h"
|
#include "ui/views/view_class_properties.h"
|
||||||
|
|
||||||
namespace ash {
|
namespace ash {
|
||||||
@@ -57,16 +60,27 @@ constexpr gfx::Insets kErrorMessageButtonInsets =
|
|||||||
gfx::Insets::TLBR(8, 10, 8, 16);
|
gfx::Insets::TLBR(8, 10, 8, 16);
|
||||||
constexpr gfx::Insets kErrorMessageLabelInsets = gfx::Insets::TLBR(8, 16, 8, 0);
|
constexpr gfx::Insets kErrorMessageLabelInsets = gfx::Insets::TLBR(8, 16, 8, 0);
|
||||||
|
|
||||||
std::unique_ptr<views::BoxLayoutView> CreateNonPremiumView() {
|
// "01 Jan 2026 00:00 UTC" in milliseconds calculated by
|
||||||
|
// https://currentmillis.com/
|
||||||
|
constexpr base::Time kFreeTrialExpryTime =
|
||||||
|
base::Time::FromMillisecondsSinceUnixEpoch(1767225600000L);
|
||||||
|
|
||||||
|
bool IsFreeTrialExpired(base::Time now) {
|
||||||
|
return now >= kFreeTrialExpryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<views::BoxLayoutView> CreateYouTubeMusicAlternateViewBase(
|
||||||
|
const int label_message_id,
|
||||||
|
const int button_message_id,
|
||||||
|
views::Button::PressedCallback callback) {
|
||||||
auto box_view = std::make_unique<views::BoxLayoutView>();
|
auto box_view = std::make_unique<views::BoxLayoutView>();
|
||||||
box_view->SetOrientation(views::BoxLayout::Orientation::kVertical);
|
box_view->SetOrientation(views::BoxLayout::Orientation::kVertical);
|
||||||
box_view->SetCrossAxisAlignment(
|
box_view->SetCrossAxisAlignment(
|
||||||
views::BoxLayout::CrossAxisAlignment::kCenter);
|
views::BoxLayout::CrossAxisAlignment::kCenter);
|
||||||
box_view->SetBetweenChildSpacing(kNonPremiumChildViewsSpacing);
|
box_view->SetBetweenChildSpacing(kNonPremiumChildViewsSpacing);
|
||||||
|
|
||||||
auto* label = box_view->AddChildView(
|
auto* label = box_view->AddChildView(std::make_unique<views::Label>(
|
||||||
std::make_unique<views::Label>(l10n_util::GetStringUTF16(
|
l10n_util::GetStringUTF16(label_message_id)));
|
||||||
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_NON_PREMIUM_LABEL)));
|
|
||||||
label->SetMultiLine(true);
|
label->SetMultiLine(true);
|
||||||
// For the label view with multiple lines, we need to set the max width for
|
// For the label view with multiple lines, we need to set the max width for
|
||||||
// it to calculate the total height of multiple lines.
|
// it to calculate the total height of multiple lines.
|
||||||
@@ -77,20 +91,49 @@ std::unique_ptr<views::BoxLayoutView> CreateNonPremiumView() {
|
|||||||
label->SetEnabledColorId(cros_tokens::kCrosSysOnSurface);
|
label->SetEnabledColorId(cros_tokens::kCrosSysOnSurface);
|
||||||
|
|
||||||
auto* button = box_view->AddChildView(std::make_unique<PillButton>(
|
auto* button = box_view->AddChildView(std::make_unique<PillButton>(
|
||||||
views::Button::PressedCallback(base::BindRepeating([]() {
|
std::move(callback), l10n_util::GetStringUTF16(button_message_id),
|
||||||
Shell::Get()
|
|
||||||
->system_tray_model()
|
|
||||||
->client()
|
|
||||||
->ShowYouTubeMusicPremiumPage();
|
|
||||||
})),
|
|
||||||
l10n_util::GetStringUTF16(
|
|
||||||
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_LEARN_MORE_BUTTON),
|
|
||||||
PillButton::Type::kSecondaryWithoutIcon));
|
PillButton::Type::kSecondaryWithoutIcon));
|
||||||
button->SetBackgroundColorId(cros_tokens::kCrosSysHighlightShape);
|
button->SetBackgroundColorId(cros_tokens::kCrosSysHighlightShape);
|
||||||
button->SetButtonTextColorId(cros_tokens::kCrosSysSystemOnPrimaryContainer);
|
button->SetButtonTextColorId(cros_tokens::kCrosSysSystemOnPrimaryContainer);
|
||||||
return box_view;
|
return box_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<views::BoxLayoutView> CreateFreeTrialView() {
|
||||||
|
return CreateYouTubeMusicAlternateViewBase(
|
||||||
|
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_FREE_TRIAL_LABEL,
|
||||||
|
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_FREE_TRIAL_BUTTON,
|
||||||
|
base::BindRepeating([]() {
|
||||||
|
FocusModeController::Get()
|
||||||
|
->focus_mode_sounds_controller()
|
||||||
|
->SavePrefForDisplayYouTubeMusicFreeTrial();
|
||||||
|
|
||||||
|
Shell::Get()
|
||||||
|
->system_tray_model()
|
||||||
|
->client()
|
||||||
|
->ShowChromebookPerksYouTubePage();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<views::BoxLayoutView> CreateNonPremiumView() {
|
||||||
|
return CreateYouTubeMusicAlternateViewBase(
|
||||||
|
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_NON_PREMIUM_LABEL,
|
||||||
|
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_LEARN_MORE_BUTTON,
|
||||||
|
base::BindRepeating([]() {
|
||||||
|
Shell::Get()
|
||||||
|
->system_tray_model()
|
||||||
|
->client()
|
||||||
|
->ShowYouTubeMusicPremiumPage();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<views::BoxLayoutView> CreateOAuthView(
|
||||||
|
views::Button::PressedCallback callback) {
|
||||||
|
return CreateYouTubeMusicAlternateViewBase(
|
||||||
|
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_LABEL,
|
||||||
|
IDS_ASH_STATUS_TRAY_FOCUS_MODE_SOUNDS_OAUTH_CONSENT_BUTTON,
|
||||||
|
std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<views::Label> CreateOfflineLabel(const int message_id) {
|
std::unique_ptr<views::Label> CreateOfflineLabel(const int message_id) {
|
||||||
auto label =
|
auto label =
|
||||||
std::make_unique<views::Label>(l10n_util::GetStringUTF16(message_id));
|
std::make_unique<views::Label>(l10n_util::GetStringUTF16(message_id));
|
||||||
@@ -153,21 +196,6 @@ FocusModeSoundsView::FocusModeSoundsView(
|
|||||||
|
|
||||||
if (is_network_connected) {
|
if (is_network_connected) {
|
||||||
CreatesSoundSectionViews(sound_sections);
|
CreatesSoundSectionViews(sound_sections);
|
||||||
|
|
||||||
if (soundscape_container_) {
|
|
||||||
// Start downloading playlists for Soundscape.
|
|
||||||
DownloadPlaylistsForType(/*is_soundscape_type=*/true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (youtube_music_container_) {
|
|
||||||
// Set the no premium callback and start downloading playlists for YouTube
|
|
||||||
// Music.
|
|
||||||
sounds_controller->SetYouTubeMusicNoPremiumCallback(base::BindRepeating(
|
|
||||||
&FocusModeSoundsView::ToggleYouTubeMusicAlternateView,
|
|
||||||
weak_factory_.GetWeakPtr(), /*show=*/true));
|
|
||||||
DownloadPlaylistsForType(/*is_soundscape_type=*/false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_show_soundscapes) {
|
if (should_show_soundscapes) {
|
||||||
OnSoundscapeButtonToggled();
|
OnSoundscapeButtonToggled();
|
||||||
} else {
|
} else {
|
||||||
@@ -354,17 +382,56 @@ void FocusModeSoundsView::CreatesSoundSectionViews(
|
|||||||
if (base::Contains(sound_sections, focus_mode_util::SoundType::kSoundscape)) {
|
if (base::Contains(sound_sections, focus_mode_util::SoundType::kSoundscape)) {
|
||||||
soundscape_container_ = AddChildView(std::make_unique<SoundSectionView>(
|
soundscape_container_ = AddChildView(std::make_unique<SoundSectionView>(
|
||||||
focus_mode_util::SoundType::kSoundscape));
|
focus_mode_util::SoundType::kSoundscape));
|
||||||
|
// Start downloading playlists for Soundscape.
|
||||||
|
DownloadPlaylistsForType(/*is_soundscape_type=*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base::Contains(sound_sections,
|
if (base::Contains(sound_sections,
|
||||||
focus_mode_util::SoundType::kYouTubeMusic)) {
|
focus_mode_util::SoundType::kYouTubeMusic)) {
|
||||||
youtube_music_container_ = AddChildView(std::make_unique<SoundSectionView>(
|
youtube_music_container_ = AddChildView(std::make_unique<SoundSectionView>(
|
||||||
focus_mode_util::SoundType::kYouTubeMusic));
|
focus_mode_util::SoundType::kYouTubeMusic));
|
||||||
youtube_music_container_->SetAlternateView(CreateNonPremiumView());
|
|
||||||
|
auto* sounds_controller =
|
||||||
|
FocusModeController::Get()->focus_mode_sounds_controller();
|
||||||
|
if (sounds_controller->ShouldDisplayYouTubeMusicOAuth()) {
|
||||||
|
youtube_music_container_->SetAlternateView(
|
||||||
|
CreateOAuthView(base::BindRepeating(
|
||||||
|
&FocusModeSoundsView::OnOAuthGetStartedButtonPressed,
|
||||||
|
weak_factory_.GetWeakPtr())));
|
||||||
|
ToggleYouTubeMusicAlternateView(/*show=*/true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sounds_controller->IsMinorUser() &&
|
||||||
|
sounds_controller->ShouldDisplayYouTubeMusicFreeTrial() &&
|
||||||
|
!IsFreeTrialExpired(base::Time::Now())) {
|
||||||
|
youtube_music_container_->SetAlternateView(CreateFreeTrialView());
|
||||||
|
} else {
|
||||||
|
youtube_music_container_->SetAlternateView(CreateNonPremiumView());
|
||||||
|
}
|
||||||
ToggleYouTubeMusicAlternateView(/*show=*/false);
|
ToggleYouTubeMusicAlternateView(/*show=*/false);
|
||||||
|
DownloadPlaylistsForType(/*is_soundscape_type=*/false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FocusModeSoundsView::OnOAuthGetStartedButtonPressed() {
|
||||||
|
auto* sounds_controller =
|
||||||
|
FocusModeController::Get()->focus_mode_sounds_controller();
|
||||||
|
sounds_controller->SavePrefForDisplayYouTubeMusicOAuth();
|
||||||
|
|
||||||
|
// Sets the alternate view to either the free trial view or the non-premium
|
||||||
|
// view for `youtube_music_container_`.
|
||||||
|
if (!sounds_controller->IsMinorUser() &&
|
||||||
|
sounds_controller->ShouldDisplayYouTubeMusicFreeTrial() &&
|
||||||
|
!IsFreeTrialExpired(base::Time::Now())) {
|
||||||
|
youtube_music_container_->SetAlternateView(CreateFreeTrialView());
|
||||||
|
} else {
|
||||||
|
youtube_music_container_->SetAlternateView(CreateNonPremiumView());
|
||||||
|
}
|
||||||
|
ToggleYouTubeMusicAlternateView(/*show=*/false);
|
||||||
|
DownloadPlaylistsForType(/*is_soundscape_type=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
void FocusModeSoundsView::ToggleYouTubeMusicAlternateView(bool show) {
|
void FocusModeSoundsView::ToggleYouTubeMusicAlternateView(bool show) {
|
||||||
CHECK(youtube_music_container_);
|
CHECK(youtube_music_container_);
|
||||||
youtube_music_container_->ShowAlternateView(show);
|
youtube_music_container_->ShowAlternateView(show);
|
||||||
@@ -395,12 +462,19 @@ void FocusModeSoundsView::MayShowSoundscapeContainer(bool show) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FocusModeSoundsView::DownloadPlaylistsForType(bool is_soundscape_type) {
|
void FocusModeSoundsView::DownloadPlaylistsForType(bool is_soundscape_type) {
|
||||||
FocusModeController::Get()
|
auto* sounds_controller =
|
||||||
->focus_mode_sounds_controller()
|
FocusModeController::Get()->focus_mode_sounds_controller();
|
||||||
->DownloadPlaylistsForType(
|
|
||||||
is_soundscape_type,
|
// Set the no premium callback only if we start downloading the YTM playlists.
|
||||||
base::BindOnce(&FocusModeSoundsView::UpdateSoundsView,
|
if (!is_soundscape_type) {
|
||||||
weak_factory_.GetWeakPtr()));
|
sounds_controller->SetYouTubeMusicNoPremiumCallback(base::BindRepeating(
|
||||||
|
&FocusModeSoundsView::ToggleYouTubeMusicAlternateView,
|
||||||
|
weak_factory_.GetWeakPtr(), /*show=*/true));
|
||||||
|
}
|
||||||
|
|
||||||
|
sounds_controller->DownloadPlaylistsForType(
|
||||||
|
is_soundscape_type, base::BindOnce(&FocusModeSoundsView::UpdateSoundsView,
|
||||||
|
weak_factory_.GetWeakPtr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FocusModeSoundsView::MaybeDismissErrorMessage() {
|
void FocusModeSoundsView::MaybeDismissErrorMessage() {
|
||||||
|
@@ -66,10 +66,15 @@ class ASH_EXPORT FocusModeSoundsView
|
|||||||
void CreateHeader(const base::flat_set<focus_mode_util::SoundType>& sections,
|
void CreateHeader(const base::flat_set<focus_mode_util::SoundType>& sections,
|
||||||
bool is_network_connected);
|
bool is_network_connected);
|
||||||
|
|
||||||
// Creates `soundscape_container_` and `youtube_music_container_`.
|
// Creates `soundscape_container_` and `youtube_music_container_` and may
|
||||||
|
// download playlists.
|
||||||
void CreatesSoundSectionViews(
|
void CreatesSoundSectionViews(
|
||||||
const base::flat_set<focus_mode_util::SoundType>& sections);
|
const base::flat_set<focus_mode_util::SoundType>& sections);
|
||||||
|
|
||||||
|
// Called when the Get started button in the YouTube Music OAuth consent view
|
||||||
|
// was pressed.
|
||||||
|
void OnOAuthGetStartedButtonPressed();
|
||||||
|
|
||||||
// Toggles YouTube Music alternate view. It's used to update the UIs for
|
// Toggles YouTube Music alternate view. It's used to update the UIs for
|
||||||
// non-premium account.
|
// non-premium account.
|
||||||
void ToggleYouTubeMusicAlternateView(bool show);
|
void ToggleYouTubeMusicAlternateView(bool show);
|
||||||
|
@@ -74,6 +74,10 @@ void SoundSectionView::ShowAlternateView(bool show_alternate_view) {
|
|||||||
void SoundSectionView::SetAlternateView(
|
void SoundSectionView::SetAlternateView(
|
||||||
std::unique_ptr<views::BoxLayoutView> alternate_view) {
|
std::unique_ptr<views::BoxLayoutView> alternate_view) {
|
||||||
CHECK(alternate_view);
|
CHECK(alternate_view);
|
||||||
|
if (alternate_view_.get()) {
|
||||||
|
RemoveChildViewT(std::exchange(alternate_view_, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
alternate_view_ = AddChildView(std::move(alternate_view));
|
alternate_view_ = AddChildView(std::move(alternate_view));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -361,6 +361,8 @@ enum {
|
|||||||
kAccessibilityFlashNotificationsColor = 100299,
|
kAccessibilityFlashNotificationsColor = 100299,
|
||||||
kPinnedChromeLabsMigrationComplete = 100300,
|
kPinnedChromeLabsMigrationComplete = 100300,
|
||||||
kAccessibilityFaceGazeGesturesToKeyCombos = 100301,
|
kAccessibilityFaceGazeGesturesToKeyCombos = 100301,
|
||||||
|
kFocusModeYTMDisplayOAuthConsent = 100302,
|
||||||
|
kFocusModeYTMDisplayFreeTrial = 100303,
|
||||||
// See components/sync_preferences/README.md about adding new entries here.
|
// See components/sync_preferences/README.md about adding new entries here.
|
||||||
// vvvvv IMPORTANT! vvvvv
|
// vvvvv IMPORTANT! vvvvv
|
||||||
// Note to the reviewer: IT IS YOUR RESPONSIBILITY to ensure that new syncable
|
// Note to the reviewer: IT IS YOUR RESPONSIBILITY to ensure that new syncable
|
||||||
@@ -750,6 +752,14 @@ constexpr auto kChromeSyncablePrefsAllowlist = base::MakeFixedFlatMap<
|
|||||||
{syncable_prefs_ids::kFocusModeSoundSection, syncer::OS_PREFERENCES,
|
{syncable_prefs_ids::kFocusModeSoundSection, syncer::OS_PREFERENCES,
|
||||||
sync_preferences::PrefSensitivity::kNone,
|
sync_preferences::PrefSensitivity::kNone,
|
||||||
sync_preferences::MergeBehavior::kNone}},
|
sync_preferences::MergeBehavior::kNone}},
|
||||||
|
{ash::prefs::kFocusModeYTMDisplayOAuthConsent,
|
||||||
|
{syncable_prefs_ids::kFocusModeYTMDisplayOAuthConsent,
|
||||||
|
syncer::OS_PREFERENCES, sync_preferences::PrefSensitivity::kNone,
|
||||||
|
sync_preferences::MergeBehavior::kNone}},
|
||||||
|
{ash::prefs::kFocusModeYTMDisplayFreeTrial,
|
||||||
|
{syncable_prefs_ids::kFocusModeYTMDisplayFreeTrial, syncer::OS_PREFERENCES,
|
||||||
|
sync_preferences::PrefSensitivity::kNone,
|
||||||
|
sync_preferences::MergeBehavior::kNone}},
|
||||||
{ash::prefs::kKeyboardDefaultChromeOSSettings,
|
{ash::prefs::kKeyboardDefaultChromeOSSettings,
|
||||||
{syncable_prefs_ids::kKeyboardDefaultChromeOSSettings,
|
{syncable_prefs_ids::kKeyboardDefaultChromeOSSettings,
|
||||||
syncer::OS_PREFERENCES, sync_preferences::PrefSensitivity::kNone,
|
syncer::OS_PREFERENCES, sync_preferences::PrefSensitivity::kNone,
|
||||||
|
@@ -94,25 +94,6 @@ IN_PROC_BROWSER_TEST_F(FocusModePolicyTest, FocusModeSounds_Enabled) {
|
|||||||
testing::Pair(testing::NotNull(), testing::NotNull()));
|
testing::Pair(testing::NotNull(), testing::NotNull()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that even though we enabled both Sounscape type and YouTube Music type
|
|
||||||
// of playlists; however, if the user is a minor user, YouTube Music will be
|
|
||||||
// unavailable.
|
|
||||||
IN_PROC_BROWSER_TEST_F(FocusModePolicyTest,
|
|
||||||
FocusModeSounds_Enabled_ForMinorUser) {
|
|
||||||
FocusModeController::Get()
|
|
||||||
->focus_mode_sounds_controller()
|
|
||||||
->SetIsMinorUserForTesting(true);
|
|
||||||
SetPolicyValue("enabled");
|
|
||||||
auto* quick_settings = OpenQuickSettings();
|
|
||||||
ClickOnFocusTile(quick_settings);
|
|
||||||
FocusModeSoundsView* sounds_view = GetSoundsView(quick_settings);
|
|
||||||
EXPECT_THAT(sounds_view->GetVisible(), testing::Eq(true));
|
|
||||||
EXPECT_THAT(sounds_view->soundscape_views(),
|
|
||||||
testing::Pair(testing::IsNull(), testing::NotNull()));
|
|
||||||
EXPECT_THAT(sounds_view->youtube_music_views(),
|
|
||||||
testing::Pair(testing::IsNull(), testing::IsNull()));
|
|
||||||
}
|
|
||||||
|
|
||||||
IN_PROC_BROWSER_TEST_F(FocusModePolicyTest, FocusModeSounds_FocusSoundsOnly) {
|
IN_PROC_BROWSER_TEST_F(FocusModePolicyTest, FocusModeSounds_FocusSoundsOnly) {
|
||||||
SetPolicyValue("focus-sounds");
|
SetPolicyValue("focus-sounds");
|
||||||
auto* quick_settings = OpenQuickSettings();
|
auto* quick_settings = OpenQuickSettings();
|
||||||
|
@@ -868,6 +868,7 @@ void SystemTrayClientImpl::ShowRemapKeysSubpage(int device_id) {
|
|||||||
|
|
||||||
void SystemTrayClientImpl::ShowYouTubeMusicPremiumPage() {
|
void SystemTrayClientImpl::ShowYouTubeMusicPremiumPage() {
|
||||||
DCHECK(ash::features::IsFocusModeEnabled());
|
DCHECK(ash::features::IsFocusModeEnabled());
|
||||||
|
DCHECK(ash::features::IsFocusModeYTMEnabled());
|
||||||
base::RecordAction(base::UserMetricsAction("ShowYouTubeMusicPremiumPage"));
|
base::RecordAction(base::UserMetricsAction("ShowYouTubeMusicPremiumPage"));
|
||||||
|
|
||||||
const GURL official_url(chrome::kYoutubeMusicPremiumURL);
|
const GURL official_url(chrome::kYoutubeMusicPremiumURL);
|
||||||
@@ -899,6 +900,12 @@ void SystemTrayClientImpl::ShowYouTubeMusicPremiumPage() {
|
|||||||
official_url));
|
official_url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemTrayClientImpl::ShowChromebookPerksYouTubePage() {
|
||||||
|
DCHECK(ash::features::IsFocusModeEnabled());
|
||||||
|
DCHECK(ash::features::IsFocusModeYTMEnabled());
|
||||||
|
OpenInBrowser(GURL(chrome::kChromebookPerksYouTubePage));
|
||||||
|
}
|
||||||
|
|
||||||
void SystemTrayClientImpl::ShowEolInfoPage() {
|
void SystemTrayClientImpl::ShowEolInfoPage() {
|
||||||
const bool use_offer_url = ash::features::kEolIncentiveParam.Get() !=
|
const bool use_offer_url = ash::features::kEolIncentiveParam.Get() !=
|
||||||
ash::features::EolIncentiveParam::kNoOffer &&
|
ash::features::EolIncentiveParam::kNoOffer &&
|
||||||
|
@@ -121,6 +121,7 @@ class SystemTrayClientImpl : public ash::SystemTrayClient,
|
|||||||
void ShowTouchpadSettings() override;
|
void ShowTouchpadSettings() override;
|
||||||
void ShowRemapKeysSubpage(int device_id) override;
|
void ShowRemapKeysSubpage(int device_id) override;
|
||||||
void ShowYouTubeMusicPremiumPage() override;
|
void ShowYouTubeMusicPremiumPage() override;
|
||||||
|
void ShowChromebookPerksYouTubePage() override;
|
||||||
void ShowKeyboardSettings() override;
|
void ShowKeyboardSettings() override;
|
||||||
void ShowPointingStickSettings() override;
|
void ShowPointingStickSettings() override;
|
||||||
void ShowNearbyShareSettings() override;
|
void ShowNearbyShareSettings() override;
|
||||||
|
@@ -882,6 +882,10 @@ inline constexpr char16_t kDeviceExtendedUpdatesLearnMoreURL[] =
|
|||||||
// The URL for the YoutTube Music Premium signup page.
|
// The URL for the YoutTube Music Premium signup page.
|
||||||
inline constexpr char kYoutubeMusicPremiumURL[] =
|
inline constexpr char kYoutubeMusicPremiumURL[] =
|
||||||
"https://music.youtube.com/music_premium";
|
"https://music.youtube.com/music_premium";
|
||||||
|
|
||||||
|
// The URL for the Chromebook Perks page for YouTube.
|
||||||
|
inline constexpr char kChromebookPerksYouTubePage[] =
|
||||||
|
"https://www.google.com/chromebook/perks/?id=youtube.2020";
|
||||||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_MAC)
|
||||||
|
@@ -641,6 +641,8 @@ chromium-metrics-reviews@google.com.
|
|||||||
<int value="100299" label="kAccessibilityFlashNotificationsColor"/>
|
<int value="100299" label="kAccessibilityFlashNotificationsColor"/>
|
||||||
<int value="100300" label="PinnedChromeLabsMigrationComplete"/>
|
<int value="100300" label="PinnedChromeLabsMigrationComplete"/>
|
||||||
<int value="100301" label="AccessibilityFaceGazeGesturesToKeyCombos"/>
|
<int value="100301" label="AccessibilityFaceGazeGesturesToKeyCombos"/>
|
||||||
|
<int value="100302" label="FocusModeYTMDisplayOAuthConsent"/>
|
||||||
|
<int value="100303" label="FocusModeYTMDisplayFreeTrial"/>
|
||||||
<!-- LINT.ThenChange(/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc:ChromeSyncablePref)-->
|
<!-- LINT.ThenChange(/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc:ChromeSyncablePref)-->
|
||||||
|
|
||||||
<!-- LINT.IfChange(IosSyncablePref) -->
|
<!-- LINT.IfChange(IosSyncablePref) -->
|
||||||
|
Reference in New Issue
Block a user