NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / translate / translate_infobar_delegate.cc
bloba2b8254571155f4e1148f26040180b65239e1b78
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.h"
14 #include "chrome/browser/infobars/infobar_service.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/translate/translate_manager.h"
17 #include "chrome/browser/translate/translate_tab_helper.h"
18 #include "components/translate/core/browser/translate_accept_languages.h"
19 #include "components/translate/core/browser/translate_download_manager.h"
20 #include "components/translate/core/common/translate_constants.h"
21 #include "content/public/browser/navigation_details.h"
22 #include "content/public/browser/navigation_entry.h"
23 #include "content/public/browser/web_contents.h"
24 #include "grit/generated_resources.h"
25 #include "grit/theme_resources.h"
26 #include "third_party/icu/source/i18n/unicode/coll.h"
27 #include "ui/base/l10n/l10n_util.h"
29 namespace {
31 // Counts used to decide whether infobars should be shown.
32 // Android and iOS implementations do not offer a drop down (for space reasons),
33 // so we are more aggressive about showing the shortcut to never translate.
34 // The "Always Translate" option is always shown on iOS and Android.
35 #if defined(OS_ANDROID)
36 const int kAlwaysTranslateMinCount = 1;
37 const int kNeverTranslateMinCount = 1;
38 #elif defined(OS_IOS)
39 // The iOS implementation, like the Android implementation, shows the "Never
40 // translate" infobar after two denials. There is an offset of one because on
41 // Android the last event is not counted.
42 const int kAlwaysTranslateMinCount = 1;
43 const int kNeverTranslateMinCount = 2;
44 #else
45 const int kAlwaysTranslateMinCount = 3;
46 const int kNeverTranslateMinCount = 3;
47 #endif
49 } // namespace
51 const size_t TranslateInfoBarDelegate::kNoIndex = TranslateUIDelegate::NO_INDEX;
53 TranslateInfoBarDelegate::~TranslateInfoBarDelegate() {
56 // static
57 void TranslateInfoBarDelegate::Create(bool replace_existing_infobar,
58 content::WebContents* web_contents,
59 TranslateTabHelper::TranslateStep step,
60 const std::string& original_language,
61 const std::string& target_language,
62 TranslateErrors::Type error_type,
63 PrefService* prefs) {
64 // Check preconditions.
65 if (step != TranslateTabHelper::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 == TranslateTabHelper::TRANSLATING ||
72 step == TranslateTabHelper::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 == TranslateTabHelper::AFTER_TRANSLATE) ||
79 (step == TranslateTabHelper::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 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<InfoBar> infobar(CreateInfoBar(
104 scoped_ptr<TranslateInfoBarDelegate>(new TranslateInfoBarDelegate(
105 web_contents, step, old_delegate, original_language,
106 target_language, error_type, prefs))));
107 if (old_delegate)
108 infobar_service->ReplaceInfoBar(old_infobar, infobar.Pass());
109 else
110 infobar_service->AddInfoBar(infobar.Pass());
114 void TranslateInfoBarDelegate::UpdateOriginalLanguageIndex(
115 size_t language_index) {
116 ui_delegate_.UpdateOriginalLanguageIndex(language_index);
119 void TranslateInfoBarDelegate::UpdateTargetLanguageIndex(
120 size_t language_index) {
121 ui_delegate_.UpdateTargetLanguageIndex(language_index);
124 void TranslateInfoBarDelegate::Translate() {
125 ui_delegate_.Translate();
128 void TranslateInfoBarDelegate::RevertTranslation() {
129 ui_delegate_.RevertTranslation();
130 infobar()->RemoveSelf();
133 void TranslateInfoBarDelegate::ReportLanguageDetectionError() {
134 TranslateManager::GetInstance()->ReportLanguageDetectionError(
135 web_contents());
138 void TranslateInfoBarDelegate::TranslationDeclined() {
139 ui_delegate_.TranslationDeclined(false);
142 bool TranslateInfoBarDelegate::IsTranslatableLanguageByPrefs() {
143 Profile* profile =
144 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
145 Profile* original_profile = profile->GetOriginalProfile();
146 scoped_ptr<TranslatePrefs> translate_prefs(
147 TranslateTabHelper::CreateTranslatePrefs(original_profile->GetPrefs()));
148 TranslateAcceptLanguages* accept_languages =
149 TranslateTabHelper::GetTranslateAcceptLanguages(original_profile);
150 return translate_prefs->CanTranslateLanguage(accept_languages,
151 original_language_code());
154 void TranslateInfoBarDelegate::ToggleTranslatableLanguageByPrefs() {
155 if (ui_delegate_.IsLanguageBlocked()) {
156 ui_delegate_.SetLanguageBlocked(false);
157 } else {
158 ui_delegate_.SetLanguageBlocked(true);
159 infobar()->RemoveSelf();
163 bool TranslateInfoBarDelegate::IsSiteBlacklisted() {
164 return ui_delegate_.IsSiteBlacklisted();
167 void TranslateInfoBarDelegate::ToggleSiteBlacklist() {
168 if (ui_delegate_.IsSiteBlacklisted()) {
169 ui_delegate_.SetSiteBlacklist(false);
170 } else {
171 ui_delegate_.SetSiteBlacklist(true);
172 infobar()->RemoveSelf();
176 bool TranslateInfoBarDelegate::ShouldAlwaysTranslate() {
177 return ui_delegate_.ShouldAlwaysTranslate();
180 void TranslateInfoBarDelegate::ToggleAlwaysTranslate() {
181 ui_delegate_.SetAlwaysTranslate(!ui_delegate_.ShouldAlwaysTranslate());
184 void TranslateInfoBarDelegate::AlwaysTranslatePageLanguage() {
185 DCHECK(!ui_delegate_.ShouldAlwaysTranslate());
186 ui_delegate_.SetAlwaysTranslate(true);
187 Translate();
190 void TranslateInfoBarDelegate::NeverTranslatePageLanguage() {
191 DCHECK(!ui_delegate_.IsLanguageBlocked());
192 ui_delegate_.SetLanguageBlocked(true);
193 infobar()->RemoveSelf();
196 base::string16 TranslateInfoBarDelegate::GetMessageInfoBarText() {
197 if (step_ == TranslateTabHelper::TRANSLATING) {
198 base::string16 target_language_name =
199 language_name_at(target_language_index());
200 return l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_TRANSLATING_TO,
201 target_language_name);
204 DCHECK_EQ(TranslateTabHelper::TRANSLATE_ERROR, step_);
205 UMA_HISTOGRAM_ENUMERATION("Translate.ShowErrorInfobar",
206 error_type_,
207 TranslateErrors::TRANSLATE_ERROR_MAX);
208 ui_delegate_.OnErrorShown(error_type_);
209 switch (error_type_) {
210 case TranslateErrors::NETWORK:
211 return l10n_util::GetStringUTF16(
212 IDS_TRANSLATE_INFOBAR_ERROR_CANT_CONNECT);
213 case TranslateErrors::INITIALIZATION_ERROR:
214 case TranslateErrors::TRANSLATION_ERROR:
215 return l10n_util::GetStringUTF16(
216 IDS_TRANSLATE_INFOBAR_ERROR_CANT_TRANSLATE);
217 case TranslateErrors::UNKNOWN_LANGUAGE:
218 return l10n_util::GetStringUTF16(
219 IDS_TRANSLATE_INFOBAR_UNKNOWN_PAGE_LANGUAGE);
220 case TranslateErrors::UNSUPPORTED_LANGUAGE:
221 return l10n_util::GetStringFUTF16(
222 IDS_TRANSLATE_INFOBAR_UNSUPPORTED_PAGE_LANGUAGE,
223 language_name_at(target_language_index()));
224 case TranslateErrors::IDENTICAL_LANGUAGES:
225 return l10n_util::GetStringFUTF16(
226 IDS_TRANSLATE_INFOBAR_ERROR_SAME_LANGUAGE,
227 language_name_at(target_language_index()));
228 default:
229 NOTREACHED();
230 return base::string16();
234 base::string16 TranslateInfoBarDelegate::GetMessageInfoBarButtonText() {
235 if (step_ != TranslateTabHelper::TRANSLATE_ERROR) {
236 DCHECK_EQ(TranslateTabHelper::TRANSLATING, step_);
237 } else if ((error_type_ != TranslateErrors::IDENTICAL_LANGUAGES) &&
238 (error_type_ != TranslateErrors::UNKNOWN_LANGUAGE)) {
239 return l10n_util::GetStringUTF16(
240 (error_type_ == TranslateErrors::UNSUPPORTED_LANGUAGE) ?
241 IDS_TRANSLATE_INFOBAR_REVERT : IDS_TRANSLATE_INFOBAR_RETRY);
243 return base::string16();
246 void TranslateInfoBarDelegate::MessageInfoBarButtonPressed() {
247 DCHECK_EQ(TranslateTabHelper::TRANSLATE_ERROR, step_);
248 if (error_type_ == TranslateErrors::UNSUPPORTED_LANGUAGE) {
249 RevertTranslation();
250 return;
252 // This is the "Try again..." case.
253 TranslateManager::GetInstance()->TranslatePage(
254 web_contents(), original_language_code(), target_language_code());
257 bool TranslateInfoBarDelegate::ShouldShowMessageInfoBarButton() {
258 return !GetMessageInfoBarButtonText().empty();
261 bool TranslateInfoBarDelegate::ShouldShowNeverTranslateShortcut() {
262 DCHECK_EQ(TranslateTabHelper::BEFORE_TRANSLATE, step_);
263 return !web_contents()->GetBrowserContext()->IsOffTheRecord() &&
264 (prefs_->GetTranslationDeniedCount(original_language_code()) >=
265 kNeverTranslateMinCount);
268 bool TranslateInfoBarDelegate::ShouldShowAlwaysTranslateShortcut() {
269 DCHECK_EQ(TranslateTabHelper::BEFORE_TRANSLATE, step_);
270 return !web_contents()->GetBrowserContext()->IsOffTheRecord() &&
271 (prefs_->GetTranslationAcceptedCount(original_language_code()) >=
272 kAlwaysTranslateMinCount);
275 // static
276 base::string16 TranslateInfoBarDelegate::GetLanguageDisplayableName(
277 const std::string& language_code) {
278 return l10n_util::GetDisplayNameForLocale(
279 language_code, g_browser_process->GetApplicationLocale(), true);
282 // static
283 void TranslateInfoBarDelegate::GetAfterTranslateStrings(
284 std::vector<base::string16>* strings,
285 bool* swap_languages,
286 bool autodetermined_source_language) {
287 DCHECK(strings);
289 if (autodetermined_source_language) {
290 size_t offset;
291 base::string16 text = l10n_util::GetStringFUTF16(
292 IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_AUTODETERMINED_SOURCE_LANGUAGE,
293 base::string16(),
294 &offset);
296 strings->push_back(text.substr(0, offset));
297 strings->push_back(text.substr(offset));
298 return;
300 DCHECK(swap_languages);
302 std::vector<size_t> offsets;
303 base::string16 text = l10n_util::GetStringFUTF16(
304 IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE, base::string16(), base::string16(),
305 &offsets);
306 DCHECK_EQ(2U, offsets.size());
308 *swap_languages = (offsets[0] > offsets[1]);
309 if (*swap_languages)
310 std::swap(offsets[0], offsets[1]);
312 strings->push_back(text.substr(0, offsets[0]));
313 strings->push_back(text.substr(offsets[0], offsets[1] - offsets[0]));
314 strings->push_back(text.substr(offsets[1]));
317 TranslateInfoBarDelegate::TranslateInfoBarDelegate(
318 content::WebContents* web_contents,
319 TranslateTabHelper::TranslateStep step,
320 TranslateInfoBarDelegate* old_delegate,
321 const std::string& original_language,
322 const std::string& target_language,
323 TranslateErrors::Type error_type,
324 PrefService* prefs)
325 : InfoBarDelegate(),
326 step_(step),
327 background_animation_(NONE),
328 ui_delegate_(web_contents, original_language, target_language),
329 error_type_(error_type),
330 prefs_(TranslateTabHelper::CreateTranslatePrefs(prefs)) {
331 DCHECK_NE((step_ == TranslateTabHelper::TRANSLATE_ERROR),
332 (error_type_ == TranslateErrors::NONE));
334 if (old_delegate && (old_delegate->is_error() != is_error()))
335 background_animation_ = is_error() ? NORMAL_TO_ERROR : ERROR_TO_NORMAL;
338 // TranslateInfoBarDelegate::CreateInfoBar() is implemented in platform-specific
339 // files.
341 void TranslateInfoBarDelegate::InfoBarDismissed() {
342 if (step_ != TranslateTabHelper::BEFORE_TRANSLATE)
343 return;
345 // The user closed the infobar without clicking the translate button.
346 TranslationDeclined();
347 UMA_HISTOGRAM_BOOLEAN("Translate.DeclineTranslateCloseInfobar", true);
350 int TranslateInfoBarDelegate::GetIconID() const {
351 return IDR_INFOBAR_TRANSLATE;
354 InfoBarDelegate::Type TranslateInfoBarDelegate::GetInfoBarType() const {
355 return PAGE_ACTION_TYPE;
358 bool TranslateInfoBarDelegate::ShouldExpire(
359 const content::LoadCommittedDetails& details) const {
360 // Note: we allow closing this infobar even if the main frame navigation
361 // was programmatic and not initiated by the user - crbug.com/70261 .
362 if (!details.is_navigation_to_different_page() && !details.is_main_frame)
363 return false;
365 return InfoBarDelegate::ShouldExpireInternal(details);
368 TranslateInfoBarDelegate*
369 TranslateInfoBarDelegate::AsTranslateInfoBarDelegate() {
370 return this;