| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/translate/core/browser/translate_manager.h" | 5 #include "components/translate/core/browser/translate_manager.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/memory/ptr_util.h" |
| 11 #include "base/metrics/field_trial.h" | 12 #include "base/metrics/field_trial.h" |
| 12 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 13 #include "base/profiler/scoped_tracker.h" | 14 #include "base/profiler/scoped_tracker.h" |
| 14 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_split.h" | 16 #include "base/strings/string_split.h" |
| 16 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 17 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 19 #include "components/metrics/proto/translate_event.pb.h" |
| 18 #include "components/prefs/pref_service.h" | 20 #include "components/prefs/pref_service.h" |
| 19 #include "components/translate/core/browser/language_state.h" | 21 #include "components/translate/core/browser/language_state.h" |
| 20 #include "components/translate/core/browser/page_translated_details.h" | 22 #include "components/translate/core/browser/page_translated_details.h" |
| 21 #include "components/translate/core/browser/translate_accept_languages.h" | 23 #include "components/translate/core/browser/translate_accept_languages.h" |
| 22 #include "components/translate/core/browser/translate_browser_metrics.h" | 24 #include "components/translate/core/browser/translate_browser_metrics.h" |
| 23 #include "components/translate/core/browser/translate_client.h" | 25 #include "components/translate/core/browser/translate_client.h" |
| 24 #include "components/translate/core/browser/translate_download_manager.h" | 26 #include "components/translate/core/browser/translate_download_manager.h" |
| 25 #include "components/translate/core/browser/translate_driver.h" | 27 #include "components/translate/core/browser/translate_driver.h" |
| 26 #include "components/translate/core/browser/translate_error_details.h" | 28 #include "components/translate/core/browser/translate_error_details.h" |
| 27 #include "components/translate/core/browser/translate_experiment.h" | 29 #include "components/translate/core/browser/translate_experiment.h" |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 } | 130 } |
| 129 | 131 |
| 130 TranslateManager::TranslateManager( | 132 TranslateManager::TranslateManager( |
| 131 TranslateClient* translate_client, | 133 TranslateClient* translate_client, |
| 132 const std::string& accept_languages_pref_name) | 134 const std::string& accept_languages_pref_name) |
| 133 : page_seq_no_(0), | 135 : page_seq_no_(0), |
| 134 accept_languages_pref_name_(accept_languages_pref_name), | 136 accept_languages_pref_name_(accept_languages_pref_name), |
| 135 translate_client_(translate_client), | 137 translate_client_(translate_client), |
| 136 translate_driver_(translate_client_->GetTranslateDriver()), | 138 translate_driver_(translate_client_->GetTranslateDriver()), |
| 137 language_state_(translate_driver_), | 139 language_state_(translate_driver_), |
| 140 translate_event_(base::MakeUnique<metrics::TranslateEventProto>()), |
| 138 weak_method_factory_(this) { | 141 weak_method_factory_(this) { |
| 139 if (TranslateRanker::IsEnabled()) | 142 if (TranslateRanker::IsEnabled()) |
| 140 TranslateRanker::GetInstance()->FetchModelData(); // Asynchronous. | 143 TranslateRanker::GetInstance()->FetchModelData(); // Asynchronous. |
| 141 } | 144 } |
| 142 | 145 |
| 143 base::WeakPtr<TranslateManager> TranslateManager::GetWeakPtr() { | 146 base::WeakPtr<TranslateManager> TranslateManager::GetWeakPtr() { |
| 144 return weak_method_factory_.GetWeakPtr(); | 147 return weak_method_factory_.GetWeakPtr(); |
| 145 } | 148 } |
| 146 | 149 |
| 147 void TranslateManager::InitiateTranslation(const std::string& page_lang) { | 150 void TranslateManager::InitiateTranslation(const std::string& page_lang) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 return; | 214 return; |
| 212 } | 215 } |
| 213 | 216 |
| 214 std::unique_ptr<TranslatePrefs> translate_prefs( | 217 std::unique_ptr<TranslatePrefs> translate_prefs( |
| 215 translate_client_->GetTranslatePrefs()); | 218 translate_client_->GetTranslatePrefs()); |
| 216 | 219 |
| 217 std::string target_lang = GetTargetLanguage(translate_prefs.get()); | 220 std::string target_lang = GetTargetLanguage(translate_prefs.get()); |
| 218 std::string language_code = | 221 std::string language_code = |
| 219 TranslateDownloadManager::GetLanguageCode(page_lang); | 222 TranslateDownloadManager::GetLanguageCode(page_lang); |
| 220 | 223 |
| 224 InitTranslateEvent(language_code, target_lang, *translate_prefs); |
| 225 |
| 221 // Don't translate similar languages (ex: en-US to en). | 226 // Don't translate similar languages (ex: en-US to en). |
| 222 if (language_code == target_lang) { | 227 if (language_code == target_lang) { |
| 223 TranslateBrowserMetrics::ReportInitiationStatus( | 228 TranslateBrowserMetrics::ReportInitiationStatus( |
| 224 TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES); | 229 TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES); |
| 225 return; | 230 return; |
| 226 } | 231 } |
| 227 | 232 |
| 228 // Nothing to do if either the language Chrome is in or the language of the | 233 // Nothing to do if either the language Chrome is in or the language of the |
| 229 // page is not supported by the translation server. | 234 // page is not supported by the translation server. |
| 230 if (target_lang.empty() || | 235 if (target_lang.empty() || |
| 231 !TranslateDownloadManager::IsSupportedLanguage(language_code)) { | 236 !TranslateDownloadManager::IsSupportedLanguage(language_code)) { |
| 232 TranslateBrowserMetrics::ReportInitiationStatus( | 237 TranslateBrowserMetrics::ReportInitiationStatus( |
| 233 TranslateBrowserMetrics::INITIATION_STATUS_LANGUAGE_IS_NOT_SUPPORTED); | 238 TranslateBrowserMetrics::INITIATION_STATUS_LANGUAGE_IS_NOT_SUPPORTED); |
| 234 TranslateBrowserMetrics::ReportUnsupportedLanguageAtInitiation( | 239 TranslateBrowserMetrics::ReportUnsupportedLanguageAtInitiation( |
| 235 language_code); | 240 language_code); |
| 241 RecordTranslateEvent(metrics::TranslateEventProto::UNSUPPORTED_LANGUAGE); |
| 236 return; | 242 return; |
| 237 } | 243 } |
| 238 | 244 |
| 239 TranslateAcceptLanguages* accept_languages = | 245 TranslateAcceptLanguages* accept_languages = |
| 240 translate_client_->GetTranslateAcceptLanguages(); | 246 translate_client_->GetTranslateAcceptLanguages(); |
| 241 // Don't translate any user black-listed languages. | 247 // Don't translate any user black-listed languages. |
| 242 if (!translate_prefs->CanTranslateLanguage(accept_languages, | 248 if (!translate_prefs->CanTranslateLanguage(accept_languages, |
| 243 language_code)) { | 249 language_code)) { |
| 244 TranslateBrowserMetrics::ReportInitiationStatus( | 250 TranslateBrowserMetrics::ReportInitiationStatus( |
| 245 TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_CONFIG); | 251 TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_CONFIG); |
| 252 RecordTranslateEvent( |
| 253 metrics::TranslateEventProto::LANGUAGE_DISABLED_BY_USER_CONFIG); |
| 246 return; | 254 return; |
| 247 } | 255 } |
| 248 | 256 |
| 249 // Don't translate any user black-listed URLs. | 257 // Don't translate any user black-listed URLs. |
| 250 if (translate_prefs->IsSiteBlacklisted(page_url.HostNoBrackets())) { | 258 if (translate_prefs->IsSiteBlacklisted(page_url.HostNoBrackets())) { |
| 251 TranslateBrowserMetrics::ReportInitiationStatus( | 259 TranslateBrowserMetrics::ReportInitiationStatus( |
| 252 TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_CONFIG); | 260 TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_CONFIG); |
| 261 RecordTranslateEvent( |
| 262 metrics::TranslateEventProto::URL_DISABLED_BY_USER_CONFIG); |
| 253 return; | 263 return; |
| 254 } | 264 } |
| 255 | 265 |
| 256 // If the user has previously selected "always translate" for this language we | 266 // If the user has previously selected "always translate" for this language we |
| 257 // automatically translate. Note that in incognito mode we disable that | 267 // automatically translate. Note that in incognito mode we disable that |
| 258 // feature; the user will get an infobar, so they can control whether the | 268 // feature; the user will get an infobar, so they can control whether the |
| 259 // page's text is sent to the translate server. | 269 // page's text is sent to the translate server. |
| 260 if (!translate_driver_->IsOffTheRecord()) { | 270 if (!translate_driver_->IsOffTheRecord()) { |
| 261 std::string auto_target_lang = | 271 std::string auto_target_lang = |
| 262 GetAutoTargetLanguage(language_code, translate_prefs.get()); | 272 GetAutoTargetLanguage(language_code, translate_prefs.get()); |
| 263 if (!auto_target_lang.empty()) { | 273 if (!auto_target_lang.empty()) { |
| 264 TranslateBrowserMetrics::ReportInitiationStatus( | 274 TranslateBrowserMetrics::ReportInitiationStatus( |
| 265 TranslateBrowserMetrics::INITIATION_STATUS_AUTO_BY_CONFIG); | 275 TranslateBrowserMetrics::INITIATION_STATUS_AUTO_BY_CONFIG); |
| 276 translate_event_->set_modified_target_language(auto_target_lang); |
| 277 RecordTranslateEvent( |
| 278 metrics::TranslateEventProto::AUTOMATICALLY_TRANSLATED); |
| 266 TranslatePage(language_code, auto_target_lang, false); | 279 TranslatePage(language_code, auto_target_lang, false); |
| 267 return; | 280 return; |
| 268 } | 281 } |
| 269 } | 282 } |
| 270 | 283 |
| 271 std::string auto_translate_to = language_state_.AutoTranslateTo(); | 284 std::string auto_translate_to = language_state_.AutoTranslateTo(); |
| 272 if (!auto_translate_to.empty()) { | 285 if (!auto_translate_to.empty()) { |
| 273 // This page was navigated through a click from a translated page. | 286 // This page was navigated through a click from a translated page. |
| 274 TranslateBrowserMetrics::ReportInitiationStatus( | 287 TranslateBrowserMetrics::ReportInitiationStatus( |
| 275 TranslateBrowserMetrics::INITIATION_STATUS_AUTO_BY_LINK); | 288 TranslateBrowserMetrics::INITIATION_STATUS_AUTO_BY_LINK); |
| 289 translate_event_->set_modified_target_language(auto_translate_to); |
| 290 RecordTranslateEvent( |
| 291 metrics::TranslateEventProto::AUTOMATICALLY_TRANSLATED); |
| 276 TranslatePage(language_code, auto_translate_to, false); | 292 TranslatePage(language_code, auto_translate_to, false); |
| 277 return; | 293 return; |
| 278 } | 294 } |
| 279 | 295 |
| 280 if (LanguageInULP(language_code)) { | 296 if (LanguageInULP(language_code)) { |
| 281 TranslateBrowserMetrics::ReportInitiationStatus( | 297 TranslateBrowserMetrics::ReportInitiationStatus( |
| 282 TranslateBrowserMetrics::INITIATION_STATUS_LANGUAGE_IN_ULP); | 298 TranslateBrowserMetrics::INITIATION_STATUS_LANGUAGE_IN_ULP); |
| 299 RecordTranslateEvent(metrics::TranslateEventProto::DISABLED_BY_PREF); |
| 283 return; | 300 return; |
| 284 } | 301 } |
| 285 | 302 |
| 286 if (TranslateRanker::IsEnabled()) { | 303 if (TranslateRanker::IsEnabled()) { |
| 287 if (!TranslateRanker::GetInstance()->ShouldOfferTranslation( | 304 TranslateRanker* translate_ranker = TranslateRanker::GetInstance(); |
| 288 *translate_client_->GetTranslatePrefs(), language_code, | 305 bool should_offer_translation = translate_ranker->ShouldOfferTranslation( |
| 289 target_lang)) { | 306 *translate_prefs, language_code, target_lang); |
| 307 translate_event_->set_ranker_request_timestamp_sec( |
| 308 (base::TimeTicks::Now() - base::TimeTicks()).InSeconds()); |
| 309 translate_event_->set_ranker_version(translate_ranker->GetModelVersion()); |
| 310 translate_event_->set_ranker_response( |
| 311 should_offer_translation ? metrics::TranslateEventProto::SHOW |
| 312 : metrics::TranslateEventProto::DONT_SHOW); |
| 313 if (!should_offer_translation && TranslateRanker::IsEnforcementEnabled()) { |
| 290 TranslateBrowserMetrics::ReportInitiationStatus( | 314 TranslateBrowserMetrics::ReportInitiationStatus( |
| 291 TranslateBrowserMetrics::INITIATION_STATUS_ABORTED_BY_RANKER); | 315 TranslateBrowserMetrics::INITIATION_STATUS_ABORTED_BY_RANKER); |
| 316 RecordTranslateEvent(metrics::TranslateEventProto::DISABLED_BY_RANKER); |
| 292 return; | 317 return; |
| 293 } | 318 } |
| 294 } | 319 } |
| 295 | 320 |
| 296 TranslateBrowserMetrics::ReportInitiationStatus( | 321 TranslateBrowserMetrics::ReportInitiationStatus( |
| 297 TranslateBrowserMetrics::INITIATION_STATUS_SHOW_INFOBAR); | 322 TranslateBrowserMetrics::INITIATION_STATUS_SHOW_INFOBAR); |
| 298 | 323 |
| 299 // Prompts the user if they want the page translated. | 324 // Prompts the user if they want the page translated. |
| 300 translate_client_->ShowTranslateUI(translate::TRANSLATE_STEP_BEFORE_TRANSLATE, | 325 translate_client_->ShowTranslateUI(translate::TRANSLATE_STEP_BEFORE_TRANSLATE, |
| 301 language_code, | 326 language_code, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 } | 359 } |
| 335 | 360 |
| 336 // Translation can be kicked by context menu against unsupported languages. | 361 // Translation can be kicked by context menu against unsupported languages. |
| 337 // Unsupported language strings should be replaced with | 362 // Unsupported language strings should be replaced with |
| 338 // kUnknownLanguageCode in order to send a translation request with enabling | 363 // kUnknownLanguageCode in order to send a translation request with enabling |
| 339 // server side auto language detection. | 364 // server side auto language detection. |
| 340 std::string source_lang(original_source_lang); | 365 std::string source_lang(original_source_lang); |
| 341 if (!TranslateDownloadManager::IsSupportedLanguage(source_lang)) | 366 if (!TranslateDownloadManager::IsSupportedLanguage(source_lang)) |
| 342 source_lang = std::string(translate::kUnknownLanguageCode); | 367 source_lang = std::string(translate::kUnknownLanguageCode); |
| 343 | 368 |
| 369 // Capture the translate event if we were triggered from the menu. |
| 370 if (triggered_from_menu) { |
| 371 RecordTranslateEvent( |
| 372 metrics::TranslateEventProto::USER_CONTEXT_MENU_TRANSLATE); |
| 373 } |
| 374 |
| 375 // Trigger the "translating now" UI. |
| 344 translate_client_->ShowTranslateUI(translate::TRANSLATE_STEP_TRANSLATING, | 376 translate_client_->ShowTranslateUI(translate::TRANSLATE_STEP_TRANSLATING, |
| 345 source_lang, | 377 source_lang, |
| 346 target_lang, | 378 target_lang, |
| 347 TranslateErrors::NONE, | 379 TranslateErrors::NONE, |
| 348 triggered_from_menu); | 380 triggered_from_menu); |
| 349 | 381 |
| 350 TranslateScript* script = TranslateDownloadManager::GetInstance()->script(); | 382 TranslateScript* script = TranslateDownloadManager::GetInstance()->script(); |
| 351 DCHECK(script != NULL); | 383 DCHECK(script != NULL); |
| 352 | 384 |
| 353 const std::string& script_data = script->data(); | 385 const std::string& script_data = script->data(); |
| 354 if (!script_data.empty()) { | 386 if (!script_data.empty()) { |
| 355 DoTranslatePage(script_data, source_lang, target_lang); | 387 DoTranslatePage(script_data, source_lang, target_lang); |
| 356 return; | 388 return; |
| 357 } | 389 } |
| 358 | 390 |
| 359 // The script is not available yet. Queue that request and query for the | 391 // The script is not available yet. Queue that request and query for the |
| 360 // script. Once it is downloaded we'll do the translate. | 392 // script. Once it is downloaded we'll do the translate. |
| 361 TranslateScript::RequestCallback callback = base::Bind( | 393 TranslateScript::RequestCallback callback = base::Bind( |
| 362 &TranslateManager::OnTranslateScriptFetchComplete, GetWeakPtr(), | 394 &TranslateManager::OnTranslateScriptFetchComplete, GetWeakPtr(), |
| 363 source_lang, target_lang); | 395 source_lang, target_lang); |
| 364 | 396 |
| 365 script->Request(callback); | 397 script->Request(callback); |
| 366 } | 398 } |
| 367 | 399 |
| 368 void TranslateManager::RevertTranslation() { | 400 void TranslateManager::RevertTranslation() { |
| 401 // Capture the revert event in the translate metrics |
| 402 RecordTranslateEvent(metrics::TranslateEventProto::USER_REVERT); |
| 403 |
| 404 // Revert the translation. |
| 369 translate_driver_->RevertTranslation(page_seq_no_); | 405 translate_driver_->RevertTranslation(page_seq_no_); |
| 370 language_state_.SetCurrentLanguage(language_state_.original_language()); | 406 language_state_.SetCurrentLanguage(language_state_.original_language()); |
| 371 } | 407 } |
| 372 | 408 |
| 373 void TranslateManager::ReportLanguageDetectionError() { | 409 void TranslateManager::ReportLanguageDetectionError() { |
| 374 TranslateBrowserMetrics::ReportLanguageDetectionError(); | 410 TranslateBrowserMetrics::ReportLanguageDetectionError(); |
| 375 | 411 |
| 376 GURL report_error_url = GURL(kReportLanguageDetectionErrorURL); | 412 GURL report_error_url = GURL(kReportLanguageDetectionErrorURL); |
| 377 | 413 |
| 378 report_error_url = net::AppendQueryParameter( | 414 report_error_url = net::AppendQueryParameter( |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 return language_state_; | 570 return language_state_; |
| 535 } | 571 } |
| 536 | 572 |
| 537 bool TranslateManager::ignore_missing_key_for_testing_ = false; | 573 bool TranslateManager::ignore_missing_key_for_testing_ = false; |
| 538 | 574 |
| 539 // static | 575 // static |
| 540 void TranslateManager::SetIgnoreMissingKeyForTesting(bool ignore) { | 576 void TranslateManager::SetIgnoreMissingKeyForTesting(bool ignore) { |
| 541 ignore_missing_key_for_testing_ = ignore; | 577 ignore_missing_key_for_testing_ = ignore; |
| 542 } | 578 } |
| 543 | 579 |
| 580 void TranslateManager::InitTranslateEvent(const std::string& src_lang, |
| 581 const std::string& dst_lang, |
| 582 const TranslatePrefs& prefs) { |
| 583 translate_event_->Clear(); |
| 584 translate_event_->set_source_language(src_lang); |
| 585 translate_event_->set_target_language(dst_lang); |
| 586 translate_event_->set_accept_count( |
| 587 prefs.GetTranslationAcceptedCount(src_lang)); |
| 588 translate_event_->set_decline_count( |
| 589 prefs.GetTranslationDeniedCount(src_lang)); |
| 590 translate_event_->set_ignore_count( |
| 591 prefs.GetTranslationIgnoredCount(src_lang)); |
| 592 translate_event_->set_ranker_response( |
| 593 metrics::TranslateEventProto::NOT_QUERIED); |
| 594 translate_event_->set_event_type(metrics::TranslateEventProto::UNKNOWN); |
| 595 // TODO(rogerm): Populate the language list. |
| 596 } |
| 597 |
| 598 void TranslateManager::RecordTranslateEvent(int event_type) { |
| 599 DCHECK(metrics::TranslateEventProto::EventType_IsValid(event_type)); |
| 600 translate_event_->set_event_type( |
| 601 static_cast<metrics::TranslateEventProto::EventType>(event_type)); |
| 602 translate_event_->set_event_timestamp_sec( |
| 603 (base::TimeTicks::Now() - base::TimeTicks()).InSeconds()); |
| 604 TranslateRanker::GetInstance()->RecordTranslateEvent(*translate_event_); |
| 605 } |
| 606 |
| 544 } // namespace translate | 607 } // namespace translate |
| OLD | NEW |