EME test page application.
[chromium-blink-merge.git] / chrome / browser / translate / translate_infobar_delegate.cc
blobdb277adb16d5ddf378d635843d56e68284256cdd
1 // Copyright 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 "components/infobars/core/infobar.h"
12 #include "components/infobars/core/infobar_manager.h"
13 #include "components/translate/core/browser/language_state.h"
14 #include "components/translate/core/browser/translate_accept_languages.h"
15 #include "components/translate/core/browser/translate_client.h"
16 #include "components/translate/core/browser/translate_download_manager.h"
17 #include "components/translate/core/browser/translate_driver.h"
18 #include "components/translate/core/browser/translate_manager.h"
19 #include "components/translate/core/common/translate_constants.h"
20 #include "grit/components_strings.h"
21 #include "grit/theme_resources.h"
22 #include "third_party/icu/source/i18n/unicode/coll.h"
23 #include "ui/base/l10n/l10n_util.h"
25 namespace {
27 // Counts used to decide whether infobars should be shown.
28 // Android and iOS implementations do not offer a drop down (for space reasons),
29 // so we are more aggressive about showing the shortcut to never translate.
30 // The "Always Translate" option is always shown on iOS and Android.
31 #if defined(OS_ANDROID)
32 const int kAlwaysTranslateMinCount = 1;
33 const int kNeverTranslateMinCount = 1;
34 #elif defined(OS_IOS)
35 // The iOS implementation, like the Android implementation, shows the "Never
36 // translate" infobar after two denials. There is an offset of one because on
37 // Android the last event is not counted.
38 const int kAlwaysTranslateMinCount = 1;
39 const int kNeverTranslateMinCount = 2;
40 #else
41 const int kAlwaysTranslateMinCount = 3;
42 const int kNeverTranslateMinCount = 3;
43 #endif
45 } // namespace
47 const size_t TranslateInfoBarDelegate::kNoIndex = TranslateUIDelegate::NO_INDEX;
49 TranslateInfoBarDelegate::~TranslateInfoBarDelegate() {
52 // static
53 void TranslateInfoBarDelegate::Create(
54 bool replace_existing_infobar,
55 const base::WeakPtr<TranslateManager>& translate_manager,
56 infobars::InfoBarManager* infobar_manager,
57 bool is_off_the_record,
58 translate::TranslateStep step,
59 const std::string& original_language,
60 const std::string& target_language,
61 TranslateErrors::Type error_type,
62 bool triggered_from_menu) {
63 DCHECK(translate_manager);
64 DCHECK(infobar_manager);
66 // Check preconditions.
67 if (step != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
68 DCHECK(TranslateDownloadManager::IsSupportedLanguage(target_language));
69 if (!TranslateDownloadManager::IsSupportedLanguage(original_language)) {
70 // The original language can only be "unknown" for the "translating"
71 // infobar, which is the case when the user started a translation from the
72 // context menu.
73 DCHECK(step == translate::TRANSLATE_STEP_TRANSLATING ||
74 step == translate::TRANSLATE_STEP_AFTER_TRANSLATE);
75 DCHECK_EQ(translate::kUnknownLanguageCode, original_language);
79 // Do not create the after translate infobar if we are auto translating.
80 if (((step == translate::TRANSLATE_STEP_AFTER_TRANSLATE) ||
81 (step == translate::TRANSLATE_STEP_TRANSLATING)) &&
82 translate_manager->translate_client()->GetTranslateDriver()
83 ->GetLanguageState().InTranslateNavigation()) {
84 return;
87 // Find any existing translate infobar delegate.
88 infobars::InfoBar* old_infobar = NULL;
89 TranslateInfoBarDelegate* old_delegate = NULL;
90 for (size_t i = 0; i < infobar_manager->infobar_count(); ++i) {
91 old_infobar = infobar_manager->infobar_at(i);
92 old_delegate = old_infobar->delegate()->AsTranslateInfoBarDelegate();
93 if (old_delegate) {
94 if (!replace_existing_infobar)
95 return;
96 break;
100 // Add the new delegate.
101 scoped_ptr<infobars::InfoBar> infobar(CreateInfoBar(
102 scoped_ptr<TranslateInfoBarDelegate>(new TranslateInfoBarDelegate(
103 translate_manager, is_off_the_record, step, old_delegate,
104 original_language, target_language, error_type,
105 triggered_from_menu))));
106 if (old_delegate)
107 infobar_manager->ReplaceInfoBar(old_infobar, infobar.Pass());
108 else
109 infobar_manager->AddInfoBar(infobar.Pass());
113 void TranslateInfoBarDelegate::UpdateOriginalLanguageIndex(
114 size_t language_index) {
115 ui_delegate_.UpdateOriginalLanguageIndex(language_index);
118 void TranslateInfoBarDelegate::UpdateTargetLanguageIndex(
119 size_t language_index) {
120 ui_delegate_.UpdateTargetLanguageIndex(language_index);
123 void TranslateInfoBarDelegate::Translate() {
124 ui_delegate_.Translate();
127 void TranslateInfoBarDelegate::RevertTranslation() {
128 ui_delegate_.RevertTranslation();
129 infobar()->RemoveSelf();
132 void TranslateInfoBarDelegate::ReportLanguageDetectionError() {
133 if (translate_manager_)
134 translate_manager_->ReportLanguageDetectionError();
137 void TranslateInfoBarDelegate::TranslationDeclined() {
138 ui_delegate_.TranslationDeclined(false);
141 bool TranslateInfoBarDelegate::IsTranslatableLanguageByPrefs() {
142 TranslateClient* client = GetTranslateClient();
143 scoped_ptr<TranslatePrefs> translate_prefs(client->GetTranslatePrefs());
144 TranslateAcceptLanguages* accept_languages =
145 client->GetTranslateAcceptLanguages();
146 return translate_prefs->CanTranslateLanguage(accept_languages,
147 original_language_code());
150 void TranslateInfoBarDelegate::ToggleTranslatableLanguageByPrefs() {
151 if (ui_delegate_.IsLanguageBlocked()) {
152 ui_delegate_.SetLanguageBlocked(false);
153 } else {
154 ui_delegate_.SetLanguageBlocked(true);
155 infobar()->RemoveSelf();
159 bool TranslateInfoBarDelegate::IsSiteBlacklisted() {
160 return ui_delegate_.IsSiteBlacklisted();
163 void TranslateInfoBarDelegate::ToggleSiteBlacklist() {
164 if (ui_delegate_.IsSiteBlacklisted()) {
165 ui_delegate_.SetSiteBlacklist(false);
166 } else {
167 ui_delegate_.SetSiteBlacklist(true);
168 infobar()->RemoveSelf();
172 bool TranslateInfoBarDelegate::ShouldAlwaysTranslate() {
173 return ui_delegate_.ShouldAlwaysTranslate();
176 void TranslateInfoBarDelegate::ToggleAlwaysTranslate() {
177 ui_delegate_.SetAlwaysTranslate(!ui_delegate_.ShouldAlwaysTranslate());
180 void TranslateInfoBarDelegate::AlwaysTranslatePageLanguage() {
181 DCHECK(!ui_delegate_.ShouldAlwaysTranslate());
182 ui_delegate_.SetAlwaysTranslate(true);
183 Translate();
186 void TranslateInfoBarDelegate::NeverTranslatePageLanguage() {
187 DCHECK(!ui_delegate_.IsLanguageBlocked());
188 ui_delegate_.SetLanguageBlocked(true);
189 infobar()->RemoveSelf();
192 base::string16 TranslateInfoBarDelegate::GetMessageInfoBarText() {
193 if (step_ == translate::TRANSLATE_STEP_TRANSLATING) {
194 base::string16 target_language_name =
195 language_name_at(target_language_index());
196 return l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_TRANSLATING_TO,
197 target_language_name);
200 DCHECK_EQ(translate::TRANSLATE_STEP_TRANSLATE_ERROR, step_);
201 UMA_HISTOGRAM_ENUMERATION("Translate.ShowErrorInfobar",
202 error_type_,
203 TranslateErrors::TRANSLATE_ERROR_MAX);
204 ui_delegate_.OnErrorShown(error_type_);
205 switch (error_type_) {
206 case TranslateErrors::NETWORK:
207 return l10n_util::GetStringUTF16(
208 IDS_TRANSLATE_INFOBAR_ERROR_CANT_CONNECT);
209 case TranslateErrors::INITIALIZATION_ERROR:
210 case TranslateErrors::TRANSLATION_ERROR:
211 return l10n_util::GetStringUTF16(
212 IDS_TRANSLATE_INFOBAR_ERROR_CANT_TRANSLATE);
213 case TranslateErrors::UNKNOWN_LANGUAGE:
214 return l10n_util::GetStringUTF16(
215 IDS_TRANSLATE_INFOBAR_UNKNOWN_PAGE_LANGUAGE);
216 case TranslateErrors::UNSUPPORTED_LANGUAGE:
217 return l10n_util::GetStringFUTF16(
218 IDS_TRANSLATE_INFOBAR_UNSUPPORTED_PAGE_LANGUAGE,
219 language_name_at(target_language_index()));
220 case TranslateErrors::IDENTICAL_LANGUAGES:
221 return l10n_util::GetStringFUTF16(
222 IDS_TRANSLATE_INFOBAR_ERROR_SAME_LANGUAGE,
223 language_name_at(target_language_index()));
224 default:
225 NOTREACHED();
226 return base::string16();
230 base::string16 TranslateInfoBarDelegate::GetMessageInfoBarButtonText() {
231 if (step_ != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
232 DCHECK_EQ(translate::TRANSLATE_STEP_TRANSLATING, step_);
233 } else if ((error_type_ != TranslateErrors::IDENTICAL_LANGUAGES) &&
234 (error_type_ != TranslateErrors::UNKNOWN_LANGUAGE)) {
235 return l10n_util::GetStringUTF16(
236 (error_type_ == TranslateErrors::UNSUPPORTED_LANGUAGE) ?
237 IDS_TRANSLATE_INFOBAR_REVERT : IDS_TRANSLATE_INFOBAR_RETRY);
239 return base::string16();
242 void TranslateInfoBarDelegate::MessageInfoBarButtonPressed() {
243 DCHECK_EQ(translate::TRANSLATE_STEP_TRANSLATE_ERROR, step_);
244 if (error_type_ == TranslateErrors::UNSUPPORTED_LANGUAGE) {
245 RevertTranslation();
246 return;
248 // This is the "Try again..." case.
249 DCHECK(translate_manager_);
250 translate_manager_->TranslatePage(
251 original_language_code(), target_language_code(), false);
254 bool TranslateInfoBarDelegate::ShouldShowMessageInfoBarButton() {
255 return !GetMessageInfoBarButtonText().empty();
258 bool TranslateInfoBarDelegate::ShouldShowNeverTranslateShortcut() {
259 DCHECK_EQ(translate::TRANSLATE_STEP_BEFORE_TRANSLATE, step_);
260 return !is_off_the_record_ &&
261 (prefs_->GetTranslationDeniedCount(original_language_code()) >=
262 kNeverTranslateMinCount);
265 bool TranslateInfoBarDelegate::ShouldShowAlwaysTranslateShortcut() {
266 DCHECK_EQ(translate::TRANSLATE_STEP_BEFORE_TRANSLATE, step_);
267 return !is_off_the_record_ &&
268 (prefs_->GetTranslationAcceptedCount(original_language_code()) >=
269 kAlwaysTranslateMinCount);
272 // static
273 void TranslateInfoBarDelegate::GetAfterTranslateStrings(
274 std::vector<base::string16>* strings,
275 bool* swap_languages,
276 bool autodetermined_source_language) {
277 DCHECK(strings);
279 if (autodetermined_source_language) {
280 size_t offset;
281 base::string16 text = l10n_util::GetStringFUTF16(
282 IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_AUTODETERMINED_SOURCE_LANGUAGE,
283 base::string16(),
284 &offset);
286 strings->push_back(text.substr(0, offset));
287 strings->push_back(text.substr(offset));
288 return;
290 DCHECK(swap_languages);
292 std::vector<size_t> offsets;
293 base::string16 text = l10n_util::GetStringFUTF16(
294 IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE, base::string16(), base::string16(),
295 &offsets);
296 DCHECK_EQ(2U, offsets.size());
298 *swap_languages = (offsets[0] > offsets[1]);
299 if (*swap_languages)
300 std::swap(offsets[0], offsets[1]);
302 strings->push_back(text.substr(0, offsets[0]));
303 strings->push_back(text.substr(offsets[0], offsets[1] - offsets[0]));
304 strings->push_back(text.substr(offsets[1]));
307 TranslateDriver* TranslateInfoBarDelegate::GetTranslateDriver() {
308 if (!translate_manager_)
309 return NULL;
311 return translate_manager_->translate_client()->GetTranslateDriver();
314 TranslateInfoBarDelegate::TranslateInfoBarDelegate(
315 const base::WeakPtr<TranslateManager>& translate_manager,
316 bool is_off_the_record,
317 translate::TranslateStep step,
318 TranslateInfoBarDelegate* old_delegate,
319 const std::string& original_language,
320 const std::string& target_language,
321 TranslateErrors::Type error_type,
322 bool triggered_from_menu)
323 : infobars::InfoBarDelegate(),
324 is_off_the_record_(is_off_the_record),
325 step_(step),
326 background_animation_(NONE),
327 ui_delegate_(translate_manager->translate_client(),
328 translate_manager.get(),
329 original_language,
330 target_language),
331 translate_manager_(translate_manager),
332 error_type_(error_type),
333 prefs_(translate_manager->translate_client()->GetTranslatePrefs()),
334 triggered_from_menu_(triggered_from_menu) {
335 DCHECK_NE((step_ == translate::TRANSLATE_STEP_TRANSLATE_ERROR),
336 (error_type_ == TranslateErrors::NONE));
337 DCHECK(translate_manager_);
339 if (old_delegate && (old_delegate->is_error() != is_error()))
340 background_animation_ = is_error() ? NORMAL_TO_ERROR : ERROR_TO_NORMAL;
343 TranslateClient* TranslateInfoBarDelegate::GetTranslateClient() {
344 if (!translate_manager_)
345 return NULL;
347 return translate_manager_->translate_client();
350 // TranslateInfoBarDelegate::CreateInfoBar() is implemented in platform-specific
351 // files.
353 void TranslateInfoBarDelegate::InfoBarDismissed() {
354 if (step_ != translate::TRANSLATE_STEP_BEFORE_TRANSLATE)
355 return;
357 // The user closed the infobar without clicking the translate button.
358 TranslationDeclined();
359 UMA_HISTOGRAM_BOOLEAN("Translate.DeclineTranslateCloseInfobar", true);
362 int TranslateInfoBarDelegate::GetIconID() const {
363 return IDR_INFOBAR_TRANSLATE;
366 infobars::InfoBarDelegate::Type TranslateInfoBarDelegate::GetInfoBarType()
367 const {
368 return PAGE_ACTION_TYPE;
371 bool TranslateInfoBarDelegate::ShouldExpire(
372 const NavigationDetails& details) const {
373 // Note: we allow closing this infobar even if the main frame navigation
374 // was programmatic and not initiated by the user - crbug.com/70261 .
375 if (!details.is_navigation_to_different_page && !details.is_main_frame)
376 return false;
378 return infobars::InfoBarDelegate::ShouldExpireInternal(details);
381 TranslateInfoBarDelegate*
382 TranslateInfoBarDelegate::AsTranslateInfoBarDelegate() {
383 return this;