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_ui_delegate.h"
6
7 #include "base/i18n/string_compare.h"
8 #include "base/metrics/histogram.h"
9 #include "components/translate/core/browser/language_state.h"
10 #include "components/translate/core/browser/translate_client.h"
11 #include "components/translate/core/browser/translate_download_manager.h"
12 #include "components/translate/core/browser/translate_driver.h"
13 #include "components/translate/core/browser/translate_manager.h"
14 #include "components/translate/core/browser/translate_prefs.h"
15 #include "components/translate/core/common/translate_constants.h"
16 #include "third_party/icu/source/i18n/unicode/coll.h"
17 #include "ui/base/l10n/l10n_util.h"
18
19 namespace {
20
21 const char kDeclineTranslate[] = "Translate.DeclineTranslate";
22 const char kRevertTranslation[] = "Translate.RevertTranslation";
23 const char kPerformTranslate[] = "Translate.Translate";
24 const char kNeverTranslateLang[] = "Translate.NeverTranslateLang";
25 const char kNeverTranslateSite[] = "Translate.NeverTranslateSite";
26 const char kAlwaysTranslateLang[] = "Translate.AlwaysTranslateLang";
27 const char kModifyOriginalLang[] = "Translate.ModifyOriginalLang";
28 const char kModifyTargetLang[] = "Translate.ModifyTargetLang";
29 const char kDeclineTranslateDismissUI[] = "Translate.DeclineTranslateDismissUI";
30 const char kShowErrorUI[] = "Translate.ShowErrorUI";
31
32 } // namespace
33
TranslateUIDelegate(const base::WeakPtr<TranslateManager> & translate_manager,const std::string & original_language,const std::string & target_language)34 TranslateUIDelegate::TranslateUIDelegate(
35 const base::WeakPtr<TranslateManager>& translate_manager,
36 const std::string& original_language,
37 const std::string& target_language)
38 : translate_driver_(
39 translate_manager->translate_client()->GetTranslateDriver()),
40 translate_manager_(translate_manager),
41 original_language_index_(NO_INDEX),
42 initial_original_language_index_(NO_INDEX),
43 target_language_index_(NO_INDEX) {
44 DCHECK(translate_driver_);
45 DCHECK(translate_manager_);
46
47 std::vector<std::string> language_codes;
48 TranslateDownloadManager::GetSupportedLanguages(&language_codes);
49
50 // Preparing for the alphabetical order in the locale.
51 UErrorCode error = U_ZERO_ERROR;
52 std::string locale =
53 TranslateDownloadManager::GetInstance()->application_locale();
54 icu::Locale loc(locale.c_str());
55 scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(loc, error));
56 collator->setStrength(icu::Collator::PRIMARY);
57
58 languages_.reserve(language_codes.size());
59 for (std::vector<std::string>::const_iterator iter = language_codes.begin();
60 iter != language_codes.end();
61 ++iter) {
62 std::string language_code = *iter;
63
64 base::string16 language_name =
65 l10n_util::GetDisplayNameForLocale(language_code, locale, true);
66 // Insert the language in languages_ in alphabetical order.
67 std::vector<LanguageNamePair>::iterator iter2;
68 for (iter2 = languages_.begin(); iter2 != languages_.end(); ++iter2) {
69 if (base::i18n::CompareString16WithCollator(
70 collator.get(), language_name, iter2->second) == UCOL_LESS) {
71 break;
72 }
73 }
74 languages_.insert(iter2, LanguageNamePair(language_code, language_name));
75 }
76 for (std::vector<LanguageNamePair>::const_iterator iter = languages_.begin();
77 iter != languages_.end();
78 ++iter) {
79 std::string language_code = iter->first;
80 if (language_code == original_language) {
81 original_language_index_ = iter - languages_.begin();
82 initial_original_language_index_ = original_language_index_;
83 }
84 if (language_code == target_language)
85 target_language_index_ = iter - languages_.begin();
86 }
87
88 prefs_ = translate_manager_->translate_client()->GetTranslatePrefs();
89 }
90
~TranslateUIDelegate()91 TranslateUIDelegate::~TranslateUIDelegate() {}
92
OnErrorShown(TranslateErrors::Type error_type)93 void TranslateUIDelegate::OnErrorShown(TranslateErrors::Type error_type) {
94 DCHECK_LE(TranslateErrors::NONE, error_type);
95 DCHECK_LT(error_type, TranslateErrors::TRANSLATE_ERROR_MAX);
96
97 if (error_type == TranslateErrors::NONE)
98 return;
99
100 UMA_HISTOGRAM_ENUMERATION(
101 kShowErrorUI, error_type, TranslateErrors::TRANSLATE_ERROR_MAX);
102 }
103
GetLanguageState()104 const LanguageState& TranslateUIDelegate::GetLanguageState() {
105 return translate_manager_->GetLanguageState();
106 }
107
GetNumberOfLanguages() const108 size_t TranslateUIDelegate::GetNumberOfLanguages() const {
109 return languages_.size();
110 }
111
GetOriginalLanguageIndex() const112 size_t TranslateUIDelegate::GetOriginalLanguageIndex() const {
113 return original_language_index_;
114 }
115
UpdateOriginalLanguageIndex(size_t language_index)116 void TranslateUIDelegate::UpdateOriginalLanguageIndex(size_t language_index) {
117 if (original_language_index_ == language_index)
118 return;
119
120 UMA_HISTOGRAM_BOOLEAN(kModifyOriginalLang, true);
121 original_language_index_ = language_index;
122 }
123
GetTargetLanguageIndex() const124 size_t TranslateUIDelegate::GetTargetLanguageIndex() const {
125 return target_language_index_;
126 }
127
UpdateTargetLanguageIndex(size_t language_index)128 void TranslateUIDelegate::UpdateTargetLanguageIndex(size_t language_index) {
129 if (target_language_index_ == language_index)
130 return;
131
132 DCHECK_LT(language_index, GetNumberOfLanguages());
133 UMA_HISTOGRAM_BOOLEAN(kModifyTargetLang, true);
134 target_language_index_ = language_index;
135 }
136
GetLanguageCodeAt(size_t index) const137 std::string TranslateUIDelegate::GetLanguageCodeAt(size_t index) const {
138 DCHECK_LT(index, GetNumberOfLanguages());
139 return languages_[index].first;
140 }
141
GetLanguageNameAt(size_t index) const142 base::string16 TranslateUIDelegate::GetLanguageNameAt(size_t index) const {
143 if (index == static_cast<size_t>(NO_INDEX))
144 return base::string16();
145 DCHECK_LT(index, GetNumberOfLanguages());
146 return languages_[index].second;
147 }
148
GetOriginalLanguageCode() const149 std::string TranslateUIDelegate::GetOriginalLanguageCode() const {
150 return (GetOriginalLanguageIndex() == static_cast<size_t>(NO_INDEX))
151 ? translate::kUnknownLanguageCode
152 : GetLanguageCodeAt(GetOriginalLanguageIndex());
153 }
154
GetTargetLanguageCode() const155 std::string TranslateUIDelegate::GetTargetLanguageCode() const {
156 return GetLanguageCodeAt(GetTargetLanguageIndex());
157 }
158
Translate()159 void TranslateUIDelegate::Translate() {
160 if (!translate_driver_->IsOffTheRecord()) {
161 prefs_->ResetTranslationDeniedCount(GetOriginalLanguageCode());
162 prefs_->IncrementTranslationAcceptedCount(GetOriginalLanguageCode());
163 }
164
165 if (translate_manager_) {
166 translate_manager_->TranslatePage(
167 GetOriginalLanguageCode(), GetTargetLanguageCode(), false);
168 UMA_HISTOGRAM_BOOLEAN(kPerformTranslate, true);
169 }
170 }
171
RevertTranslation()172 void TranslateUIDelegate::RevertTranslation() {
173 if (translate_manager_) {
174 translate_manager_->RevertTranslation();
175 UMA_HISTOGRAM_BOOLEAN(kRevertTranslation, true);
176 }
177 }
178
TranslationDeclined(bool explicitly_closed)179 void TranslateUIDelegate::TranslationDeclined(bool explicitly_closed) {
180 if (!translate_driver_->IsOffTheRecord()) {
181 prefs_->ResetTranslationAcceptedCount(GetOriginalLanguageCode());
182 prefs_->IncrementTranslationDeniedCount(GetOriginalLanguageCode());
183 }
184
185 // Remember that the user declined the translation so as to prevent showing a
186 // translate infobar for that page again. (TranslateManager initiates
187 // translations when getting a LANGUAGE_DETERMINED from the page, which
188 // happens when a load stops. That could happen multiple times, including
189 // after the user already declined the translation.)
190 if (translate_manager_) {
191 translate_manager_->GetLanguageState().set_translation_declined(true);
192 UMA_HISTOGRAM_BOOLEAN(kDeclineTranslate, true);
193 }
194
195 if (!explicitly_closed)
196 UMA_HISTOGRAM_BOOLEAN(kDeclineTranslateDismissUI, true);
197 }
198
IsLanguageBlocked()199 bool TranslateUIDelegate::IsLanguageBlocked() {
200 return prefs_->IsBlockedLanguage(GetOriginalLanguageCode());
201 }
202
SetLanguageBlocked(bool value)203 void TranslateUIDelegate::SetLanguageBlocked(bool value) {
204 if (value) {
205 prefs_->BlockLanguage(GetOriginalLanguageCode());
206 if (translate_manager_) {
207 translate_manager_->GetLanguageState().SetTranslateEnabled(false);
208 }
209 } else {
210 prefs_->UnblockLanguage(GetOriginalLanguageCode());
211 }
212
213 UMA_HISTOGRAM_BOOLEAN(kNeverTranslateLang, true);
214 }
215
IsSiteBlacklisted()216 bool TranslateUIDelegate::IsSiteBlacklisted() {
217 std::string host = GetPageHost();
218 return !host.empty() && prefs_->IsSiteBlacklisted(host);
219 }
220
SetSiteBlacklist(bool value)221 void TranslateUIDelegate::SetSiteBlacklist(bool value) {
222 std::string host = GetPageHost();
223 if (host.empty())
224 return;
225
226 if (value) {
227 prefs_->BlacklistSite(host);
228 if (translate_manager_) {
229 translate_manager_->GetLanguageState().SetTranslateEnabled(false);
230 }
231 } else {
232 prefs_->RemoveSiteFromBlacklist(host);
233 }
234
235 UMA_HISTOGRAM_BOOLEAN(kNeverTranslateSite, true);
236 }
237
ShouldAlwaysTranslate()238 bool TranslateUIDelegate::ShouldAlwaysTranslate() {
239 return prefs_->IsLanguagePairWhitelisted(GetOriginalLanguageCode(),
240 GetTargetLanguageCode());
241 }
242
SetAlwaysTranslate(bool value)243 void TranslateUIDelegate::SetAlwaysTranslate(bool value) {
244 const std::string& original_lang = GetOriginalLanguageCode();
245 const std::string& target_lang = GetTargetLanguageCode();
246 if (value)
247 prefs_->WhitelistLanguagePair(original_lang, target_lang);
248 else
249 prefs_->RemoveLanguagePairFromWhitelist(original_lang, target_lang);
250
251 UMA_HISTOGRAM_BOOLEAN(kAlwaysTranslateLang, true);
252 }
253
GetPageHost()254 std::string TranslateUIDelegate::GetPageHost() {
255 if (!translate_driver_->HasCurrentPage())
256 return std::string();
257 return translate_driver_->GetActiveURL().HostNoBrackets();
258 }
259