This source file includes following definitions.
- request_pending_
- GetSupportedLanguages
- GetLanguageCode
- IsSupportedLanguage
- IsAlphaLanguage
- TranslateLanguageUrl
- RequestLanguageList
- SetResourceRequestsAllowed
- RegisterEventCallback
- DisableUpdate
- OnLanguageListFetchComplete
- NotifyEvent
- SetSupportedLanguages
#include "components/translate/core/browser/translate_language_list.h"
#include <set>
#include "base/bind.h"
#include "base/json/json_reader.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "components/translate/core/browser/translate_browser_metrics.h"
#include "components/translate/core/browser/translate_download_manager.h"
#include "components/translate/core/browser/translate_event_details.h"
#include "components/translate/core/browser/translate_url_fetcher.h"
#include "components/translate/core/browser/translate_url_util.h"
#include "components/translate/core/common/translate_util.h"
#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
namespace {
const char* const kDefaultSupportedLanguages[] = {
"af",
"sq",
"ar",
"be",
"bg",
"ca",
"zh-CN",
"zh-TW",
"hr",
"cs",
"da",
"nl",
"en",
"eo",
"et",
"tl",
"fi",
"fr",
"gl",
"de",
"el",
"ht",
"iw",
"hi",
"hu",
"is",
"id",
"ga",
"it",
"ja",
"ko",
"lv",
"lt",
"mk",
"ms",
"mt",
"no",
"fa",
"pl",
"pt",
"ro",
"ru",
"sr",
"sk",
"sl",
"es",
"sw",
"sv",
"th",
"tr",
"uk",
"vi",
"cy",
"yi",
};
const char kLanguageListFetchPath[] = "translate_a/l?client=chrome&cb=sl";
const char kAlphaLanguageQueryName[] = "alpha";
const char kAlphaLanguageQueryValue[] = "1";
bool update_is_disabled = false;
const int kMaxRetryOn5xx = 5;
}
const char TranslateLanguageList::kLanguageListCallbackName[] = "sl(";
const char TranslateLanguageList::kTargetLanguagesKey[] = "tl";
const char TranslateLanguageList::kAlphaLanguagesKey[] = "al";
TranslateLanguageList::TranslateLanguageList()
: resource_requests_allowed_(false), request_pending_(false) {
for (size_t i = 0; i < arraysize(kDefaultSupportedLanguages); ++i)
all_supported_languages_.insert(kDefaultSupportedLanguages[i]);
if (update_is_disabled)
return;
language_list_fetcher_.reset(new TranslateURLFetcher(kFetcherId));
language_list_fetcher_->set_max_retry_on_5xx(kMaxRetryOn5xx);
}
TranslateLanguageList::~TranslateLanguageList() {}
void TranslateLanguageList::GetSupportedLanguages(
std::vector<std::string>* languages) {
DCHECK(languages && languages->empty());
std::set<std::string>::const_iterator iter = all_supported_languages_.begin();
for (; iter != all_supported_languages_.end(); ++iter)
languages->push_back(*iter);
if (!update_is_disabled && language_list_fetcher_.get())
RequestLanguageList();
}
std::string TranslateLanguageList::GetLanguageCode(
const std::string& language) {
if (IsSupportedLanguage(language))
return language;
size_t hypen_index = language.find('-');
if (hypen_index == std::string::npos)
return language;
return language.substr(0, hypen_index);
}
bool TranslateLanguageList::IsSupportedLanguage(const std::string& language) {
return all_supported_languages_.count(language) != 0;
}
bool TranslateLanguageList::IsAlphaLanguage(const std::string& language) {
return alpha_languages_.count(language) != 0;
}
GURL TranslateLanguageList::TranslateLanguageUrl() {
std::string url = translate::GetTranslateSecurityOrigin().spec() +
kLanguageListFetchPath;
return GURL(url);
}
void TranslateLanguageList::RequestLanguageList() {
if (!resource_requests_allowed_) {
request_pending_ = true;
return;
}
request_pending_ = false;
if (language_list_fetcher_.get() &&
(language_list_fetcher_->state() == TranslateURLFetcher::IDLE ||
language_list_fetcher_->state() == TranslateURLFetcher::FAILED)) {
GURL url = TranslateLanguageUrl();
url = TranslateURLUtil::AddHostLocaleToUrl(url);
url = TranslateURLUtil::AddApiKeyToUrl(url);
url = net::AppendQueryParameter(
url, kAlphaLanguageQueryName, kAlphaLanguageQueryValue);
std::string message = base::StringPrintf(
"Language list including alpha languages fetch starts (URL: %s)",
url.spec().c_str());
NotifyEvent(__LINE__, message);
bool result = language_list_fetcher_->Request(
url,
base::Bind(&TranslateLanguageList::OnLanguageListFetchComplete,
base::Unretained(this)));
if (!result)
NotifyEvent(__LINE__, "Request is omitted due to retry limit");
}
}
void TranslateLanguageList::SetResourceRequestsAllowed(bool allowed) {
resource_requests_allowed_ = allowed;
if (resource_requests_allowed_ && request_pending_) {
RequestLanguageList();
DCHECK(!request_pending_);
}
}
scoped_ptr<TranslateLanguageList::EventCallbackList::Subscription>
TranslateLanguageList::RegisterEventCallback(const EventCallback& callback) {
return callback_list_.Add(callback);
}
void TranslateLanguageList::DisableUpdate() {
update_is_disabled = true;
}
void TranslateLanguageList::OnLanguageListFetchComplete(
int id,
bool success,
const std::string& data) {
if (!success) {
NotifyEvent(__LINE__, "Failed to fetch languages");
return;
}
NotifyEvent(__LINE__, "Language list is updated");
DCHECK_EQ(kFetcherId, id);
SetSupportedLanguages(data);
language_list_fetcher_.reset();
last_updated_ = base::Time::Now();
}
void TranslateLanguageList::NotifyEvent(int line, const std::string& message) {
TranslateEventDetails details(__FILE__, line, message);
callback_list_.Notify(details);
}
void TranslateLanguageList::SetSupportedLanguages(
const std::string& language_list) {
if (!StartsWithASCII(language_list,
TranslateLanguageList::kLanguageListCallbackName,
false) ||
!EndsWith(language_list, ")", false)) {
return;
}
static const size_t kLanguageListCallbackNameLength =
strlen(TranslateLanguageList::kLanguageListCallbackName);
std::string languages_json = language_list.substr(
kLanguageListCallbackNameLength,
language_list.size() - kLanguageListCallbackNameLength - 1);
scoped_ptr<base::Value> json_value(
base::JSONReader::Read(languages_json, base::JSON_ALLOW_TRAILING_COMMAS));
if (json_value == NULL || !json_value->IsType(base::Value::TYPE_DICTIONARY)) {
NOTREACHED();
return;
}
base::DictionaryValue* language_dict =
static_cast<base::DictionaryValue*>(json_value.get());
base::DictionaryValue* target_languages = NULL;
if (!language_dict->GetDictionary(TranslateLanguageList::kTargetLanguagesKey,
&target_languages) ||
target_languages == NULL) {
NOTREACHED();
return;
}
const std::string& locale =
TranslateDownloadManager::GetInstance()->application_locale();
all_supported_languages_.clear();
std::string message;
for (base::DictionaryValue::Iterator iter(*target_languages);
!iter.IsAtEnd();
iter.Advance()) {
const std::string& lang = iter.key();
if (!l10n_util::IsLocaleNameTranslated(lang.c_str(), locale)) {
TranslateBrowserMetrics::ReportUndisplayableLanguage(lang);
continue;
}
all_supported_languages_.insert(lang);
if (message.empty())
message += lang;
else
message += ", " + lang;
}
NotifyEvent(__LINE__, message);
base::DictionaryValue* alpha_languages = NULL;
if (!language_dict->GetDictionary(TranslateLanguageList::kAlphaLanguagesKey,
&alpha_languages) ||
alpha_languages == NULL) {
return;
}
alpha_languages_.clear();
for (base::DictionaryValue::Iterator iter(*alpha_languages);
!iter.IsAtEnd(); iter.Advance()) {
const std::string& lang = iter.key();
if (!l10n_util::IsLocaleNameTranslated(lang.c_str(), locale))
continue;
alpha_languages_.insert(lang);
}
}