// Copyright 2013 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 "chrome/browser/ui/webui/translate_internals/translate_internals_handler.h" #include <map> #include <vector> #include "base/bind.h" #include "base/bind_helpers.h" #include "base/prefs/pref_service.h" #include "base/values.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/translate/chrome_translate_client.h" #include "chrome/browser/translate/translate_service.h" #include "chrome/common/pref_names.h" #include "components/translate/core/browser/translate_download_manager.h" #include "components/translate/core/browser/translate_error_details.h" #include "components/translate/core/browser/translate_event_details.h" #include "components/translate/core/browser/translate_prefs.h" #include "components/translate/core/common/language_detection_details.h" #include "components/translate/core/common/translate_pref_names.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" TranslateInternalsHandler::TranslateInternalsHandler() { notification_registrar_.Add(this, chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, content::NotificationService::AllSources()); error_subscription_ = TranslateManager::RegisterTranslateErrorCallback( base::Bind(&TranslateInternalsHandler::OnTranslateError, base::Unretained(this))); TranslateLanguageList* language_list = TranslateDownloadManager::GetInstance()->language_list(); if (!language_list) { NOTREACHED(); return; } event_subscription_ = language_list->RegisterEventCallback(base::Bind( &TranslateInternalsHandler::OnTranslateEvent, base::Unretained(this))); } TranslateInternalsHandler::~TranslateInternalsHandler() { // |event_subscription_| and |error_subscription_| are deleted automatically // and un-register the callbacks automatically. } void TranslateInternalsHandler::RegisterMessages() { web_ui()->RegisterMessageCallback("removePrefItem", base::Bind( &TranslateInternalsHandler::OnRemovePrefItem, base::Unretained(this))); web_ui()->RegisterMessageCallback("requestInfo", base::Bind( &TranslateInternalsHandler::OnRequestInfo, base::Unretained(this))); } void TranslateInternalsHandler::Observe( int type, const content::NotificationSource& source, const content::NotificationDetails& details) { DCHECK_EQ(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, type); const LanguageDetectionDetails* language_detection_details = content::Details<const LanguageDetectionDetails>(details).ptr(); content::WebContents* web_contents = content::Source<content::WebContents>(source).ptr(); if (web_contents->GetBrowserContext()->IsOffTheRecord() || !TranslateService::IsTranslatableURL(language_detection_details->url)) { return; } base::DictionaryValue dict; dict.Set( "time", new base::FundamentalValue(language_detection_details->time.ToJsTime())); dict.Set("url", new base::StringValue(language_detection_details->url.spec())); dict.Set("content_language", new base::StringValue(language_detection_details->content_language)); dict.Set("cld_language", new base::StringValue(language_detection_details->cld_language)); dict.Set( "is_cld_reliable", new base::FundamentalValue(language_detection_details->is_cld_reliable)); dict.Set( "html_root_language", new base::StringValue(language_detection_details->html_root_language)); dict.Set("adopted_language", new base::StringValue(language_detection_details->adopted_language)); dict.Set("content", new base::StringValue(language_detection_details->contents)); SendMessageToJs("languageDetectionInfoAdded", dict); } void TranslateInternalsHandler::OnTranslateError( const TranslateErrorDetails& details) { base::DictionaryValue dict; dict.Set("time", new base::FundamentalValue(details.time.ToJsTime())); dict.Set("url", new base::StringValue(details.url.spec())); dict.Set("error", new base::FundamentalValue(details.error)); SendMessageToJs("translateErrorDetailsAdded", dict); } void TranslateInternalsHandler::OnTranslateEvent( const TranslateEventDetails& details) { base::DictionaryValue dict; dict.Set("time", new base::FundamentalValue(details.time.ToJsTime())); dict.Set("filename", new base::StringValue(details.filename)); dict.Set("line", new base::FundamentalValue(details.line)); dict.Set("message", new base::StringValue(details.message)); SendMessageToJs("translateEventDetailsAdded", dict); } void TranslateInternalsHandler::OnRemovePrefItem(const base::ListValue* args) { content::WebContents* web_contents = web_ui()->GetWebContents(); Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); PrefService* prefs = profile->GetOriginalProfile()->GetPrefs(); scoped_ptr<TranslatePrefs> translate_prefs( ChromeTranslateClient::CreateTranslatePrefs(prefs)); std::string pref_name; if (!args->GetString(0, &pref_name)) return; if (pref_name == "blocked_languages") { std::string language; if (!args->GetString(1, &language)) return; translate_prefs->UnblockLanguage(language); } else if (pref_name == "language_blacklist") { std::string language; if (!args->GetString(1, &language)) return; translate_prefs->RemoveLanguageFromLegacyBlacklist(language); } else if (pref_name == "site_blacklist") { std::string site; if (!args->GetString(1, &site)) return; translate_prefs->RemoveSiteFromBlacklist(site); } else if (pref_name == "whitelists") { std::string from, to; if (!args->GetString(1, &from)) return; if (!args->GetString(2, &to)) return; translate_prefs->RemoveLanguagePairFromWhitelist(from, to); } else if (pref_name == "too_often_denied") { translate_prefs->ResetDenialState(); } else { return; } SendPrefsToJs(); } void TranslateInternalsHandler::OnRequestInfo(const base::ListValue* /*args*/) { SendPrefsToJs(); SendSupportedLanguagesToJs(); } void TranslateInternalsHandler::SendMessageToJs(const std::string& message, const base::Value& value) { const char func[] = "cr.translateInternals.messageHandler"; base::StringValue message_data(message); web_ui()->CallJavascriptFunction(func, message_data, value); } void TranslateInternalsHandler::SendPrefsToJs() { content::WebContents* web_contents = web_ui()->GetWebContents(); Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); PrefService* prefs = profile->GetOriginalProfile()->GetPrefs(); base::DictionaryValue dict; std::vector<std::string> keys; keys.push_back(prefs::kEnableTranslate); keys.push_back(TranslatePrefs::kPrefTranslateBlockedLanguages); keys.push_back(TranslatePrefs::kPrefTranslateLanguageBlacklist); keys.push_back(TranslatePrefs::kPrefTranslateSiteBlacklist); keys.push_back(TranslatePrefs::kPrefTranslateWhitelists); keys.push_back(TranslatePrefs::kPrefTranslateDeniedCount); keys.push_back(TranslatePrefs::kPrefTranslateAcceptedCount); keys.push_back(TranslatePrefs::kPrefTranslateLastDeniedTime); keys.push_back(TranslatePrefs::kPrefTranslateTooOftenDenied); for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it) { const std::string& key = *it; const PrefService::Preference* pref = prefs->FindPreference(key.c_str()); if (pref) dict.Set(key, pref->GetValue()->DeepCopy()); } SendMessageToJs("prefsUpdated", dict); } void TranslateInternalsHandler::SendSupportedLanguagesToJs() { base::DictionaryValue dict; std::vector<std::string> languages; TranslateDownloadManager::GetSupportedLanguages(&languages); base::Time last_updated = TranslateDownloadManager::GetSupportedLanguagesLastUpdated(); base::ListValue* languages_list = new base::ListValue(); base::ListValue* alpha_languages_list = new base::ListValue(); for (std::vector<std::string>::iterator it = languages.begin(); it != languages.end(); ++it) { const std::string& lang = *it; languages_list->Append(new base::StringValue(lang)); if (TranslateDownloadManager::IsAlphaLanguage(lang)) alpha_languages_list->Append(new base::StringValue(lang)); } dict.Set("languages", languages_list); dict.Set("alpha_languages", alpha_languages_list); dict.Set("last_updated", new base::FundamentalValue(last_updated.ToJsTime())); SendMessageToJs("supportedLanguagesUpdated", dict); }