• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/translate/core/browser/translate_prefs.h"
6 
7 #include <set>
8 
9 #include "base/prefs/pref_service.h"
10 #include "base/prefs/scoped_user_pref_update.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_util.h"
13 #include "components/pref_registry/pref_registry_syncable.h"
14 #include "components/translate/core/browser/translate_accept_languages.h"
15 #include "components/translate/core/browser/translate_download_manager.h"
16 #include "components/translate/core/common/translate_util.h"
17 
18 namespace translate {
19 
20 const char TranslatePrefs::kPrefTranslateLanguageBlacklist[] =
21     "translate_language_blacklist";
22 const char TranslatePrefs::kPrefTranslateSiteBlacklist[] =
23     "translate_site_blacklist";
24 const char TranslatePrefs::kPrefTranslateWhitelists[] =
25     "translate_whitelists";
26 const char TranslatePrefs::kPrefTranslateDeniedCount[] =
27     "translate_denied_count";
28 const char TranslatePrefs::kPrefTranslateAcceptedCount[] =
29     "translate_accepted_count";
30 const char TranslatePrefs::kPrefTranslateBlockedLanguages[] =
31     "translate_blocked_languages";
32 const char TranslatePrefs::kPrefTranslateLastDeniedTime[] =
33     "translate_last_denied_time";
34 const char TranslatePrefs::kPrefTranslateTooOftenDenied[] =
35     "translate_too_often_denied";
36 
37 namespace {
38 
GetBlacklistedLanguages(const PrefService * prefs,std::vector<std::string> * languages)39 void GetBlacklistedLanguages(const PrefService* prefs,
40                              std::vector<std::string>* languages) {
41   DCHECK(languages);
42   DCHECK(languages->empty());
43 
44   const char* key = TranslatePrefs::kPrefTranslateLanguageBlacklist;
45   const base::ListValue* list = prefs->GetList(key);
46   for (base::ListValue::const_iterator it = list->begin();
47        it != list->end(); ++it) {
48     std::string lang;
49     (*it)->GetAsString(&lang);
50     languages->push_back(lang);
51   }
52 }
53 
54 // Expands language codes to make these more suitable for Accept-Language.
55 // Example: ['en-US', 'ja', 'en-CA'] => ['en-US', 'en', 'ja', 'en-CA'].
56 // 'en' won't appear twice as this function eliminates duplicates.
ExpandLanguageCodes(const std::vector<std::string> & languages,std::vector<std::string> * expanded_languages)57 void ExpandLanguageCodes(const std::vector<std::string>& languages,
58                          std::vector<std::string>* expanded_languages) {
59   DCHECK(expanded_languages);
60   DCHECK(expanded_languages->empty());
61 
62   // used to eliminate duplicates.
63   std::set<std::string> seen;
64 
65   for (std::vector<std::string>::const_iterator it = languages.begin();
66        it != languages.end(); ++it) {
67     const std::string& language = *it;
68     if (seen.find(language) == seen.end()) {
69       expanded_languages->push_back(language);
70       seen.insert(language);
71     }
72 
73     std::vector<std::string> tokens;
74     base::SplitString(language, '-', &tokens);
75     if (tokens.size() == 0)
76       continue;
77     const std::string& main_part = tokens[0];
78     if (seen.find(main_part) == seen.end()) {
79       expanded_languages->push_back(main_part);
80       seen.insert(main_part);
81     }
82   }
83 }
84 
85 }  // namespace
86 
TranslatePrefs(PrefService * user_prefs,const char * accept_languages_pref,const char * preferred_languages_pref)87 TranslatePrefs::TranslatePrefs(PrefService* user_prefs,
88                                const char* accept_languages_pref,
89                                const char* preferred_languages_pref)
90     : accept_languages_pref_(accept_languages_pref),
91       prefs_(user_prefs) {
92 #if defined(OS_CHROMEOS)
93   preferred_languages_pref_ = preferred_languages_pref;
94 #else
95   DCHECK(!preferred_languages_pref);
96 #endif
97 }
98 
ResetToDefaults()99 void TranslatePrefs::ResetToDefaults() {
100   ClearBlockedLanguages();
101   ClearBlacklistedSites();
102   ClearWhitelistedLanguagePairs();
103 
104   std::vector<std::string> languages;
105   GetLanguageList(&languages);
106   for (std::vector<std::string>::const_iterator it = languages.begin();
107       it != languages.end(); ++it) {
108     const std::string& language = *it;
109     ResetTranslationAcceptedCount(language);
110     ResetTranslationDeniedCount(language);
111   }
112 
113   prefs_->ClearPref(kPrefTranslateLastDeniedTime);
114   prefs_->ClearPref(kPrefTranslateTooOftenDenied);
115 }
116 
IsBlockedLanguage(const std::string & original_language) const117 bool TranslatePrefs::IsBlockedLanguage(
118     const std::string& original_language) const {
119   return IsValueBlacklisted(kPrefTranslateBlockedLanguages,
120                             original_language);
121 }
122 
BlockLanguage(const std::string & original_language)123 void TranslatePrefs::BlockLanguage(const std::string& original_language) {
124   BlacklistValue(kPrefTranslateBlockedLanguages, original_language);
125 
126   // Add the language to the language list at chrome://settings/languages.
127   std::string language = original_language;
128   translate::ToChromeLanguageSynonym(&language);
129 
130   std::vector<std::string> languages;
131   GetLanguageList(&languages);
132 
133   if (std::find(languages.begin(), languages.end(), language) ==
134       languages.end()) {
135     languages.push_back(language);
136     UpdateLanguageList(languages);
137   }
138 }
139 
UnblockLanguage(const std::string & original_language)140 void TranslatePrefs::UnblockLanguage(const std::string& original_language) {
141   RemoveValueFromBlacklist(kPrefTranslateBlockedLanguages, original_language);
142 }
143 
RemoveLanguageFromLegacyBlacklist(const std::string & original_language)144 void TranslatePrefs::RemoveLanguageFromLegacyBlacklist(
145     const std::string& original_language) {
146   RemoveValueFromBlacklist(kPrefTranslateLanguageBlacklist, original_language);
147 }
148 
IsSiteBlacklisted(const std::string & site) const149 bool TranslatePrefs::IsSiteBlacklisted(const std::string& site) const {
150   return IsValueBlacklisted(kPrefTranslateSiteBlacklist, site);
151 }
152 
BlacklistSite(const std::string & site)153 void TranslatePrefs::BlacklistSite(const std::string& site) {
154   BlacklistValue(kPrefTranslateSiteBlacklist, site);
155 }
156 
RemoveSiteFromBlacklist(const std::string & site)157 void TranslatePrefs::RemoveSiteFromBlacklist(const std::string& site) {
158   RemoveValueFromBlacklist(kPrefTranslateSiteBlacklist, site);
159 }
160 
IsLanguagePairWhitelisted(const std::string & original_language,const std::string & target_language)161 bool TranslatePrefs::IsLanguagePairWhitelisted(
162     const std::string& original_language,
163     const std::string& target_language) {
164   const base::DictionaryValue* dict =
165       prefs_->GetDictionary(kPrefTranslateWhitelists);
166   if (dict && !dict->empty()) {
167     std::string auto_target_lang;
168     if (dict->GetString(original_language, &auto_target_lang) &&
169         auto_target_lang == target_language)
170       return true;
171   }
172   return false;
173 }
174 
WhitelistLanguagePair(const std::string & original_language,const std::string & target_language)175 void TranslatePrefs::WhitelistLanguagePair(const std::string& original_language,
176                                            const std::string& target_language) {
177   DictionaryPrefUpdate update(prefs_, kPrefTranslateWhitelists);
178   base::DictionaryValue* dict = update.Get();
179   if (!dict) {
180     NOTREACHED() << "Unregistered translate whitelist pref";
181     return;
182   }
183   dict->SetString(original_language, target_language);
184 }
185 
RemoveLanguagePairFromWhitelist(const std::string & original_language,const std::string & target_language)186 void TranslatePrefs::RemoveLanguagePairFromWhitelist(
187     const std::string& original_language,
188     const std::string& target_language) {
189   DictionaryPrefUpdate update(prefs_, kPrefTranslateWhitelists);
190   base::DictionaryValue* dict = update.Get();
191   if (!dict) {
192     NOTREACHED() << "Unregistered translate whitelist pref";
193     return;
194   }
195   dict->Remove(original_language, NULL);
196 }
197 
HasBlockedLanguages() const198 bool TranslatePrefs::HasBlockedLanguages() const {
199   return !IsListEmpty(kPrefTranslateBlockedLanguages);
200 }
201 
ClearBlockedLanguages()202 void TranslatePrefs::ClearBlockedLanguages() {
203   prefs_->ClearPref(kPrefTranslateBlockedLanguages);
204 }
205 
HasBlacklistedSites() const206 bool TranslatePrefs::HasBlacklistedSites() const {
207   return !IsListEmpty(kPrefTranslateSiteBlacklist);
208 }
209 
ClearBlacklistedSites()210 void TranslatePrefs::ClearBlacklistedSites() {
211   prefs_->ClearPref(kPrefTranslateSiteBlacklist);
212 }
213 
HasWhitelistedLanguagePairs() const214 bool TranslatePrefs::HasWhitelistedLanguagePairs() const {
215   return !IsDictionaryEmpty(kPrefTranslateWhitelists);
216 }
217 
ClearWhitelistedLanguagePairs()218 void TranslatePrefs::ClearWhitelistedLanguagePairs() {
219   prefs_->ClearPref(kPrefTranslateWhitelists);
220 }
221 
GetTranslationDeniedCount(const std::string & language) const222 int TranslatePrefs::GetTranslationDeniedCount(
223     const std::string& language) const {
224   const base::DictionaryValue* dict =
225       prefs_->GetDictionary(kPrefTranslateDeniedCount);
226   int count = 0;
227   return dict->GetInteger(language, &count) ? count : 0;
228 }
229 
IncrementTranslationDeniedCount(const std::string & language)230 void TranslatePrefs::IncrementTranslationDeniedCount(
231     const std::string& language) {
232   DictionaryPrefUpdate update(prefs_, kPrefTranslateDeniedCount);
233   base::DictionaryValue* dict = update.Get();
234 
235   int count = 0;
236   dict->GetInteger(language, &count);
237   dict->SetInteger(language, count + 1);
238 }
239 
ResetTranslationDeniedCount(const std::string & language)240 void TranslatePrefs::ResetTranslationDeniedCount(const std::string& language) {
241   DictionaryPrefUpdate update(prefs_, kPrefTranslateDeniedCount);
242   update.Get()->SetInteger(language, 0);
243 }
244 
GetTranslationAcceptedCount(const std::string & language)245 int TranslatePrefs::GetTranslationAcceptedCount(const std::string& language) {
246   const base::DictionaryValue* dict =
247       prefs_->GetDictionary(kPrefTranslateAcceptedCount);
248   int count = 0;
249   return dict->GetInteger(language, &count) ? count : 0;
250 }
251 
IncrementTranslationAcceptedCount(const std::string & language)252 void TranslatePrefs::IncrementTranslationAcceptedCount(
253     const std::string& language) {
254   DictionaryPrefUpdate update(prefs_, kPrefTranslateAcceptedCount);
255   base::DictionaryValue* dict = update.Get();
256   int count = 0;
257   dict->GetInteger(language, &count);
258   dict->SetInteger(language, count + 1);
259 }
260 
ResetTranslationAcceptedCount(const std::string & language)261 void TranslatePrefs::ResetTranslationAcceptedCount(
262     const std::string& language) {
263   DictionaryPrefUpdate update(prefs_, kPrefTranslateAcceptedCount);
264   update.Get()->SetInteger(language, 0);
265 }
266 
UpdateLastDeniedTime()267 void TranslatePrefs::UpdateLastDeniedTime() {
268   if (IsTooOftenDenied())
269     return;
270 
271   double time = prefs_->GetDouble(kPrefTranslateLastDeniedTime);
272   base::Time last_closed_time = base::Time::FromJsTime(time);
273   base::Time now = base::Time::Now();
274   prefs_->SetDouble(kPrefTranslateLastDeniedTime, now.ToJsTime());
275   if (now - last_closed_time <= base::TimeDelta::FromDays(1))
276     prefs_->SetBoolean(kPrefTranslateTooOftenDenied, true);
277 }
278 
IsTooOftenDenied() const279 bool TranslatePrefs::IsTooOftenDenied() const {
280   return prefs_->GetBoolean(kPrefTranslateTooOftenDenied);
281 }
282 
ResetDenialState()283 void TranslatePrefs::ResetDenialState() {
284   prefs_->SetDouble(kPrefTranslateLastDeniedTime, 0);
285   prefs_->SetBoolean(kPrefTranslateTooOftenDenied, false);
286 }
287 
GetLanguageList(std::vector<std::string> * languages)288 void TranslatePrefs::GetLanguageList(std::vector<std::string>* languages) {
289   DCHECK(languages);
290   DCHECK(languages->empty());
291 
292 #if defined(OS_CHROMEOS)
293   const char* key = preferred_languages_pref_.c_str();
294 #else
295   const char* key = accept_languages_pref_.c_str();
296 #endif
297 
298   std::string languages_str = prefs_->GetString(key);
299   base::SplitString(languages_str, ',', languages);
300 }
301 
UpdateLanguageList(const std::vector<std::string> & languages)302 void TranslatePrefs::UpdateLanguageList(
303     const std::vector<std::string>& languages) {
304 #if defined(OS_CHROMEOS)
305   std::string languages_str = JoinString(languages, ',');
306   prefs_->SetString(preferred_languages_pref_.c_str(), languages_str);
307 #endif
308 
309   // Save the same language list as accept languages preference as well, but we
310   // need to expand the language list, to make it more acceptable. For instance,
311   // some web sites don't understand 'en-US' but 'en'. See crosbug.com/9884.
312   std::vector<std::string> accept_languages;
313   ExpandLanguageCodes(languages, &accept_languages);
314   std::string accept_languages_str = JoinString(accept_languages, ',');
315   prefs_->SetString(accept_languages_pref_.c_str(), accept_languages_str);
316 }
317 
CanTranslateLanguage(TranslateAcceptLanguages * accept_languages,const std::string & language)318 bool TranslatePrefs::CanTranslateLanguage(
319     TranslateAcceptLanguages* accept_languages,
320     const std::string& language) {
321   bool can_be_accept_language =
322       TranslateAcceptLanguages::CanBeAcceptLanguage(language);
323   bool is_accept_language = accept_languages->IsAcceptLanguage(language);
324 
325   // Don't translate any user black-listed languages. Checking
326   // |is_accept_language| is necessary because if the user eliminates the
327   // language from the preference, it is natural to forget whether or not
328   // the language should be translated. Checking |cannot_be_accept_language|
329   // is also necessary because some minor languages can't be selected in the
330   // language preference even though the language is available in Translate
331   // server.
332   if (IsBlockedLanguage(language) &&
333       (is_accept_language || !can_be_accept_language))
334     return false;
335 
336   return true;
337 }
338 
ShouldAutoTranslate(const std::string & original_language,std::string * target_language)339 bool TranslatePrefs::ShouldAutoTranslate(const std::string& original_language,
340                                          std::string* target_language) {
341   const base::DictionaryValue* dict =
342       prefs_->GetDictionary(kPrefTranslateWhitelists);
343   if (dict && dict->GetString(original_language, target_language)) {
344     DCHECK(!target_language->empty());
345     return !target_language->empty();
346   }
347   return false;
348 }
349 
350 // static
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)351 void TranslatePrefs::RegisterProfilePrefs(
352     user_prefs::PrefRegistrySyncable* registry) {
353   registry->RegisterListPref(kPrefTranslateLanguageBlacklist,
354                              user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
355   registry->RegisterListPref(kPrefTranslateSiteBlacklist,
356                              user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
357   registry->RegisterDictionaryPref(
358       kPrefTranslateWhitelists,
359       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
360   registry->RegisterDictionaryPref(
361       kPrefTranslateDeniedCount,
362       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
363   registry->RegisterDictionaryPref(
364       kPrefTranslateAcceptedCount,
365       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
366   registry->RegisterListPref(kPrefTranslateBlockedLanguages,
367                              user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
368   registry->RegisterDoublePref(
369       kPrefTranslateLastDeniedTime, 0,
370       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
371   registry->RegisterBooleanPref(
372       kPrefTranslateTooOftenDenied, false,
373       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
374 }
375 
376 // static
MigrateUserPrefs(PrefService * user_prefs,const char * accept_languages_pref)377 void TranslatePrefs::MigrateUserPrefs(PrefService* user_prefs,
378                                       const char* accept_languages_pref) {
379   // Old format of kPrefTranslateWhitelists
380   // - original language -> list of target langs to auto-translate
381   // - list of langs is in order of being enabled i.e. last in list is the
382   //   most recent language that user enabled via
383   //   Always translate |source_lang| to |target_lang|"
384   // - this results in a one-to-n relationship between source lang and target
385   //   langs.
386   // New format:
387   // - original language -> one target language to auto-translate
388   // - each time that the user enables the "Always translate..." option, that
389   //   target lang overwrites the previous one.
390   // - this results in a one-to-one relationship between source lang and target
391   //   lang
392   // - we replace old list of target langs with the last target lang in list,
393   //   assuming the last (i.e. most recent) target lang is what user wants to
394   //   keep auto-translated.
395   DictionaryPrefUpdate update(user_prefs, kPrefTranslateWhitelists);
396   base::DictionaryValue* dict = update.Get();
397   if (dict && !dict->empty()) {
398     base::DictionaryValue::Iterator iter(*dict);
399     while (!iter.IsAtEnd()) {
400       const base::ListValue* list = NULL;
401       if (!iter.value().GetAsList(&list) || !list)
402         break;  // Dictionary has either been migrated or new format.
403       std::string key = iter.key();
404       // Advance the iterator before removing the current element.
405       iter.Advance();
406       std::string target_lang;
407       if (list->empty() ||
408           !list->GetString(list->GetSize() - 1, &target_lang) ||
409           target_lang.empty()) {
410         dict->Remove(key, NULL);
411       } else {
412         dict->SetString(key, target_lang);
413       }
414     }
415   }
416 
417   // Get the union of the blacklist and the Accept languages, and set this to
418   // the new language set 'translate_blocked_languages'. This is used for the
419   // settings UI for Translate and configration to determine which langauage
420   // should be translated instead of the blacklist. The blacklist is no longer
421   // used after launching the settings UI.
422   // After that, Set 'translate_languages_not_translate' to Accept languages to
423   // enable settings for users.
424   bool merged = user_prefs->HasPrefPath(kPrefTranslateBlockedLanguages);
425 
426   if (!merged) {
427     std::vector<std::string> blacklisted_languages;
428     GetBlacklistedLanguages(user_prefs, &blacklisted_languages);
429 
430     std::string accept_languages_str =
431         user_prefs->GetString(accept_languages_pref);
432     std::vector<std::string> accept_languages;
433     base::SplitString(accept_languages_str, ',', &accept_languages);
434 
435     std::vector<std::string> blocked_languages;
436     CreateBlockedLanguages(
437         &blocked_languages, blacklisted_languages, accept_languages);
438 
439     // Create the new preference kPrefTranslateBlockedLanguages.
440     {
441       base::ListValue blocked_languages_list;
442       for (std::vector<std::string>::const_iterator it =
443                blocked_languages.begin();
444            it != blocked_languages.end(); ++it) {
445         blocked_languages_list.Append(new base::StringValue(*it));
446       }
447       ListPrefUpdate update(user_prefs, kPrefTranslateBlockedLanguages);
448       base::ListValue* list = update.Get();
449       DCHECK(list != NULL);
450       list->Swap(&blocked_languages_list);
451     }
452 
453     // Update kAcceptLanguages
454     for (std::vector<std::string>::const_iterator it =
455              blocked_languages.begin();
456          it != blocked_languages.end(); ++it) {
457       std::string lang = *it;
458       translate::ToChromeLanguageSynonym(&lang);
459       bool not_found =
460           std::find(accept_languages.begin(), accept_languages.end(), lang) ==
461           accept_languages.end();
462       if (not_found)
463         accept_languages.push_back(lang);
464     }
465 
466     std::string new_accept_languages_str = JoinString(accept_languages, ",");
467     user_prefs->SetString(accept_languages_pref, new_accept_languages_str);
468   }
469 }
470 
471 // static
CreateBlockedLanguages(std::vector<std::string> * blocked_languages,const std::vector<std::string> & blacklisted_languages,const std::vector<std::string> & accept_languages)472 void TranslatePrefs::CreateBlockedLanguages(
473     std::vector<std::string>* blocked_languages,
474     const std::vector<std::string>& blacklisted_languages,
475     const std::vector<std::string>& accept_languages) {
476   DCHECK(blocked_languages);
477   DCHECK(blocked_languages->empty());
478 
479   std::set<std::string> result;
480 
481   for (std::vector<std::string>::const_iterator it =
482            blacklisted_languages.begin();
483        it != blacklisted_languages.end(); ++it) {
484     result.insert(*it);
485   }
486 
487   const std::string& app_locale =
488       TranslateDownloadManager::GetInstance()->application_locale();
489   std::string ui_lang = TranslateDownloadManager::GetLanguageCode(app_locale);
490   bool is_ui_english = ui_lang == "en" ||
491       StartsWithASCII(ui_lang, "en-", false);
492 
493   for (std::vector<std::string>::const_iterator it = accept_languages.begin();
494        it != accept_languages.end(); ++it) {
495     std::string converted_lang = ConvertLangCodeForTranslation(*it);
496 
497     // Regarding http://crbug.com/36182, even though English exists in Accept
498     // language list, English could be translated on non-English locale.
499     if (converted_lang == "en" && !is_ui_english)
500       continue;
501 
502     result.insert(converted_lang);
503   }
504 
505   blocked_languages->insert(
506       blocked_languages->begin(), result.begin(), result.end());
507 }
508 
509 // static
ConvertLangCodeForTranslation(const std::string & lang)510 std::string TranslatePrefs::ConvertLangCodeForTranslation(
511     const std::string& lang) {
512   std::vector<std::string> tokens;
513   base::SplitString(lang, '-', &tokens);
514   if (tokens.size() < 1)
515     return lang;
516 
517   std::string main_part = tokens[0];
518 
519   // Translate doesn't support General Chinese and the sub code is necessary.
520   if (main_part == "zh")
521     return lang;
522 
523   translate::ToTranslateLanguageSynonym(&main_part);
524   return main_part;
525 }
526 
IsValueInList(const base::ListValue * list,const std::string & in_value) const527 bool TranslatePrefs::IsValueInList(const base::ListValue* list,
528                                    const std::string& in_value) const {
529   for (size_t i = 0; i < list->GetSize(); ++i) {
530     std::string value;
531     if (list->GetString(i, &value) && value == in_value)
532       return true;
533   }
534   return false;
535 }
536 
IsValueBlacklisted(const char * pref_id,const std::string & value) const537 bool TranslatePrefs::IsValueBlacklisted(const char* pref_id,
538                                         const std::string& value) const {
539   const base::ListValue* blacklist = prefs_->GetList(pref_id);
540   return (blacklist && !blacklist->empty() && IsValueInList(blacklist, value));
541 }
542 
BlacklistValue(const char * pref_id,const std::string & value)543 void TranslatePrefs::BlacklistValue(const char* pref_id,
544                                     const std::string& value) {
545   {
546     ListPrefUpdate update(prefs_, pref_id);
547     base::ListValue* blacklist = update.Get();
548     if (!blacklist) {
549       NOTREACHED() << "Unregistered translate blacklist pref";
550       return;
551     }
552     blacklist->Append(new base::StringValue(value));
553   }
554 }
555 
RemoveValueFromBlacklist(const char * pref_id,const std::string & value)556 void TranslatePrefs::RemoveValueFromBlacklist(const char* pref_id,
557                                               const std::string& value) {
558   ListPrefUpdate update(prefs_, pref_id);
559   base::ListValue* blacklist = update.Get();
560   if (!blacklist) {
561     NOTREACHED() << "Unregistered translate blacklist pref";
562     return;
563   }
564   base::StringValue string_value(value);
565   blacklist->Remove(string_value, NULL);
566 }
567 
IsListEmpty(const char * pref_id) const568 bool TranslatePrefs::IsListEmpty(const char* pref_id) const {
569   const base::ListValue* blacklist = prefs_->GetList(pref_id);
570   return (blacklist == NULL || blacklist->empty());
571 }
572 
IsDictionaryEmpty(const char * pref_id) const573 bool TranslatePrefs::IsDictionaryEmpty(const char* pref_id) const {
574   const base::DictionaryValue* dict = prefs_->GetDictionary(pref_id);
575   return (dict == NULL || dict->empty());
576 }
577 
578 }  // namespace translate
579