File: translate_prefs.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (398 lines) | stat: -rw-r--r-- 17,953 bytes parent folder | download | duplicates (5)
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
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_PREFS_H_
#define COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_PREFS_H_

#include <stddef.h>

#include <memory>
#include <string>
#include <string_view>
#include <vector>

#include "base/feature_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"

class PrefService;

namespace user_prefs {
class PrefRegistrySyncable;
}

namespace language {
class LanguagePrefs;
}

namespace translate {

// Enables or disables using the most recent target language as the default
// target language option.
BASE_DECLARE_FEATURE(kTranslateRecentTarget);

// Whether to migrate the obsolete always-translate languages pref to the new
// pref during object construction as a fix for crbug/1291356, which had
// previously not been migrated at all on iOS. This also enables a more
// conservative pref merging process that aims to merge in old always-translate
// language values from the obsolete pref without conflicting with any values in
// the new pref that may have been added.
//
// TODO(crbug.com/40826252): This base::Feature only exists to allow a less
// risky merge into iOS M98. This base::Feature should be removed once it's no
// longer relevant and the enabled behavior should become the only behavior.
BASE_DECLARE_FEATURE(kMigrateAlwaysTranslateLanguagesFix);

// Minimum number of times the user must accept a translation before we show
// a shortcut to the "Always Translate" functionality.
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
// The "Always Translate" shortcut is always shown on iOS and Android.
constexpr int kAlwaysTranslateShortcutMinimumAccepts = 1;
#else
constexpr int kAlwaysTranslateShortcutMinimumAccepts = 3;
#endif

// Minimum number of times the user must deny a translation before we show
// a shortcut to the "Never Translate" functionality.
// Android and iOS implementations do not offer a drop down (for space reasons),
// so we are more aggressive about showing this shortcut.
#if BUILDFLAG(IS_ANDROID)
// On Android, this shows the "Never Translate" shortcut after two denials just
// like on iOS. However, the last event is not counted so we must subtract one
// to get the same behavior.
constexpr int kNeverTranslateShortcutMinimumDenials = 1;
#elif BUILDFLAG(IS_IOS)
constexpr int kNeverTranslateShortcutMinimumDenials = 2;
#else
constexpr int kNeverTranslateShortcutMinimumDenials = 3;
#endif

// This class holds various info about a language, that are related to Translate
// Preferences and Language Settings.
struct TranslateLanguageInfo {
  TranslateLanguageInfo();

  TranslateLanguageInfo(const TranslateLanguageInfo&);
  TranslateLanguageInfo(TranslateLanguageInfo&&) noexcept;
  TranslateLanguageInfo& operator=(const TranslateLanguageInfo&);
  TranslateLanguageInfo& operator=(TranslateLanguageInfo&&) noexcept;

  // This ISO code of the language.
  std::string code;
  // The display name of the language in the current locale.
  std::string display_name;
  // The display name of the language in the language locale.
  std::string native_display_name;
  // Whether we support translate for this language.
  bool supports_translate = false;
};

// The wrapper of PrefService object for Translate.
//
// It is assumed that |prefs_| is alive while this instance is alive.
class TranslatePrefs {
 public:
  static constexpr char kPrefForceTriggerTranslateCount[] =
      "translate_force_trigger_on_english_count_for_backoff_1";
  // TODO(crbug.com/40433029): Remove kPrefNeverPromptSites after
  // 3 milestones (M74).
  static constexpr char kPrefNeverPromptSitesDeprecated[] =
      "translate_site_blacklist";
  static constexpr char kPrefTranslateDeniedCount[] =
      "translate_denied_count_for_language";
  static constexpr char kPrefTranslateIgnoredCount[] =
      "translate_ignored_count_for_language";
  static constexpr char kPrefTranslateAcceptedCount[] =
      "translate_accepted_count";

  // TODO(crbug.com/40826252): Deprecated 10/2021. Check status of bug before
  // removing.
  static constexpr char kPrefAlwaysTranslateListDeprecated[] =
      "translate_whitelists";

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
  static constexpr char kPrefTranslateAutoAlwaysCount[] =
      "translate_auto_always_count";
  static constexpr char kPrefTranslateAutoNeverCount[] =
      "translate_auto_never_count";
#endif

  // This parameter specifies how the language should be moved within the list.
  enum RearrangeSpecifier {
    // No-op enumerator.
    kNone,
    // Move the language to the very top of the list.
    kTop,
    // Move the language up towards the front of the list.
    kUp,
    // Move the language down towards the back of the list.
    kDown
  };

  explicit TranslatePrefs(PrefService* user_prefs);

  TranslatePrefs(const TranslatePrefs&) = delete;
  TranslatePrefs& operator=(const TranslatePrefs&) = delete;

  ~TranslatePrefs();

  // Some existing preferences do not follow inclusive naming. Existing
  // preference names cannot be renamed since values are saved client side.
  // Map these to inclusive alternatives to reduce references to those names in
  // the rest of the code.
  static std::string MapPreferenceName(const std::string& pref_name);

  // Returns true if the "offer translate" pref is enabled (i.e. allowing for
  // automatic Full Page Translate bubbles).
  bool IsOfferTranslateEnabled() const;

  // Returns true if Translate is allowed by policy.
  bool IsTranslateAllowedByPolicy() const;

  // Sets the country that the application is run in. Determined by the
  // VariationsService, can be left empty. Used by the TranslateRanker.
  void SetCountry(const std::string& country);
  std::string GetCountry() const;

  // Resets the blocked languages list, the never-translate site list, the
  // always-translate languages list, the accepted/denied counts, and whether
  // Translate is enabled.
  void ResetToDefaults();

  // Before adding to, removing from, or checking the block list the source
  // language is converted to its translate synonym.
  // A blocked language will not be offered to be translated. All blocked
  // languages form the "Never translate" list.
  bool IsBlockedLanguage(std::string_view source_language) const;
  void BlockLanguage(std::string_view source_language);
  void UnblockLanguage(std::string_view source_language);
  // Returns the languages that should be blocked by default as a
  // base::Value::List.
  static base::Value::List GetDefaultBlockedLanguages();
  void ResetBlockedLanguagesToDefault();
  // Prevent empty blocked languages by resetting them to the default value.
  // (crbug.com/902354)
  void ResetEmptyBlockedLanguagesToDefaults();
  // Get the languages that for which translation should never be prompted
  // formatted as Chrome language codes.
  std::vector<std::string> GetNeverTranslateLanguages() const;

  // Adds the language to the language list at chrome://settings/languages.
  // If the param |force_blocked| is set to true, the language is added to the
  // blocked list.
  // If force_blocked is set to false, the language is added to the blocked list
  // if the language list does not already contain another language with the
  // same base language.
  void AddToLanguageList(std::string_view language, bool force_blocked);
  // Removes the language from the language list at chrome://settings/languages.
  void RemoveFromLanguageList(std::string_view language);

  // Rearranges the given language inside the language list.
  // The direction of the move is specified as a RearrangeSpecifier.
  // |offset| is ignored unless the RearrangeSpecifier is kUp or kDown: in
  // which case it needs to be positive for any change to be made.
  // The param |enabled_languages| is a list of languages that are enabled in
  // the current UI. This is required because the full language list contains
  // some languages that might not be enabled in the current UI and we need to
  // skip those languages while rearranging the list.
  void RearrangeLanguage(std::string_view language,
                         RearrangeSpecifier where,
                         int offset,
                         const std::vector<std::string>& enabled_languages);

  // Sets the language order to the provided order.
  // This function is called from the language preference manager in Chrome for
  // Android.
  void SetLanguageOrder(const std::vector<std::string>& new_order);

  // Returns the list of TranslateLanguageInfo for all languages that are
  // available in the given locale.
  // The list returned in |languages| is sorted alphabetically based on the
  // display names in the given locale.
  // May cause a supported language list fetch unless |translate_allowed| is
  // false.
  static void GetLanguageInfoList(
      const std::string& app_locale,
      bool translate_allowed,
      std::vector<TranslateLanguageInfo>* languages);

  // Returns a list of language codes representing content language set by the
  // user that are translatable for given app_language. The list returned in
  // |codes| is ordered based on the user's ordering. In case user has
  // country variants for a specific language set, the language main
  // translatable language is returned, e.g. if a user has "de" and "de-CH", the
  // result is "de", if a user only has "de-CH" content language set, "de" is
  // returned.
  void GetTranslatableContentLanguages(const std::string& app_locale,
                                       std::vector<std::string>* codes);

  bool IsSiteOnNeverPromptList(std::string_view site) const;
  void AddSiteToNeverPromptList(std::string_view site);
  void RemoveSiteFromNeverPromptList(std::string_view site);

  std::vector<std::string> GetNeverPromptSitesBetween(base::Time begin,
                                                      base::Time end) const;
  void DeleteNeverPromptSitesBetween(base::Time begin, base::Time end);

  bool HasLanguagePairsToAlwaysTranslate() const;

  bool IsLanguagePairOnAlwaysTranslateList(std::string_view source_language,
                                           std::string_view target_language);
  // Converts the source and target language to their translate synonym and
  // adds the pair to the always translate dict.
  void AddLanguagePairToAlwaysTranslateList(std::string_view source_language,
                                            std::string_view target_language);
  // Removes the translate synonym of source_language from the always
  // translate dict.
  void RemoveLanguagePairFromAlwaysTranslateList(
      std::string_view source_language);

  // Gets the languages that are set to always translate formatted as Chrome
  // language codes.
  std::vector<std::string> GetAlwaysTranslateLanguages() const;

  // These methods are used to track how many times the user has denied the
  // translation for a specific language. (So we can present a UI to blocklist
  // that language if the user keeps denying translations).
  int GetTranslationDeniedCount(std::string_view language) const;
  void IncrementTranslationDeniedCount(std::string_view language);
  void ResetTranslationDeniedCount(std::string_view language);

  // These methods are used to track how many times the user has ignored the
  // translation bubble for a specific language.
  int GetTranslationIgnoredCount(std::string_view language) const;
  void IncrementTranslationIgnoredCount(std::string_view language);
  void ResetTranslationIgnoredCount(std::string_view language);

  // These methods are used to track how many times the user has accepted the
  // translation for a specific language. (So we can present a UI to allowlist
  // that language if the user keeps accepting translations).
  int GetTranslationAcceptedCount(std::string_view language) const;
  void IncrementTranslationAcceptedCount(std::string_view language);
  void ResetTranslationAcceptedCount(std::string_view language);

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
  // These methods are used to track how many times the auto-always translation
  // has been triggered for a specific language.
  int GetTranslationAutoAlwaysCount(std::string_view language) const;
  void IncrementTranslationAutoAlwaysCount(std::string_view language);
  void ResetTranslationAutoAlwaysCount(std::string_view language);

  // These methods are used to track how many times the auto-never translation
  // has been triggered for a specific language.
  int GetTranslationAutoNeverCount(std::string_view language) const;
  void IncrementTranslationAutoNeverCount(std::string_view language);
  void ResetTranslationAutoNeverCount(std::string_view language);
#endif

#if BUILDFLAG(IS_ANDROID)
  // These methods are used to determine whether the app language prompt was
  // displayed to the user already. Once shown it can not be unset.
  bool GetAppLanguagePromptShown() const;
  void SetAppLanguagePromptShown();
#endif

  // Gets the full (policy-forced and user selected) language list from language
  // settings.
  void GetLanguageList(std::vector<std::string>* languages) const;

  // Gets the user selected language list from language settings.
  void GetUserSelectedLanguageList(std::vector<std::string>* languages) const;

  // Returns true if translate should trigger the UI on English
  // pages, even when the UI language is English. This function also records
  // whether the backoff threshold was reached in UMA.
  bool ShouldForceTriggerTranslateOnEnglishPages();
  static void SetShouldForceTriggerTranslateOnEnglishPagesForTesting();

  bool CanTranslateLanguage(std::string_view language);
  bool ShouldAutoTranslate(std::string_view source_language,
                           std::string* target_language);
  // True if the detailed language settings are enabled for this user.
  static bool IsDetailedLanguageSettingsEnabled();

  // Stores and retrieves the last-observed translate target language. Used to
  // determine which target language to offer in future. The translate target
  // is converted to a translate synonym before it is set.
  void SetRecentTargetLanguage(const std::string& target_language);
  void ResetRecentTargetLanguage();
  std::string GetRecentTargetLanguage() const;

  // Gets the value for the pref that represents how often the
  // force English in India feature made translate trigger on an
  // English page when it otherwise wouldn't have. This pref is used to
  // determine whether the feature should be suppressed for a particular user
  int GetForceTriggerOnEnglishPagesCount() const;
  // Increments the pref that represents how often the
  // force English in India feature made translate trigger on an
  // English page when it otherwise wouldn't have.
  void ReportForceTriggerOnEnglishPages();
  // Sets to -1 the pref that represents how often the
  // force English in India feature made translate trigger on an
  // English page when it otherwise wouldn't have. This is a special value that
  // signals that the backoff should not happen for that user.
  void ReportAcceptedAfterForceTriggerOnEnglishPages();

  // Migrate the sites to never translate from a list to a dictionary that maps
  // sites to a timestamp of the creation of this entry.
  void MigrateNeverPromptSites();

  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);

  static void RegisterProfilePrefsForMigration(
      user_prefs::PrefRegistrySyncable* registry);

 private:
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest,
                           UpdateLanguageListFeatureEnabled);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, BlockLanguage);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, UnblockLanguage);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, AddToLanguageList);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, RemoveFromLanguageList);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest,
                           RemoveFromLanguageListRemovesRemainingUnsupported);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest,
                           RemoveFromLanguageListClearsRecentLanguage);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, AddToLanguageList);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, RemoveFromLanguageList);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, MoveLanguageToTheTop);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, MoveLanguageUp);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, MoveLanguageDown);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, ResetBlockedLanguagesToDefault);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, MigrateNeverPromptSites);
  FRIEND_TEST_ALL_PREFIXES(TranslatePrefsTest, SiteNeverPromptList);
  friend class TranslatePrefsTest;

  void ClearNeverPromptSiteList();
  void ClearAlwaysTranslateLanguagePairs();

  // |pref_id| is the name of a list pref.
  bool IsValueOnNeverPromptList(const char* pref_id,
                                std::string_view value) const;
  void AddValueToNeverPromptList(const char* pref_id, std::string_view value);
  // Used for testing. The public version passes in base::Time::Now()
  void AddSiteToNeverPromptList(std::string_view site, base::Time time);
  void RemoveValueFromNeverPromptList(const char* pref_id,
                                      std::string_view value);
  size_t GetListSize(const char* pref_id) const;

  bool IsDictionaryEmpty(const char* pref_id) const;

  raw_ptr<PrefService> prefs_;  // Weak.

  std::string country_;  // The country the app runs in.

  std::unique_ptr<language::LanguagePrefs> language_prefs_;

  static bool force_translate_on_english_for_testing_;
};

}  // namespace translate

#endif  // COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_PREFS_H_