1// Copyright 2013 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#include "chrome/browser/ui/webui/translate_internals/translate_internals_handler.h" 6 7#include <map> 8#include <vector> 9 10#include "base/bind.h" 11#include "base/bind_helpers.h" 12#include "base/prefs/pref_service.h" 13#include "base/values.h" 14#include "chrome/browser/chrome_notification_types.h" 15#include "chrome/browser/profiles/profile.h" 16#include "chrome/browser/translate/chrome_translate_client.h" 17#include "chrome/browser/translate/translate_service.h" 18#include "chrome/common/pref_names.h" 19#include "components/translate/core/browser/translate_download_manager.h" 20#include "components/translate/core/browser/translate_error_details.h" 21#include "components/translate/core/browser/translate_event_details.h" 22#include "components/translate/core/browser/translate_prefs.h" 23#include "components/translate/core/common/language_detection_details.h" 24#include "components/translate/core/common/translate_pref_names.h" 25#include "content/public/browser/notification_details.h" 26#include "content/public/browser/notification_service.h" 27#include "content/public/browser/notification_source.h" 28#include "content/public/browser/notification_types.h" 29#include "content/public/browser/web_contents.h" 30#include "content/public/browser/web_ui.h" 31 32TranslateInternalsHandler::TranslateInternalsHandler() { 33 notification_registrar_.Add(this, 34 chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, 35 content::NotificationService::AllSources()); 36 37 error_subscription_ = 38 translate::TranslateManager::RegisterTranslateErrorCallback( 39 base::Bind(&TranslateInternalsHandler::OnTranslateError, 40 base::Unretained(this))); 41 42 translate::TranslateLanguageList* language_list = 43 translate::TranslateDownloadManager::GetInstance()->language_list(); 44 if (!language_list) { 45 NOTREACHED(); 46 return; 47 } 48 49 event_subscription_ = language_list->RegisterEventCallback(base::Bind( 50 &TranslateInternalsHandler::OnTranslateEvent, base::Unretained(this))); 51} 52 53TranslateInternalsHandler::~TranslateInternalsHandler() { 54 // |event_subscription_| and |error_subscription_| are deleted automatically 55 // and un-register the callbacks automatically. 56} 57 58void TranslateInternalsHandler::RegisterMessages() { 59 web_ui()->RegisterMessageCallback("removePrefItem", base::Bind( 60 &TranslateInternalsHandler::OnRemovePrefItem, base::Unretained(this))); 61 web_ui()->RegisterMessageCallback("requestInfo", base::Bind( 62 &TranslateInternalsHandler::OnRequestInfo, base::Unretained(this))); 63} 64 65void TranslateInternalsHandler::Observe( 66 int type, 67 const content::NotificationSource& source, 68 const content::NotificationDetails& details) { 69 DCHECK_EQ(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, type); 70 const translate::LanguageDetectionDetails* language_detection_details = 71 content::Details<const translate::LanguageDetectionDetails>(details) 72 .ptr(); 73 content::WebContents* web_contents = 74 content::Source<content::WebContents>(source).ptr(); 75 76 if (web_contents->GetBrowserContext()->IsOffTheRecord() || 77 !TranslateService::IsTranslatableURL(language_detection_details->url)) { 78 return; 79 } 80 81 base::DictionaryValue dict; 82 dict.Set( 83 "time", 84 new base::FundamentalValue(language_detection_details->time.ToJsTime())); 85 dict.Set("url", 86 new base::StringValue(language_detection_details->url.spec())); 87 dict.Set("content_language", 88 new base::StringValue(language_detection_details->content_language)); 89 dict.Set("cld_language", 90 new base::StringValue(language_detection_details->cld_language)); 91 dict.Set( 92 "is_cld_reliable", 93 new base::FundamentalValue(language_detection_details->is_cld_reliable)); 94 dict.Set( 95 "html_root_language", 96 new base::StringValue(language_detection_details->html_root_language)); 97 dict.Set("adopted_language", 98 new base::StringValue(language_detection_details->adopted_language)); 99 dict.Set("content", 100 new base::StringValue(language_detection_details->contents)); 101 SendMessageToJs("languageDetectionInfoAdded", dict); 102} 103 104void TranslateInternalsHandler::OnTranslateError( 105 const translate::TranslateErrorDetails& details) { 106 base::DictionaryValue dict; 107 dict.Set("time", 108 new base::FundamentalValue(details.time.ToJsTime())); 109 dict.Set("url", 110 new base::StringValue(details.url.spec())); 111 dict.Set("error", 112 new base::FundamentalValue(details.error)); 113 SendMessageToJs("translateErrorDetailsAdded", dict); 114} 115 116void TranslateInternalsHandler::OnTranslateEvent( 117 const translate::TranslateEventDetails& details) { 118 base::DictionaryValue dict; 119 dict.Set("time", new base::FundamentalValue(details.time.ToJsTime())); 120 dict.Set("filename", new base::StringValue(details.filename)); 121 dict.Set("line", new base::FundamentalValue(details.line)); 122 dict.Set("message", new base::StringValue(details.message)); 123 SendMessageToJs("translateEventDetailsAdded", dict); 124} 125 126void TranslateInternalsHandler::OnRemovePrefItem(const base::ListValue* args) { 127 content::WebContents* web_contents = web_ui()->GetWebContents(); 128 Profile* profile = 129 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 130 PrefService* prefs = profile->GetOriginalProfile()->GetPrefs(); 131 scoped_ptr<translate::TranslatePrefs> translate_prefs( 132 ChromeTranslateClient::CreateTranslatePrefs(prefs)); 133 134 std::string pref_name; 135 if (!args->GetString(0, &pref_name)) 136 return; 137 138 if (pref_name == "blocked_languages") { 139 std::string language; 140 if (!args->GetString(1, &language)) 141 return; 142 translate_prefs->UnblockLanguage(language); 143 } else if (pref_name == "language_blacklist") { 144 std::string language; 145 if (!args->GetString(1, &language)) 146 return; 147 translate_prefs->RemoveLanguageFromLegacyBlacklist(language); 148 } else if (pref_name == "site_blacklist") { 149 std::string site; 150 if (!args->GetString(1, &site)) 151 return; 152 translate_prefs->RemoveSiteFromBlacklist(site); 153 } else if (pref_name == "whitelists") { 154 std::string from, to; 155 if (!args->GetString(1, &from)) 156 return; 157 if (!args->GetString(2, &to)) 158 return; 159 translate_prefs->RemoveLanguagePairFromWhitelist(from, to); 160 } else if (pref_name == "too_often_denied") { 161 translate_prefs->ResetDenialState(); 162 } else { 163 return; 164 } 165 166 SendPrefsToJs(); 167} 168 169void TranslateInternalsHandler::OnRequestInfo(const base::ListValue* /*args*/) { 170 SendPrefsToJs(); 171 SendSupportedLanguagesToJs(); 172} 173 174void TranslateInternalsHandler::SendMessageToJs(const std::string& message, 175 const base::Value& value) { 176 const char func[] = "cr.translateInternals.messageHandler"; 177 base::StringValue message_data(message); 178 web_ui()->CallJavascriptFunction(func, message_data, value); 179} 180 181void TranslateInternalsHandler::SendPrefsToJs() { 182 content::WebContents* web_contents = web_ui()->GetWebContents(); 183 Profile* profile = 184 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 185 PrefService* prefs = profile->GetOriginalProfile()->GetPrefs(); 186 187 base::DictionaryValue dict; 188 189 std::vector<std::string> keys; 190 keys.push_back(prefs::kEnableTranslate); 191 192 keys.push_back(translate::TranslatePrefs::kPrefTranslateBlockedLanguages); 193 keys.push_back(translate::TranslatePrefs::kPrefTranslateLanguageBlacklist); 194 keys.push_back(translate::TranslatePrefs::kPrefTranslateSiteBlacklist); 195 keys.push_back(translate::TranslatePrefs::kPrefTranslateWhitelists); 196 keys.push_back(translate::TranslatePrefs::kPrefTranslateDeniedCount); 197 keys.push_back(translate::TranslatePrefs::kPrefTranslateAcceptedCount); 198 keys.push_back(translate::TranslatePrefs::kPrefTranslateLastDeniedTime); 199 keys.push_back(translate::TranslatePrefs::kPrefTranslateTooOftenDenied); 200 201 for (std::vector<std::string>::const_iterator it = keys.begin(); 202 it != keys.end(); ++it) { 203 const std::string& key = *it; 204 const PrefService::Preference* pref = prefs->FindPreference(key.c_str()); 205 if (pref) 206 dict.Set(key, pref->GetValue()->DeepCopy()); 207 } 208 209 SendMessageToJs("prefsUpdated", dict); 210} 211 212void TranslateInternalsHandler::SendSupportedLanguagesToJs() { 213 base::DictionaryValue dict; 214 215 std::vector<std::string> languages; 216 translate::TranslateDownloadManager::GetSupportedLanguages(&languages); 217 base::Time last_updated = 218 translate::TranslateDownloadManager::GetSupportedLanguagesLastUpdated(); 219 220 base::ListValue* languages_list = new base::ListValue(); 221 base::ListValue* alpha_languages_list = new base::ListValue(); 222 for (std::vector<std::string>::iterator it = languages.begin(); 223 it != languages.end(); ++it) { 224 const std::string& lang = *it; 225 languages_list->Append(new base::StringValue(lang)); 226 if (translate::TranslateDownloadManager::IsAlphaLanguage(lang)) 227 alpha_languages_list->Append(new base::StringValue(lang)); 228 } 229 230 dict.Set("languages", languages_list); 231 dict.Set("alpha_languages", alpha_languages_list); 232 dict.Set("last_updated", 233 new base::FundamentalValue(last_updated.ToJsTime())); 234 SendMessageToJs("supportedLanguagesUpdated", dict); 235} 236