Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / translate / translate_infobar_delegate.cc
blobfeb8ca9f0dc80ae6053cf448a39a65c4ce8ea298
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/translate/translate_infobar_delegate.h"
7 #include <algorithm>
9 #include "base/i18n/string_compare.h"
10 #include "base/metrics/histogram.h"
11 #include "base/prefs/pref_service.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/infobars/infobar_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/translate/translate_tab_helper.h"
16 #include "components/infobars/core/infobar.h"
17 #include "components/translate/core/browser/translate_accept_languages.h"
18 #include "components/translate/core/browser/translate_download_manager.h"
19 #include "components/translate/core/browser/translate_manager.h"
20 #include "components/translate/core/common/translate_constants.h"
21 #include "content/public/browser/navigation_entry.h"
22 #include "content/public/browser/web_contents.h"
23 #include "grit/generated_resources.h"
24 #include "grit/theme_resources.h"
25 #include "third_party/icu/source/i18n/unicode/coll.h"
26 #include "ui/base/l10n/l10n_util.h"
28 namespace {
30 // Counts used to decide whether infobars should be shown.
31 // Android and iOS implementations do not offer a drop down (for space reasons),
32 // so we are more aggressive about showing the shortcut to never translate.
33 // The "Always Translate" option is always shown on iOS and Android.
34 #if defined(OS_ANDROID)
35 const int kAlwaysTranslateMinCount = 1;
36 const int kNeverTranslateMinCount = 1;
37 #elif defined(OS_IOS)
38 // The iOS implementation, like the Android implementation, shows the "Never
39 // translate" infobar after two denials. There is an offset of one because on
40 // Android the last event is not counted.
41 const int kAlwaysTranslateMinCount = 1;
42 const int kNeverTranslateMinCount = 2;
43 #else
44 const int kAlwaysTranslateMinCount = 3;
45 const int kNeverTranslateMinCount = 3;
46 #endif
48 } // namespace
50 const size_t TranslateInfoBarDelegate::kNoIndex = TranslateUIDelegate::NO_INDEX;
52 TranslateInfoBarDelegate::~TranslateInfoBarDelegate() {
55 // static
56 void TranslateInfoBarDelegate::Create(bool replace_existing_infobar,
57 content::WebContents* web_contents,
58 translate::TranslateStep step,
59 const std::string& original_language,
60 const std::string& target_language,
61 TranslateErrors::Type error_type,
62 PrefService* prefs,
63 bool triggered_from_menu) {
64 // Check preconditions.
65 if (step != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
66 DCHECK(TranslateDownloadManager::IsSupportedLanguage(target_language));
67 if (!TranslateDownloadManager::IsSupportedLanguage(original_language)) {
68 // The original language can only be "unknown" for the "translating"
69 // infobar, which is the case when the user started a translation from the
70 // context menu.
71 DCHECK(step == translate::TRANSLATE_STEP_TRANSLATING ||
72 step == translate::TRANSLATE_STEP_AFTER_TRANSLATE);
73 DCHECK_EQ(translate::kUnknownLanguageCode, original_language);
77 // Do not create the after translate infobar if we are auto translating.
78 if ((step == translate::TRANSLATE_STEP_AFTER_TRANSLATE) ||
79 (step == translate::TRANSLATE_STEP_TRANSLATING)) {
80 TranslateTabHelper* translate_tab_helper =
81 TranslateTabHelper::FromWebContents(web_contents);
82 if (!translate_tab_helper ||
83 translate_tab_helper->GetLanguageState().InTranslateNavigation())
84 return;
87 // Find any existing translate infobar delegate.
88 infobars::InfoBar* old_infobar = NULL;
89 InfoBarService* infobar_service =
90 InfoBarService::FromWebContents(web_contents);
91 TranslateInfoBarDelegate* old_delegate = NULL;
92 for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
93 old_infobar = infobar_service->infobar_at(i);
94 old_delegate = old_infobar->delegate()->AsTranslateInfoBarDelegate();
95 if (old_delegate) {
96 if (!replace_existing_infobar)
97 return;
98 break;
102 // Add the new delegate.
103 scoped_ptr<infobars::InfoBar> infobar(CreateInfoBar(
104 scoped_ptr<TranslateInfoBarDelegate>(new TranslateInfoBarDelegate(
105 web_contents, step, old_delegate, original_language,
106 target_language, error_type, prefs,
107 triggered_from_menu))));
108 if (old_delegate)
109 infobar_service->ReplaceInfoBar(old_infobar, infobar.Pass());
110 else
111 infobar_service->AddInfoBar(infobar.Pass());
115 void TranslateInfoBarDelegate::UpdateOriginalLanguageIndex(
116 size_t language_index) {
117 ui_delegate_.UpdateOriginalLanguageIndex(language_index);
120 void TranslateInfoBarDelegate::UpdateTargetLanguageIndex(
121 size_t language_index) {
122 ui_delegate_.UpdateTargetLanguageIndex(language_index);
125 void TranslateInfoBarDelegate::Translate() {
126 ui_delegate_.Translate();
129 void TranslateInfoBarDelegate::RevertTranslation() {
130 ui_delegate_.RevertTranslation();
131 infobar()->RemoveSelf();
134 void TranslateInfoBarDelegate::ReportLanguageDetectionError() {
135 TranslateManager* manager =
136 TranslateTabHelper::GetManagerFromWebContents(GetWebContents());
137 if (!manager)
138 return;
139 manager->ReportLanguageDetectionError();
142 void TranslateInfoBarDelegate::TranslationDeclined() {
143 ui_delegate_.TranslationDeclined(false);
146 bool TranslateInfoBarDelegate::IsTranslatableLanguageByPrefs() {
147 Profile* profile =
148 Profile::FromBrowserContext(GetWebContents()->GetBrowserContext());
149 Profile* original_profile = profile->GetOriginalProfile();
150 scoped_ptr<TranslatePrefs> translate_prefs(
151 TranslateTabHelper::CreateTranslatePrefs(original_profile->GetPrefs()));
152 TranslateAcceptLanguages* accept_languages =
153 TranslateTabHelper::GetTranslateAcceptLanguages(original_profile);
154 return translate_prefs->CanTranslateLanguage(accept_languages,
155 original_language_code());
158 void TranslateInfoBarDelegate::ToggleTranslatableLanguageByPrefs() {
159 if (ui_delegate_.IsLanguageBlocked()) {
160 ui_delegate_.SetLanguageBlocked(false);
161 } else {
162 ui_delegate_.SetLanguageBlocked(true);
163 infobar()->RemoveSelf();
167 bool TranslateInfoBarDelegate::IsSiteBlacklisted() {
168 return ui_delegate_.IsSiteBlacklisted();
171 void TranslateInfoBarDelegate::ToggleSiteBlacklist() {
172 if (ui_delegate_.IsSiteBlacklisted()) {
173 ui_delegate_.SetSiteBlacklist(false);
174 } else {
175 ui_delegate_.SetSiteBlacklist(true);
176 infobar()->RemoveSelf();
180 bool TranslateInfoBarDelegate::ShouldAlwaysTranslate() {
181 return ui_delegate_.ShouldAlwaysTranslate();
184 void TranslateInfoBarDelegate::ToggleAlwaysTranslate() {
185 ui_delegate_.SetAlwaysTranslate(!ui_delegate_.ShouldAlwaysTranslate());
188 void TranslateInfoBarDelegate::AlwaysTranslatePageLanguage() {
189 DCHECK(!ui_delegate_.ShouldAlwaysTranslate());
190 ui_delegate_.SetAlwaysTranslate(true);
191 Translate();
194 void TranslateInfoBarDelegate::NeverTranslatePageLanguage() {
195 DCHECK(!ui_delegate_.IsLanguageBlocked());
196 ui_delegate_.SetLanguageBlocked(true);
197 infobar()->RemoveSelf();
200 base::string16 TranslateInfoBarDelegate::GetMessageInfoBarText() {
201 if (step_ == translate::TRANSLATE_STEP_TRANSLATING) {
202 base::string16 target_language_name =
203 language_name_at(target_language_index());
204 return l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_TRANSLATING_TO,
205 target_language_name);
208 DCHECK_EQ(translate::TRANSLATE_STEP_TRANSLATE_ERROR, step_);
209 UMA_HISTOGRAM_ENUMERATION("Translate.ShowErrorInfobar",
210 error_type_,
211 TranslateErrors::TRANSLATE_ERROR_MAX);
212 ui_delegate_.OnErrorShown(error_type_);
213 switch (error_type_) {
214 case TranslateErrors::NETWORK:
215 return l10n_util::GetStringUTF16(
216 IDS_TRANSLATE_INFOBAR_ERROR_CANT_CONNECT);
217 case TranslateErrors::INITIALIZATION_ERROR:
218 case TranslateErrors::TRANSLATION_ERROR:
219 return l10n_util::GetStringUTF16(
220 IDS_TRANSLATE_INFOBAR_ERROR_CANT_TRANSLATE);
221 case TranslateErrors::UNKNOWN_LANGUAGE:
222 return l10n_util::GetStringUTF16(
223 IDS_TRANSLATE_INFOBAR_UNKNOWN_PAGE_LANGUAGE);
224 case TranslateErrors::UNSUPPORTED_LANGUAGE:
225 return l10n_util::GetStringFUTF16(
226 IDS_TRANSLATE_INFOBAR_UNSUPPORTED_PAGE_LANGUAGE,
227 language_name_at(target_language_index()));
228 case TranslateErrors::IDENTICAL_LANGUAGES:
229 return l10n_util::GetStringFUTF16(
230 IDS_TRANSLATE_INFOBAR_ERROR_SAME_LANGUAGE,
231 language_name_at(target_language_index()));
232 default:
233 NOTREACHED();
234 return base::string16();
238 base::string16 TranslateInfoBarDelegate::GetMessageInfoBarButtonText() {
239 if (step_ != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
240 DCHECK_EQ(translate::TRANSLATE_STEP_TRANSLATING, step_);
241 } else if ((error_type_ != TranslateErrors::IDENTICAL_LANGUAGES) &&
242 (error_type_ != TranslateErrors::UNKNOWN_LANGUAGE)) {
243 return l10n_util::GetStringUTF16(
244 (error_type_ == TranslateErrors::UNSUPPORTED_LANGUAGE) ?
245 IDS_TRANSLATE_INFOBAR_REVERT : IDS_TRANSLATE_INFOBAR_RETRY);
247 return base::string16();
250 void TranslateInfoBarDelegate::MessageInfoBarButtonPressed() {
251 DCHECK_EQ(translate::TRANSLATE_STEP_TRANSLATE_ERROR, step_);
252 if (error_type_ == TranslateErrors::UNSUPPORTED_LANGUAGE) {
253 RevertTranslation();
254 return;
256 // This is the "Try again..." case.
257 TranslateManager* manager =
258 TranslateTabHelper::GetManagerFromWebContents(GetWebContents());
259 DCHECK(manager);
260 manager->TranslatePage(
261 original_language_code(), target_language_code(), false);
264 bool TranslateInfoBarDelegate::ShouldShowMessageInfoBarButton() {
265 return !GetMessageInfoBarButtonText().empty();
268 bool TranslateInfoBarDelegate::ShouldShowNeverTranslateShortcut() {
269 DCHECK_EQ(translate::TRANSLATE_STEP_BEFORE_TRANSLATE, step_);
270 return !GetWebContents()->GetBrowserContext()->IsOffTheRecord() &&
271 (prefs_->GetTranslationDeniedCount(original_language_code()) >=
272 kNeverTranslateMinCount);
275 bool TranslateInfoBarDelegate::ShouldShowAlwaysTranslateShortcut() {
276 DCHECK_EQ(translate::TRANSLATE_STEP_BEFORE_TRANSLATE, step_);
277 return !GetWebContents()->GetBrowserContext()->IsOffTheRecord() &&
278 (prefs_->GetTranslationAcceptedCount(original_language_code()) >=
279 kAlwaysTranslateMinCount);
282 content::WebContents* TranslateInfoBarDelegate::GetWebContents() {
283 return InfoBarService::WebContentsFromInfoBar(infobar());
286 // static
287 base::string16 TranslateInfoBarDelegate::GetLanguageDisplayableName(
288 const std::string& language_code) {
289 return l10n_util::GetDisplayNameForLocale(
290 language_code, g_browser_process->GetApplicationLocale(), true);
293 // static
294 void TranslateInfoBarDelegate::GetAfterTranslateStrings(
295 std::vector<base::string16>* strings,
296 bool* swap_languages,
297 bool autodetermined_source_language) {
298 DCHECK(strings);
300 if (autodetermined_source_language) {
301 size_t offset;
302 base::string16 text = l10n_util::GetStringFUTF16(
303 IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_AUTODETERMINED_SOURCE_LANGUAGE,
304 base::string16(),
305 &offset);
307 strings->push_back(text.substr(0, offset));
308 strings->push_back(text.substr(offset));
309 return;
311 DCHECK(swap_languages);
313 std::vector<size_t> offsets;
314 base::string16 text = l10n_util::GetStringFUTF16(
315 IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE, base::string16(), base::string16(),
316 &offsets);
317 DCHECK_EQ(2U, offsets.size());
319 *swap_languages = (offsets[0] > offsets[1]);
320 if (*swap_languages)
321 std::swap(offsets[0], offsets[1]);
323 strings->push_back(text.substr(0, offsets[0]));
324 strings->push_back(text.substr(offsets[0], offsets[1] - offsets[0]));
325 strings->push_back(text.substr(offsets[1]));
328 TranslateInfoBarDelegate::TranslateInfoBarDelegate(
329 content::WebContents* web_contents,
330 translate::TranslateStep step,
331 TranslateInfoBarDelegate* old_delegate,
332 const std::string& original_language,
333 const std::string& target_language,
334 TranslateErrors::Type error_type,
335 PrefService* prefs,
336 bool triggered_from_menu)
337 : infobars::InfoBarDelegate(),
338 step_(step),
339 background_animation_(NONE),
340 ui_delegate_(TranslateTabHelper::FromWebContents(web_contents),
341 TranslateTabHelper::GetManagerFromWebContents(web_contents),
342 original_language,
343 target_language),
344 error_type_(error_type),
345 prefs_(TranslateTabHelper::CreateTranslatePrefs(prefs)),
346 triggered_from_menu_(triggered_from_menu) {
347 DCHECK_NE((step_ == translate::TRANSLATE_STEP_TRANSLATE_ERROR),
348 (error_type_ == TranslateErrors::NONE));
350 if (old_delegate && (old_delegate->is_error() != is_error()))
351 background_animation_ = is_error() ? NORMAL_TO_ERROR : ERROR_TO_NORMAL;
354 // TranslateInfoBarDelegate::CreateInfoBar() is implemented in platform-specific
355 // files.
357 void TranslateInfoBarDelegate::InfoBarDismissed() {
358 if (step_ != translate::TRANSLATE_STEP_BEFORE_TRANSLATE)
359 return;
361 // The user closed the infobar without clicking the translate button.
362 TranslationDeclined();
363 UMA_HISTOGRAM_BOOLEAN("Translate.DeclineTranslateCloseInfobar", true);
366 int TranslateInfoBarDelegate::GetIconID() const {
367 return IDR_INFOBAR_TRANSLATE;
370 infobars::InfoBarDelegate::Type TranslateInfoBarDelegate::GetInfoBarType()
371 const {
372 return PAGE_ACTION_TYPE;
375 bool TranslateInfoBarDelegate::ShouldExpire(
376 const NavigationDetails& details) const {
377 // Note: we allow closing this infobar even if the main frame navigation
378 // was programmatic and not initiated by the user - crbug.com/70261 .
379 if (!details.is_navigation_to_different_page && !details.is_main_frame)
380 return false;
382 return infobars::InfoBarDelegate::ShouldExpireInternal(details);
385 TranslateInfoBarDelegate*
386 TranslateInfoBarDelegate::AsTranslateInfoBarDelegate() {
387 return this;