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 #ifndef COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_INFOBAR_DELEGATE_H_ 6 #define COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_INFOBAR_DELEGATE_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include "base/feature_list.h" 16 #include "base/macros.h" 17 #include "base/memory/weak_ptr.h" 18 #include "base/observer_list.h" 19 #include "base/observer_list_types.h" 20 #include "build/build_config.h" 21 #include "components/infobars/core/infobar_delegate.h" 22 #include "components/translate/core/browser/translate_prefs.h" 23 #include "components/translate/core/browser/translate_step.h" 24 #include "components/translate/core/browser/translate_ui_delegate.h" 25 #include "components/translate/core/common/translate_constants.h" 26 #include "components/translate/core/common/translate_errors.h" 27 28 namespace infobars { 29 class InfoBarManager; 30 } 31 32 namespace translate { 33 34 // Feature flag used to control the auto-always and auto-never snackbar 35 // parameters (i.e. threshold and maximum-number-of). 36 extern const base::Feature kTranslateAutoSnackbars; 37 38 // Feature flag for "Translate Compact Infobar UI" project. 39 extern const base::Feature kTranslateCompactUI; 40 41 class TranslateDriver; 42 class TranslateManager; 43 44 class TranslateInfoBarDelegate : public infobars::InfoBarDelegate { 45 public: 46 // An observer to handle different translate steps' UI changes. 47 class Observer : public base::CheckedObserver { 48 public: 49 // Handles UI changes on the translate step given. 50 virtual void OnTranslateStepChanged(translate::TranslateStep step, 51 TranslateErrors::Type error_type) = 0; 52 // Handles UI changes when the target language is updated. 53 virtual void OnTargetLanguageChanged( 54 const std::string& target_language_code) = 0; 55 // Return whether user declined translate service. 56 virtual bool IsDeclinedByUser() = 0; 57 // Called when the TranslateInfoBarDelegate instance is destroyed. 58 virtual void OnTranslateInfoBarDelegateDestroyed( 59 TranslateInfoBarDelegate* delegate) = 0; 60 }; 61 62 static const size_t kNoIndex; 63 64 // Get the threshold and maximum number of occurences that parameterize 65 // automatic always- and never-translate. 66 static int GetAutoAlwaysThreshold(); 67 static int GetAutoNeverThreshold(); 68 static int GetMaximumNumberOfAutoAlways(); 69 static int GetMaximumNumberOfAutoNever(); 70 71 ~TranslateInfoBarDelegate() override; 72 73 // Factory method to create a translate infobar. |error_type| must be 74 // specified iff |step| == TRANSLATION_ERROR. For other translate steps, 75 // |original_language| and |target_language| must be ASCII language codes 76 // (e.g. "en", "fr", etc.) for languages the TranslateManager supports 77 // translating. The lone exception is when the user initiates translation 78 // from the context menu, in which case it's legal to call this with 79 // |step| == TRANSLATING and |original_language| == kUnknownLanguageCode. 80 // 81 // If |replace_existing_infobar| is true, the infobar is created and added to 82 // the infobar manager, replacing any other translate infobar already present 83 // there. Otherwise, the infobar will only be added if there is no other 84 // translate infobar already present. 85 static void Create(bool replace_existing_infobar, 86 const base::WeakPtr<TranslateManager>& translate_manager, 87 infobars::InfoBarManager* infobar_manager, 88 bool is_off_the_record, 89 translate::TranslateStep step, 90 const std::string& original_language, 91 const std::string& target_language, 92 TranslateErrors::Type error_type, 93 bool triggered_from_menu); 94 95 // Returns the number of languages supported. 96 virtual size_t num_languages() const; 97 98 // Returns the ISO code for the language at |index|. 99 virtual std::string language_code_at(size_t index) const; 100 101 // Returns the displayable name for the language at |index|. 102 virtual base::string16 language_name_at(size_t index) const; 103 translate_step()104 translate::TranslateStep translate_step() const { return step_; } 105 is_off_the_record()106 bool is_off_the_record() { return is_off_the_record_; } 107 error_type()108 TranslateErrors::Type error_type() const { return error_type_; } 109 original_language_code()110 std::string original_language_code() const { 111 return ui_delegate_.GetOriginalLanguageCode(); 112 } 113 114 virtual base::string16 original_language_name() const; 115 116 virtual void UpdateOriginalLanguage(const std::string& language_code); 117 target_language_code()118 std::string target_language_code() const { 119 return ui_delegate_.GetTargetLanguageCode(); 120 } 121 122 virtual base::string16 target_language_name() const; 123 124 virtual void UpdateTargetLanguage(const std::string& language_code); 125 126 // Returns true if the current infobar indicates an error (in which case it 127 // should get a yellow background instead of a blue one). is_error()128 bool is_error() const { 129 return step_ == translate::TRANSLATE_STEP_TRANSLATE_ERROR; 130 } 131 132 void OnErrorShown(TranslateErrors::Type error_type); 133 134 // Return true if the translation was triggered by a menu entry instead of 135 // via an infobar/bubble or preference. triggered_from_menu()136 bool triggered_from_menu() const { 137 return triggered_from_menu_; 138 } 139 140 virtual void Translate(); 141 virtual void RevertTranslation(); 142 virtual void RevertWithoutClosingInfobar(); 143 void ReportLanguageDetectionError(); 144 145 // Called when the user declines to translate a page, by either closing the 146 // infobar or pressing the "Don't translate" button. 147 virtual void TranslationDeclined(); 148 149 // Methods called by the Options menu delegate. 150 virtual bool IsTranslatableLanguageByPrefs() const; 151 virtual void ToggleTranslatableLanguageByPrefs(); 152 virtual bool IsSiteBlacklisted() const; 153 virtual void ToggleSiteBlacklist(); 154 virtual bool ShouldAlwaysTranslate() const; 155 virtual void ToggleAlwaysTranslate(); 156 157 // Methods called by the extra-buttons that can appear on the "before 158 // translate" infobar (when the user has accepted/declined the translation 159 // several times). 160 void AlwaysTranslatePageLanguage(); 161 void NeverTranslatePageLanguage(); 162 163 int GetTranslationAcceptedCount(); 164 int GetTranslationDeniedCount(); 165 166 void ResetTranslationAcceptedCount(); 167 void ResetTranslationDeniedCount(); 168 169 // Returns whether "Always Translate Language" should automatically trigger. 170 // If true, this method has the side effect of mutating some prefs. 171 bool ShouldAutoAlwaysTranslate(); 172 // Returns whether "Never Translate Language" should automatically trigger. 173 // If true, this method has the side effect of mutating some prefs. 174 bool ShouldAutoNeverTranslate(); 175 176 int GetTranslationAutoAlwaysCount(); 177 int GetTranslationAutoNeverCount(); 178 179 void IncrementTranslationAutoAlwaysCount(); 180 void IncrementTranslationAutoNeverCount(); 181 182 // The following methods are called by the infobar that displays the status 183 // while translating and also the one displaying the error message. 184 base::string16 GetMessageInfoBarButtonText(); 185 void MessageInfoBarButtonPressed(); 186 bool ShouldShowMessageInfoBarButton(); 187 188 // Returns true if the infobar should offer a (platform-specific) shortcut to 189 // allow the user to always/never translate the language, when we think the 190 // user wants that functionality. 191 bool ShouldShowAlwaysTranslateShortcut(); 192 bool ShouldShowNeverTranslateShortcut(); 193 194 #if defined(OS_IOS) 195 // Shows the Infobar offering to never translate the language or the site. 196 void ShowNeverTranslateInfobar(); 197 #endif 198 199 // Adds the strings that should be displayed in the after translate infobar to 200 // |strings|. If |autodetermined_source_language| is false, the text in that 201 // infobar is: 202 // "The page has been translated from <lang1> to <lang2>." 203 // Otherwise: 204 // "The page has been translated to <lang1>." 205 // Because <lang1>, or <lang1> and <lang2> are displayed in menu buttons, the 206 // text is split in 2 or 3 chunks. |swap_languages| is set to true if 207 // |autodetermined_source_language| is false, and <lang1> and <lang2> 208 // should be inverted (some languages express the sentense as "The page has 209 // been translate to <lang2> from <lang1>."). It is ignored if 210 // |autodetermined_source_language| is true. 211 static void GetAfterTranslateStrings(std::vector<base::string16>* strings, 212 bool* swap_languages, 213 bool autodetermined_source_language); 214 215 // Gets the TranslateDriver associated with this object. 216 // May return NULL if the driver has been destroyed. 217 TranslateDriver* GetTranslateDriver(); 218 219 // Add an observer. 220 virtual void AddObserver(Observer* observer); 221 222 // Remove an observer. 223 virtual void RemoveObserver(Observer* observer); 224 225 // Handles when the user closes the translate infobar. This includes when: the 226 // user presses the 'x' button, the user selects to never translate the site, 227 // and the user selects to never translate the language. 228 void OnInfoBarClosedByUser(); 229 230 // InfoBarDelegate: 231 infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; 232 int GetIconId() const override; 233 void InfoBarDismissed() override; 234 TranslateInfoBarDelegate* AsTranslateInfoBarDelegate() override; 235 236 protected: 237 TranslateInfoBarDelegate( 238 const base::WeakPtr<TranslateManager>& translate_manager, 239 bool is_off_the_record, 240 translate::TranslateStep step, 241 const std::string& original_language, 242 const std::string& target_language, 243 TranslateErrors::Type error_type, 244 bool triggered_from_menu); 245 246 private: 247 friend class TranslationInfoBarTest; 248 typedef std::pair<std::string, base::string16> LanguageNamePair; 249 250 bool is_off_the_record_; 251 translate::TranslateStep step_; 252 253 TranslateUIDelegate ui_delegate_; 254 base::WeakPtr<TranslateManager> translate_manager_; 255 256 // The error that occurred when trying to translate (NONE if no error). 257 TranslateErrors::Type error_type_; 258 259 // The translation related preferences. 260 std::unique_ptr<TranslatePrefs> prefs_; 261 262 // Whether the translation was triggered via a menu click vs automatically 263 // (due to language detection, preferences...) 264 bool triggered_from_menu_; 265 266 // Observers to handle front-end changes on different steps. 267 // It's only used when we try to reuse the existing UI. 268 base::ObserverList<Observer> observers_; 269 270 DISALLOW_COPY_AND_ASSIGN(TranslateInfoBarDelegate); 271 }; 272 273 } // namespace translate 274 275 #endif // COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_INFOBAR_DELEGATE_H_ 276