-
Notifications
You must be signed in to change notification settings - Fork 887
/
brave_theme_service.cc
361 lines (314 loc) · 13.2 KB
/
brave_theme_service.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
/* Copyright (c) 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "brave/browser/themes/brave_theme_service.h"
#include <utility>
#include "base/command_line.h"
#include "base/strings/string_util.h"
#include "brave/browser/extensions/brave_theme_event_router.h"
#include "brave/browser/profiles/profile_util.h"
#include "brave/browser/themes/theme_properties.h"
#include "brave/browser/themes/brave_theme_utils.h"
#include "brave/common/brave_switches.h"
#include "brave/common/pref_names.h"
#include "brave/grit/brave_generated_resources.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/omnibox/omnibox_theme.h"
#include "chrome/common/channel_info.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/version_info/channel.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/native_theme/native_theme.h"
#if defined(OS_WIN)
#include "ui/native_theme/native_theme_win.h"
#endif
namespace {
// Omnibox text colors
const SkColor kDarkOmniboxText = SkColorSetRGB(0xff, 0xff, 0xff);
const SkColor kLightOmniboxText = SkColorSetRGB(0x42, 0x42, 0x42);
// Location bar colors
const SkColor kPrivateLocationBarBgBase = SkColorSetRGB(0x1b, 0x0e, 0x2c);
SkColor GetLocationBarBackground(bool dark, bool priv, bool hover) {
return dark ? (hover ? SkColorSetRGB(0x44, 0x44, 0x44)
: SkColorSetRGB(0x22, 0x22, 0x22))
: (priv ? color_utils::HSLShift(kPrivateLocationBarBgBase,
{-1, -1, hover ? 0.54 : 0.52})
: (hover ? color_utils::AlphaBlend(
SK_ColorWHITE,
SkColorSetRGB(0xf3, 0xf3, 0xf3), 0.7f)
: SK_ColorWHITE));
}
// Omnibox result bg colors
SkColor GetOmniboxResultBackground(int id, bool dark, bool priv) {
// For high contrast, selected rows use inverted colors to stand out more.
ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
bool high_contrast = native_theme && native_theme->UsesHighContrastColors();
OmniboxPartState state = OmniboxPartState::NORMAL;
if (id == ThemeProperties::COLOR_OMNIBOX_RESULTS_BG_HOVERED) {
state = OmniboxPartState::HOVERED;
} else if (id == ThemeProperties::COLOR_OMNIBOX_RESULTS_BG_SELECTED) {
state = OmniboxPartState::SELECTED;
}
return color_utils::BlendTowardMaxContrast(
dark
? (high_contrast ? gfx::kGoogleGrey900 : gfx::kGoogleGrey800)
: (priv ? color_utils::HSLShift(kPrivateLocationBarBgBase,
{-1, -1, high_contrast ? 0.45 : 0.56})
: SK_ColorWHITE),
gfx::ToRoundedInt(GetOmniboxStateOpacity(state) * 0xff));
}
BraveThemeType GetThemeTypeBasedOnChannel() {
switch (chrome::GetChannel()) {
case version_info::Channel::STABLE:
case version_info::Channel::BETA:
return BraveThemeType::BRAVE_THEME_TYPE_LIGHT;
case version_info::Channel::DEV:
case version_info::Channel::CANARY:
case version_info::Channel::UNKNOWN:
default:
return BraveThemeType::BRAVE_THEME_TYPE_DARK;
}
}
} // namespace
// static
std::string BraveThemeService::GetStringFromBraveThemeType(
BraveThemeType type) {
switch (type) {
case BraveThemeType::BRAVE_THEME_TYPE_LIGHT:
return "Light";
case BraveThemeType::BRAVE_THEME_TYPE_DARK:
return "Dark";
default:
NOTREACHED();
return "Default";
}
}
// static
void BraveThemeService::SetBraveThemeType(Profile* profile, std::string type) {
BraveThemeType parsedType = BraveThemeType::BRAVE_THEME_TYPE_DEFAULT;
if (type == "Light") {
parsedType = BraveThemeType::BRAVE_THEME_TYPE_LIGHT;
} else if (type == "Dark") {
parsedType = BraveThemeType::BRAVE_THEME_TYPE_DARK;
}
profile->GetPrefs()->SetInteger(kBraveThemeType, parsedType);
}
// static
base::Value BraveThemeService::GetBraveThemeList() {
base::Value list(base::Value::Type::LIST);
if (SystemThemeModeEnabled()) {
base::Value system_type(base::Value::Type::DICTIONARY);
system_type.SetKey(
"value",
base::Value(BraveThemeType::BRAVE_THEME_TYPE_DEFAULT));
system_type.SetKey(
"name",
base::Value(l10n_util::GetStringUTF16(IDS_BRAVE_THEME_TYPE_SYSTEM)));
list.GetList().push_back(std::move(system_type));
}
base::Value dark_type(base::Value::Type::DICTIONARY);
dark_type.SetKey("value", base::Value(BraveThemeType::BRAVE_THEME_TYPE_DARK));
dark_type.SetKey(
"name",
base::Value(l10n_util::GetStringUTF16(IDS_BRAVE_THEME_TYPE_DARK)));
list.GetList().push_back(std::move(dark_type));
base::Value light_type(base::Value::Type::DICTIONARY);
light_type.SetKey("value",
base::Value(BraveThemeType::BRAVE_THEME_TYPE_LIGHT));
light_type.SetKey(
"name",
base::Value(l10n_util::GetStringUTF16(IDS_BRAVE_THEME_TYPE_LIGHT)));
list.GetList().push_back(std::move(light_type));
return list;
}
// static
void BraveThemeService::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterIntegerPref(kBraveThemeType, BRAVE_THEME_TYPE_DEFAULT);
// When this is set to true, prefs is changed from default type to
// effective type. In dtor, pref is reverted to default type if this is
// still true. With this, we can preserve the context that user didn't touch
// theme type yet. If it is changed to false, it means user changes system
// theme explicitly.
// To handle crash case, prefs is used instead of boolean flags. Recovering
// is done in BraveThemeService::Init().
registry->RegisterBooleanPref(kUseOverriddenBraveThemeType, false);
}
// static
BraveThemeType BraveThemeService::GetActiveBraveThemeType(
Profile* profile) {
// allow override via cli flag
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kUiMode)) {
std::string requested_theme_value =
command_line.GetSwitchValueASCII(switches::kUiMode);
std::string requested_theme_value_lower =
base::ToLowerASCII(requested_theme_value);
if (requested_theme_value_lower == "light")
return BraveThemeType::BRAVE_THEME_TYPE_LIGHT;
if (requested_theme_value_lower == "dark")
return BraveThemeType::BRAVE_THEME_TYPE_DARK;
}
BraveThemeType type = static_cast<BraveThemeType>(
profile->GetPrefs()->GetInteger(kBraveThemeType));
if (type == BraveThemeType::BRAVE_THEME_TYPE_DEFAULT) {
DCHECK(SystemThemeModeEnabled());
return ui::NativeTheme::GetInstanceForNativeUi()->ShouldUseDarkColors()
? BraveThemeType::BRAVE_THEME_TYPE_DARK
: BraveThemeType::BRAVE_THEME_TYPE_LIGHT;
}
return type;
}
BraveThemeService::BraveThemeService() {}
BraveThemeService::~BraveThemeService() {
// In test, kBraveThemeType isn't registered.
if (!profile()->GetPrefs()->FindPreference(kBraveThemeType))
return;
if (profile()->GetPrefs()->GetBoolean(kUseOverriddenBraveThemeType)) {
brave_theme_type_pref_.Destroy();
profile()->GetPrefs()->SetInteger(kBraveThemeType,
BraveThemeType::BRAVE_THEME_TYPE_DEFAULT);
}
}
void BraveThemeService::Init(Profile* profile) {
ThemeService::Init(profile);
// In test, kBraveThemeType isn't registered.
if (profile->GetPrefs()->FindPreference(kBraveThemeType)) {
RecoverPrefStates(profile);
OverrideDefaultThemeIfNeeded(profile);
// Prevent to overwrite system theme type by using tor/guest profile's one.
// System theme type is global value not the profile specific.
// So, SetSystemTheme() should not be called by tor/guest profile.
// If not, system theme is changed when tor/guest profile is created.
// Also, brave theme type could not be changed by tor/guest window.
// So, we don't need to care about pref change of their profile.
if (brave::IsTorProfile(profile) || brave::IsGuestProfile(profile))
return;
#if defined(OS_WIN)
ui::IgnoreSystemDarkModeChange(
profile->GetPrefs()->GetInteger(kBraveThemeType) !=
BraveThemeType::BRAVE_THEME_TYPE_DEFAULT);
#endif
// Start with proper system theme to make brave theme and
// base ui components theme use same theme.
SetSystemTheme(static_cast<BraveThemeType>(
profile->GetPrefs()->GetInteger(kBraveThemeType)));
brave_theme_type_pref_.Init(
kBraveThemeType,
profile->GetPrefs(),
base::Bind(&BraveThemeService::OnPreferenceChanged,
base::Unretained(this)));
brave_theme_event_router_.reset(
new extensions::BraveThemeEventRouter(profile));
}
}
SkColor BraveThemeService::GetDefaultColor(int id, bool incognito) const {
#if defined(OS_LINUX)
// IF gtk theme is selected, respect it.
if (UsingSystemTheme())
return ThemeService::GetDefaultColor(id, incognito);
#endif
// Brave Tor profiles are always 'incognito' (for now)
if (!incognito &&
(brave::IsTorProfile(profile()) || brave::IsGuestProfile(profile())))
incognito = true;
const BraveThemeType theme = GetActiveBraveThemeType(profile());
const base::Optional<SkColor> braveColor =
MaybeGetDefaultColorForBraveUi(id, incognito, theme);
if (braveColor)
return braveColor.value();
// make sure we fallback to chrome's dark theme (incognito) for our dark theme
if (theme == BraveThemeType::BRAVE_THEME_TYPE_DARK)
incognito = true;
return ThemeService::GetDefaultColor(id, incognito);
}
base::Optional<SkColor> BraveThemeService::GetOmniboxColor(
int id,
bool incognito,
bool* has_custom_color) const {
#if defined(OS_LINUX)
// If gtk theme is selected, respect it.
if (UsingSystemTheme())
return ThemeService::GetOmniboxColor(id, incognito, has_custom_color);
#endif
const bool dark = GetActiveBraveThemeType(profile()) ==
BraveThemeType::BRAVE_THEME_TYPE_DARK;
incognito = incognito || brave::IsTorProfile(profile()) ||
brave::IsGuestProfile(profile());
// TODO(petemill): Get colors from color-pallete and theme constants
switch (id) {
case ThemeProperties::COLOR_OMNIBOX_BACKGROUND: {
return GetLocationBarBackground(dark, incognito, /*hover*/ false);
}
case ThemeProperties::COLOR_OMNIBOX_BACKGROUND_HOVERED: {
return GetLocationBarBackground(dark, incognito, /*hover*/ true);
}
case ThemeProperties::COLOR_OMNIBOX_TEXT: {
return (dark || incognito) ? kDarkOmniboxText : kLightOmniboxText;
}
case ThemeProperties::COLOR_OMNIBOX_RESULTS_BG:
case ThemeProperties::COLOR_OMNIBOX_RESULTS_BG_HOVERED:
case ThemeProperties::COLOR_OMNIBOX_RESULTS_BG_SELECTED: {
return GetOmniboxResultBackground(id, dark, incognito);
}
default:
break;
}
// All other values, call original function
return ThemeService::GetOmniboxColor(id, incognito, has_custom_color);
}
void BraveThemeService::OnPreferenceChanged(const std::string& pref_name) {
DCHECK(pref_name == kBraveThemeType);
// Changing theme type means default theme is not overridden anymore.
profile()->GetPrefs()->SetBoolean(kUseOverriddenBraveThemeType, false);
#if defined(OS_WIN)
ui::IgnoreSystemDarkModeChange(
profile()->GetPrefs()->GetInteger(kBraveThemeType) !=
BraveThemeType::BRAVE_THEME_TYPE_DEFAULT);
#endif
SetSystemTheme(static_cast<BraveThemeType>(
profile()->GetPrefs()->GetInteger(kBraveThemeType)));
}
void BraveThemeService::RecoverPrefStates(Profile* profile) {
// kUseOverriddenBraveThemeType is true means pref states are not cleaned
// up properly at the last running(ex, crash). Recover them here.
if (profile->GetPrefs()->GetBoolean(kUseOverriddenBraveThemeType)) {
profile->GetPrefs()->SetInteger(kBraveThemeType,
BraveThemeType::BRAVE_THEME_TYPE_DEFAULT);
}
}
void BraveThemeService::OverrideDefaultThemeIfNeeded(Profile* profile) {
if (!SystemThemeModeEnabled() &&
profile->GetPrefs()->GetInteger(kBraveThemeType) ==
BraveThemeType::BRAVE_THEME_TYPE_DEFAULT) {
profile->GetPrefs()->SetBoolean(kUseOverriddenBraveThemeType,
true);
profile->GetPrefs()->SetInteger(kBraveThemeType,
GetThemeTypeBasedOnChannel());
}
}
void BraveThemeService::SetBraveThemeEventRouterForTesting(
extensions::BraveThemeEventRouter* mock_router) {
brave_theme_event_router_.reset(mock_router);
}
// static
bool BraveThemeService::use_system_theme_mode_in_test_ = false;
bool BraveThemeService::is_test_ = false;
// static
bool BraveThemeService::SystemThemeModeEnabled() {
if (is_test_)
return use_system_theme_mode_in_test_;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceDarkMode))
return true;
return ui::NativeTheme::GetInstanceForNativeUi()->SystemDarkModeSupported();
}