| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/translate/core/browser/translate_manager.h" |
| |
| #include <map> |
| #include <memory> |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/metrics/histogram.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/time/time.h" |
| #include "components/language/core/browser/language_model.h" |
| #include "components/language/core/common/language_experiments.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/translate/core/browser/language_state.h" |
| #include "components/translate/core/browser/page_translated_details.h" |
| #include "components/translate/core/browser/translate_accept_languages.h" |
| #include "components/translate/core/browser/translate_browser_metrics.h" |
| #include "components/translate/core/browser/translate_client.h" |
| #include "components/translate/core/browser/translate_download_manager.h" |
| #include "components/translate/core/browser/translate_driver.h" |
| #include "components/translate/core/browser/translate_error_details.h" |
| #include "components/translate/core/browser/translate_language_list.h" |
| #include "components/translate/core/browser/translate_prefs.h" |
| #include "components/translate/core/browser/translate_ranker.h" |
| #include "components/translate/core/browser/translate_script.h" |
| #include "components/translate/core/browser/translate_url_util.h" |
| #include "components/translate/core/common/language_detection_details.h" |
| #include "components/translate/core/common/translate_constants.h" |
| #include "components/translate/core/common/translate_switches.h" |
| #include "components/translate/core/common/translate_util.h" |
| #include "components/variations/variations_associated_data.h" |
| #include "google_apis/google_api_keys.h" |
| #include "net/base/network_change_notifier.h" |
| #include "net/base/url_util.h" |
| #include "net/http/http_status_code.h" |
| #include "third_party/metrics_proto/translate_event.pb.h" |
| |
| namespace translate { |
| |
| namespace { |
| |
| // Callbacks for translate errors. |
| TranslateManager::TranslateErrorCallbackList* g_callback_list_ = nullptr; |
| |
| const char kReportLanguageDetectionErrorURL[] = |
| "https://translate.google.com/translate_error?client=cr&action=langidc"; |
| |
| // Used in kReportLanguageDetectionErrorURL to specify the original page |
| // language. |
| const char kSourceLanguageQueryName[] = "sl"; |
| |
| // Used in kReportLanguageDetectionErrorURL to specify the page URL. |
| const char kUrlQueryName[] = "u"; |
| |
| std::set<std::string> GetSkippedLanguagesForExperiments( |
| std::string source_lang, |
| translate::TranslatePrefs* translate_prefs) { |
| // Under this experiment, skip english as the target language if possible so |
| // that Translate triggers on English pages. |
| std::set<std::string> skipped_languages; |
| if (language::ShouldForceTriggerTranslateOnEnglishPages( |
| translate_prefs->GetForceTriggerOnEnglishPagesCount()) && |
| source_lang == "en") { |
| skipped_languages.insert("en"); |
| } |
| return skipped_languages; |
| } |
| |
| // Moves any element in |languages| for which |lang_code| is found in |
| // |skipped_languages| to the end of |languages|. Otherwise preserves relative |
| // ordering of elements. Modifies |languages| in place. |
| void MoveSkippedLanguagesToEndIfNecessary( |
| std::vector<std::string>* languages, |
| const std::set<std::string>& skipped_languages) { |
| if (!skipped_languages.empty()) { |
| std::stable_partition( |
| languages->begin(), languages->end(), [&](const auto& lang) { |
| return skipped_languages.find(lang) == skipped_languages.end(); |
| }); |
| } |
| } |
| |
| } // namespace |
| |
| TranslateManager::~TranslateManager() {} |
| |
| // static |
| std::unique_ptr<TranslateManager::TranslateErrorCallbackList::Subscription> |
| TranslateManager::RegisterTranslateErrorCallback( |
| const TranslateManager::TranslateErrorCallback& callback) { |
| if (!g_callback_list_) |
| g_callback_list_ = new TranslateErrorCallbackList; |
| return g_callback_list_->Add(callback); |
| } |
| |
| TranslateManager::TranslateManager(TranslateClient* translate_client, |
| TranslateRanker* translate_ranker, |
| language::LanguageModel* language_model) |
| : page_seq_no_(0), |
| translate_client_(translate_client), |
| translate_driver_(translate_client_->GetTranslateDriver()), |
| translate_ranker_(translate_ranker), |
| language_model_(language_model), |
| language_state_(translate_driver_), |
| translate_event_(std::make_unique<metrics::TranslateEventProto>()), |
| weak_method_factory_(this) {} |
| |
| base::WeakPtr<TranslateManager> TranslateManager::GetWeakPtr() { |
| return weak_method_factory_.GetWeakPtr(); |
| } |
| |
| void TranslateManager::InitiateTranslation(const std::string& page_lang) { |
| // Short-circuit out if not in a state where initiating translation makes |
| // sense (this method may be called muhtiple times for a given page). |
| if (!language_state_.page_needs_translation() || |
| language_state_.translation_pending() || |
| language_state_.translation_declined() || |
| language_state_.IsPageTranslated() || |
| !base::FeatureList::IsEnabled(translate::kTranslateUI)) { |
| return; |
| } |
| |
| // Also, skip if the connection is currently offline - initiation doesn't make |
| // sense there, either. |
| if (net::NetworkChangeNotifier::IsOffline()) |
| return; |
| |
| if (!ignore_missing_key_for_testing_ && |
| !::google_apis::HasAPIKeyConfigured()) { |
| // Without an API key, translate won't work, so don't offer to translate in |
| // the first place. Leave prefs::kOfferTranslateEnabled on, though, because |
| // that settings syncs and we don't want to turn off translate everywhere |
| // else. |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_KEY); |
| return; |
| } |
| |
| std::unique_ptr<TranslatePrefs> translate_prefs( |
| translate_client_->GetTranslatePrefs()); |
| |
| if (!translate_prefs->IsOfferTranslateEnabled()) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_PREFS); |
| std::string target_lang = |
| GetTargetLanguage(translate_prefs.get(), language_model_); |
| std::string language_code = |
| TranslateDownloadManager::GetLanguageCode(page_lang); |
| InitTranslateEvent(language_code, target_lang, *translate_prefs); |
| RecordTranslateEvent(metrics::TranslateEventProto::DISABLED_BY_PREF); |
| const std::string& locale = |
| TranslateDownloadManager::GetInstance()->application_locale(); |
| TranslateBrowserMetrics::ReportLocalesOnDisabledByPrefs(locale); |
| return; |
| } |
| |
| // MHTML pages currently cannot be translated. |
| // See bug: 217945. |
| if (translate_driver_->GetContentsMimeType() == "multipart/related") { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_MIME_TYPE_IS_NOT_SUPPORTED); |
| return; |
| } |
| |
| // Don't translate any Chrome specific page, e.g., New Tab Page, Download, |
| // History, and so on. |
| const GURL& page_url = translate_driver_->GetVisibleURL(); |
| if (!translate_client_->IsTranslatableURL(page_url)) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_URL_IS_NOT_SUPPORTED); |
| return; |
| } |
| |
| std::string language_code = |
| TranslateDownloadManager::GetLanguageCode(page_lang); |
| const std::set<std::string>& skipped_languages = |
| GetSkippedLanguagesForExperiments(language_code, translate_prefs.get()); |
| std::string target_lang = GetTargetLanguage( |
| translate_prefs.get(), language_model_, skipped_languages); |
| |
| // Don't translate similar languages (ex: en-US to en). |
| if (language_code == target_lang) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES); |
| return; |
| } |
| |
| InitTranslateEvent(language_code, target_lang, *translate_prefs); |
| |
| // Querying the ranker now, but not exiting immediately so that we may log |
| // other potential suppression reasons. |
| // Ignore Ranker's decision under triggering experiments since it wasn't |
| // trained appropriately under those scenarios. |
| bool should_offer_translation = |
| language::ShouldPreventRankerEnforcementInIndia( |
| translate_prefs->GetForceTriggerOnEnglishPagesCount()) || |
| translate_ranker_->ShouldOfferTranslation(translate_event_.get()); |
| |
| // Nothing to do if either the language Chrome is in or the language of |
| // the page is not supported by the translation server. |
| if (target_lang.empty() || |
| !TranslateDownloadManager::IsSupportedLanguage(language_code)) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_LANGUAGE_IS_NOT_SUPPORTED); |
| TranslateBrowserMetrics::ReportUnsupportedLanguageAtInitiation( |
| language_code); |
| RecordTranslateEvent(metrics::TranslateEventProto::UNSUPPORTED_LANGUAGE); |
| return; |
| } |
| |
| TranslateAcceptLanguages* accept_languages = |
| translate_client_->GetTranslateAcceptLanguages(); |
| // Don't translate any user black-listed languages. |
| if (!translate_prefs->CanTranslateLanguage(accept_languages, language_code)) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_CONFIG); |
| RecordTranslateEvent( |
| metrics::TranslateEventProto::LANGUAGE_DISABLED_BY_USER_CONFIG); |
| return; |
| } |
| |
| // Don't translate any user black-listed URLs. |
| if (translate_prefs->IsSiteBlacklisted(page_url.HostNoBrackets())) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_CONFIG); |
| RecordTranslateEvent( |
| metrics::TranslateEventProto::URL_DISABLED_BY_USER_CONFIG); |
| return; |
| } |
| |
| // If the user has previously selected "always translate" for this language we |
| // automatically translate. Note that in incognito mode we disable that |
| // feature; the user will get an infobar, so they can control whether the |
| // page's text is sent to the translate server. |
| if (!translate_driver_->IsIncognito()) { |
| std::string auto_target_lang = |
| GetAutoTargetLanguage(language_code, translate_prefs.get()); |
| if (!auto_target_lang.empty()) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_AUTO_BY_CONFIG); |
| translate_event_->set_modified_target_language(auto_target_lang); |
| RecordTranslateEvent( |
| metrics::TranslateEventProto::AUTO_TRANSLATION_BY_PREF); |
| TranslatePage(language_code, auto_target_lang, false); |
| return; |
| } |
| } |
| |
| std::string auto_translate_to = language_state_.AutoTranslateTo(); |
| if (!auto_translate_to.empty()) { |
| // This page was navigated through a click from a translated page. |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_AUTO_BY_LINK); |
| translate_event_->set_modified_target_language(auto_translate_to); |
| RecordTranslateEvent( |
| metrics::TranslateEventProto::AUTO_TRANSLATION_BY_LINK); |
| TranslatePage(language_code, auto_translate_to, false); |
| return; |
| } |
| |
| // Show the omnibar icon if we've gotten this far. |
| language_state_.SetTranslateEnabled(true); |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_SHOW_ICON); |
| |
| // Will be true if we've decided to show the infobar/bubble UI to the user. |
| bool did_show_ui = false; |
| |
| if (should_offer_translation) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_SHOW_INFOBAR); |
| |
| // If the source language matches the UI language, it means the translation |
| // prompt is being forced by an experiment. Report this so the count of how |
| // often it happens can be tracked to suppress the experiment as necessary. |
| if (language_code == |
| TranslateDownloadManager::GetLanguageCode( |
| TranslateDownloadManager::GetInstance()->application_locale())) { |
| translate_prefs->ReportForceTriggerOnEnglishPages(); |
| } |
| |
| // Prompts the user if they want the page translated. |
| did_show_ui = translate_client_->ShowTranslateUI( |
| translate::TRANSLATE_STEP_BEFORE_TRANSLATE, language_code, target_lang, |
| TranslateErrors::NONE, false); |
| |
| } else { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_ABORTED_BY_RANKER); |
| RecordTranslateEvent(metrics::TranslateEventProto::DISABLED_BY_RANKER); |
| } |
| |
| if (!did_show_ui) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_SUPPRESS_INFOBAR); |
| } |
| } |
| |
| void TranslateManager::TranslatePage(const std::string& original_source_lang, |
| const std::string& target_lang, |
| bool triggered_from_menu) { |
| if (!translate_driver_->HasCurrentPage()) { |
| NOTREACHED(); |
| return; |
| } |
| |
| // Log the source and target languages of the translate request. |
| TranslateBrowserMetrics::ReportTranslateSourceLanguage(original_source_lang); |
| TranslateBrowserMetrics::ReportTranslateTargetLanguage(target_lang); |
| |
| // If the source language matches the UI language, it means the translation |
| // prompt is being forced by an experiment. Report this so the count of how |
| // often it happens can be decremented (meaning the user didn't decline or |
| // ignore the prompt). |
| if (original_source_lang == |
| TranslateDownloadManager::GetLanguageCode( |
| TranslateDownloadManager::GetInstance()->application_locale())) { |
| translate_client_->GetTranslatePrefs() |
| ->ReportAcceptedAfterForceTriggerOnEnglishPages(); |
| } |
| |
| // If the target language isn't in the chrome://settings/languages list, add |
| // it there. This way, it's obvious to the user that Chrome is remembering |
| // their choice, they can remove it from the list, and they'll send that |
| // language in the Accept-Language header, giving servers a chance to serve |
| // them pages in that language. |
| AddTargetLanguageToAcceptLanguages(target_lang); |
| |
| // Translation can be kicked by context menu against unsupported languages. |
| // Unsupported language strings should be replaced with |
| // kUnknownLanguageCode in order to send a translation request with enabling |
| // server side auto language detection. |
| std::string source_lang(original_source_lang); |
| if (!TranslateDownloadManager::IsSupportedLanguage(source_lang)) |
| source_lang = std::string(translate::kUnknownLanguageCode); |
| |
| // Capture the translate event if we were triggered from the menu. |
| if (triggered_from_menu) { |
| RecordTranslateEvent( |
| metrics::TranslateEventProto::USER_CONTEXT_MENU_TRANSLATE); |
| } |
| |
| // Trigger the "translating now" UI. |
| translate_client_->ShowTranslateUI( |
| translate::TRANSLATE_STEP_TRANSLATING, source_lang, target_lang, |
| TranslateErrors::NONE, triggered_from_menu); |
| |
| TranslateScript* script = TranslateDownloadManager::GetInstance()->script(); |
| DCHECK(script != nullptr); |
| |
| const std::string& script_data = script->data(); |
| if (!script_data.empty()) { |
| DoTranslatePage(script_data, source_lang, target_lang); |
| return; |
| } |
| |
| // The script is not available yet. Queue that request and query for the |
| // script. Once it is downloaded we'll do the translate. |
| TranslateScript::RequestCallback callback = |
| base::Bind(&TranslateManager::OnTranslateScriptFetchComplete, |
| GetWeakPtr(), source_lang, target_lang); |
| |
| script->Request(callback); |
| } |
| |
| void TranslateManager::RevertTranslation() { |
| // Capture the revert event in the translate metrics |
| RecordTranslateEvent(metrics::TranslateEventProto::USER_REVERT); |
| |
| // Revert the translation. |
| translate_driver_->RevertTranslation(page_seq_no_); |
| language_state_.SetCurrentLanguage(language_state_.original_language()); |
| } |
| |
| void TranslateManager::ReportLanguageDetectionError() { |
| TranslateBrowserMetrics::ReportLanguageDetectionError(); |
| |
| GURL report_error_url = GURL(kReportLanguageDetectionErrorURL); |
| |
| report_error_url = net::AppendQueryParameter( |
| report_error_url, kUrlQueryName, |
| translate_driver_->GetLastCommittedURL().spec()); |
| |
| report_error_url = |
| net::AppendQueryParameter(report_error_url, kSourceLanguageQueryName, |
| language_state_.original_language()); |
| |
| report_error_url = translate::AddHostLocaleToUrl(report_error_url); |
| report_error_url = translate::AddApiKeyToUrl(report_error_url); |
| |
| translate_client_->ShowReportLanguageDetectionErrorUI(report_error_url); |
| } |
| |
| void TranslateManager::DoTranslatePage(const std::string& translate_script, |
| const std::string& source_lang, |
| const std::string& target_lang) { |
| language_state_.set_translation_pending(true); |
| translate_driver_->TranslatePage(page_seq_no_, translate_script, source_lang, |
| target_lang); |
| } |
| |
| // Notifies |g_callback_list_| of translate errors. |
| void TranslateManager::NotifyTranslateError(TranslateErrors::Type error_type) { |
| if (!g_callback_list_ || error_type == TranslateErrors::NONE || |
| translate_driver_->IsIncognito()) { |
| return; |
| } |
| |
| TranslateErrorDetails error_details; |
| error_details.time = base::Time::Now(); |
| error_details.url = translate_driver_->GetLastCommittedURL(); |
| error_details.error = error_type; |
| g_callback_list_->Notify(error_details); |
| } |
| |
| void TranslateManager::PageTranslated(const std::string& source_lang, |
| const std::string& target_lang, |
| TranslateErrors::Type error_type) { |
| if (error_type == TranslateErrors::NONE) |
| language_state_.SetCurrentLanguage(target_lang); |
| |
| language_state_.set_translation_pending(false); |
| language_state_.set_translation_error(error_type != TranslateErrors::NONE); |
| |
| if ((error_type == TranslateErrors::NONE) && |
| source_lang != translate::kUnknownLanguageCode && |
| !TranslateDownloadManager::IsSupportedLanguage(source_lang)) { |
| error_type = TranslateErrors::UNSUPPORTED_LANGUAGE; |
| } |
| |
| // Currently we only want to log any error happens during the translation |
| // script initialization phase such as translation script failed because of |
| // CSP issues (crbug.com/738277). |
| // Note: NotifyTranslateError and ShowTranslateUI will not log the errors. |
| if (error_type == TranslateErrors::INITIALIZATION_ERROR) |
| RecordTranslateEvent(metrics::TranslateEventProto::INITIALIZATION_ERROR); |
| translate_client_->ShowTranslateUI(translate::TRANSLATE_STEP_AFTER_TRANSLATE, |
| source_lang, target_lang, error_type, |
| false); |
| NotifyTranslateError(error_type); |
| } |
| |
| void TranslateManager::OnTranslateScriptFetchComplete( |
| const std::string& source_lang, |
| const std::string& target_lang, |
| bool success, |
| const std::string& data) { |
| if (!translate_driver_->HasCurrentPage()) |
| return; |
| |
| if (success) { |
| // Translate the page. |
| TranslateScript* translate_script = |
| TranslateDownloadManager::GetInstance()->script(); |
| DCHECK(translate_script); |
| DoTranslatePage(translate_script->data(), source_lang, target_lang); |
| } else { |
| translate_client_->ShowTranslateUI( |
| translate::TRANSLATE_STEP_TRANSLATE_ERROR, source_lang, target_lang, |
| TranslateErrors::NETWORK, false); |
| NotifyTranslateError(TranslateErrors::NETWORK); |
| } |
| } |
| |
| // static |
| std::string TranslateManager::GetTargetLanguage( |
| const TranslatePrefs* prefs, |
| language::LanguageModel* language_model, |
| const std::set<std::string>& skipped_languages) { |
| DCHECK(prefs); |
| const std::string& recent_target = prefs->GetRecentTargetLanguage(); |
| |
| // If we've recorded the most recent target language, use that. |
| if (base::FeatureList::IsEnabled(kTranslateRecentTarget) && |
| !recent_target.empty()) { |
| return recent_target; |
| } |
| |
| if (language_model) { |
| std::vector<std::string> language_codes; |
| for (const auto& lang : language_model->GetLanguages()) { |
| std::string lang_code = |
| TranslateDownloadManager::GetLanguageCode(lang.lang_code); |
| translate::ToTranslateLanguageSynonym(&lang_code); |
| if (TranslateDownloadManager::IsSupportedLanguage(lang_code)) |
| language_codes.push_back(lang_code); |
| } |
| // If some languages need to be skipped, move them to the end of the |
| // language vector so that any other eligible language takes priority. |
| MoveSkippedLanguagesToEndIfNecessary(&language_codes, skipped_languages); |
| |
| // Use the first language from the model that translate supports. |
| if (!language_codes.empty()) |
| return language_codes[0]; |
| } else { |
| // Get the browser's user interface language. |
| std::string language = TranslateDownloadManager::GetLanguageCode( |
| TranslateDownloadManager::GetInstance()->application_locale()); |
| // Map 'he', 'nb', 'fil' back to 'iw', 'no', 'tl' |
| translate::ToTranslateLanguageSynonym(&language); |
| if (TranslateDownloadManager::IsSupportedLanguage(language)) |
| return language; |
| |
| // Will translate to the first supported language on the Accepted Language |
| // list or not at all if no such candidate exists. |
| std::vector<std::string> accept_languages_list; |
| prefs->GetLanguageList(&accept_languages_list); |
| for (const auto& lang : accept_languages_list) { |
| std::string lang_code = TranslateDownloadManager::GetLanguageCode(lang); |
| if (TranslateDownloadManager::IsSupportedLanguage(lang_code)) |
| return lang_code; |
| } |
| } |
| |
| return std::string(); |
| } |
| |
| // static |
| std::string TranslateManager::GetTargetLanguage( |
| const TranslatePrefs* prefs, |
| language::LanguageModel* language_model) { |
| return GetTargetLanguage(prefs, language_model, {}); |
| } |
| |
| // static |
| std::string TranslateManager::GetAutoTargetLanguage( |
| const std::string& original_language, |
| TranslatePrefs* translate_prefs) { |
| std::string auto_target_lang; |
| if (translate_prefs->ShouldAutoTranslate(original_language, |
| &auto_target_lang)) { |
| // We need to confirm that the saved target language is still supported. |
| // Also, GetLanguageCode will take care of removing country code if any. |
| auto_target_lang = |
| TranslateDownloadManager::GetLanguageCode(auto_target_lang); |
| if (TranslateDownloadManager::IsSupportedLanguage(auto_target_lang)) |
| return auto_target_lang; |
| } |
| return std::string(); |
| } |
| |
| LanguageState& TranslateManager::GetLanguageState() { |
| return language_state_; |
| } |
| |
| bool TranslateManager::ignore_missing_key_for_testing_ = false; |
| |
| // static |
| void TranslateManager::SetIgnoreMissingKeyForTesting(bool ignore) { |
| ignore_missing_key_for_testing_ = ignore; |
| } |
| |
| void TranslateManager::InitTranslateEvent(const std::string& src_lang, |
| const std::string& dst_lang, |
| const TranslatePrefs& prefs) { |
| translate_event_->Clear(); |
| translate_event_->set_source_language(src_lang); |
| translate_event_->set_target_language(dst_lang); |
| translate_event_->set_country(prefs.GetCountry()); |
| translate_event_->set_accept_count( |
| prefs.GetTranslationAcceptedCount(src_lang)); |
| translate_event_->set_decline_count( |
| prefs.GetTranslationDeniedCount(src_lang)); |
| translate_event_->set_ignore_count( |
| prefs.GetTranslationIgnoredCount(src_lang)); |
| translate_event_->set_ranker_response( |
| metrics::TranslateEventProto::NOT_QUERIED); |
| translate_event_->set_event_type(metrics::TranslateEventProto::UNKNOWN); |
| // TODO(rogerm): Populate the language list. |
| } |
| |
| void TranslateManager::RecordTranslateEvent(int event_type) { |
| translate_ranker_->RecordTranslateEvent( |
| event_type, translate_driver_->GetVisibleURL(), translate_event_.get()); |
| translate_client_->RecordTranslateEvent(*translate_event_); |
| } |
| |
| bool TranslateManager::ShouldOverrideDecision(int event_type) { |
| return translate_ranker_->ShouldOverrideDecision( |
| event_type, translate_driver_->GetVisibleURL(), translate_event_.get()); |
| } |
| |
| bool TranslateManager::ShouldSuppressBubbleUI( |
| bool triggered_from_menu, |
| const std::string& source_language) { |
| // Suppress the UI if the user navigates to a page with |
| // the same language as the previous page. In the new UI, |
| // continue offering translation after the user navigates |
| // to another page. |
| if (!language_state_.HasLanguageChanged() && |
| !ShouldOverrideDecision( |
| metrics::TranslateEventProto::MATCHES_PREVIOUS_LANGUAGE)) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics:: |
| INITIATION_STATUS_ABORTED_BY_MATCHES_PREVIOUS_LANGUAGE); |
| return true; |
| } |
| |
| // Suppress the UI if the user denied translation for this language |
| // too often. |
| if (!triggered_from_menu && |
| translate_client_->GetTranslatePrefs()->IsTooOftenDenied( |
| source_language) && |
| !ShouldOverrideDecision( |
| metrics::TranslateEventProto::LANGUAGE_DISABLED_BY_AUTO_BLACKLIST)) { |
| TranslateBrowserMetrics::ReportInitiationStatus( |
| TranslateBrowserMetrics::INITIATION_STATUS_ABORTED_BY_TOO_OFTEN_DENIED); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void TranslateManager::AddTargetLanguageToAcceptLanguages( |
| const std::string& target_language_code) { |
| auto prefs = translate_client_->GetTranslatePrefs(); |
| std::vector<std::string> languages; |
| prefs->GetLanguageList(&languages); |
| if (!base::ContainsValue(languages, target_language_code)) { |
| prefs->AddToLanguageList(target_language_code, /*force_blocked=*/false); |
| } |
| } |
| |
| } // namespace translate |