blob: bc45d9e6cf2f69591bcf653a00e1ebbc839e01ba [file] [log] [blame]
// 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/values.h"
#include "chrome/browser/browser_process.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/prefs/pref_service.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 "components/variations/service/variations_service.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_ =
translate::TranslateManager::RegisterTranslateErrorCallback(
base::Bind(&TranslateInternalsHandler::OnTranslateError,
base::Unretained(this)));
translate::TranslateLanguageList* language_list =
translate::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)));
web_ui()->RegisterMessageCallback(
"overrideCountry",
base::Bind(&TranslateInternalsHandler::OnOverrideCountry,
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 translate::LanguageDetectionDetails* language_detection_details =
content::Details<const translate::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("has_notranslate", new base::FundamentalValue(
language_detection_details->has_notranslate));
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 translate::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 translate::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();
std::unique_ptr<translate::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 == "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::OnOverrideCountry(const base::ListValue* args) {
std::string country;
if (args->GetString(0, &country)) {
variations::VariationsService* variations_service =
g_browser_process->variations_service();
if (variations_service) {
SendCountryToJs(
variations_service->OverrideStoredPermanentCountry(country));
}
}
}
void TranslateInternalsHandler::OnRequestInfo(const base::ListValue* /*args*/) {
SendPrefsToJs();
SendSupportedLanguagesToJs();
SendCountryToJs(false);
}
void TranslateInternalsHandler::SendMessageToJs(const std::string& message,
const base::Value& value) {
const char func[] = "cr.translateInternals.messageHandler";
base::StringValue message_data(message);
web_ui()->CallJavascriptFunctionUnsafe(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;
static const char* keys[] = {
prefs::kEnableTranslate,
translate::TranslatePrefs::kPrefTranslateBlockedLanguages,
translate::TranslatePrefs::kPrefTranslateSiteBlacklist,
translate::TranslatePrefs::kPrefTranslateWhitelists,
translate::TranslatePrefs::kPrefTranslateDeniedCount,
translate::TranslatePrefs::kPrefTranslateIgnoredCount,
translate::TranslatePrefs::kPrefTranslateAcceptedCount,
translate::TranslatePrefs::kPrefTranslateLastDeniedTimeForLanguage,
translate::TranslatePrefs::kPrefTranslateTooOftenDeniedForLanguage,
};
for (const char* key : keys) {
const PrefService::Preference* pref = prefs->FindPreference(key);
if (pref)
dict.Set(key, pref->GetValue()->DeepCopy());
}
SendMessageToJs("prefsUpdated", dict);
}
void TranslateInternalsHandler::SendSupportedLanguagesToJs() {
base::DictionaryValue dict;
std::vector<std::string> languages;
translate::TranslateDownloadManager::GetSupportedLanguages(&languages);
base::Time last_updated =
translate::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->AppendString(lang);
if (translate::TranslateDownloadManager::IsAlphaLanguage(lang))
alpha_languages_list->AppendString(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);
}
void TranslateInternalsHandler::SendCountryToJs(bool was_updated) {
std::string country;
variations::VariationsService* variations_service =
g_browser_process->variations_service();
if (variations_service)
country = variations_service->GetStoredPermanentCountry();
base::DictionaryValue dict;
if (!country.empty()) {
dict.Set("country", new base::StringValue(country));
dict.Set("update", new base::FundamentalValue(was_updated));
}
SendMessageToJs("countryUpdated", dict);
}