Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/translate/translate_language_list.h" | 5 #include "chrome/browser/translate/translate_language_list.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 "https://translate.googleapis.com/translate_a/l?client=chrome&cb=sl"; | 98 "https://translate.googleapis.com/translate_a/l?client=chrome&cb=sl"; |
| 99 | 99 |
| 100 // Used in kTranslateScriptURL to request supporting languages list including | 100 // Used in kTranslateScriptURL to request supporting languages list including |
| 101 // "alpha languages". | 101 // "alpha languages". |
| 102 const char kAlphaLanguageQueryName[] = "alpha"; | 102 const char kAlphaLanguageQueryName[] = "alpha"; |
| 103 const char kAlphaLanguageQueryValue[] = "1"; | 103 const char kAlphaLanguageQueryValue[] = "1"; |
| 104 | 104 |
| 105 // Retry parameter for fetching supporting language list. | 105 // Retry parameter for fetching supporting language list. |
| 106 const int kMaxRetryLanguageListFetch = 5; | 106 const int kMaxRetryLanguageListFetch = 5; |
| 107 | 107 |
| 108 // Parses |language_list| containing the list of languages that the translate | |
| 109 // server can translate to and from, and fills |set| with them. | |
| 110 void SetSupportedLanguages(const std::string& language_list, | |
| 111 std::set<std::string>* set) { | |
|
MAD
2013/05/30 14:17:59
DCHECK(set);
Takashi Toyoshima
2013/05/30 14:41:38
Done.
| |
| 112 // The format is: | |
| 113 // sl({"sl": {"XX": "LanguageName", ...}, "tl": {"XX": "LanguageName", ...}}) | |
| 114 // Where "sl(" is set in kLanguageListCallbackName | |
| 115 // and "tl" is kTargetLanguagesKey | |
| 116 if (!StartsWithASCII(language_list, | |
| 117 TranslateLanguageList::kLanguageListCallbackName, | |
| 118 false) || | |
| 119 !EndsWith(language_list, ")", false)) { | |
| 120 // We don't have a NOTREACHED here since this can happen in ui_tests, even | |
| 121 // though the the BrowserMain function won't call us with parameters.ui_task | |
| 122 // is NULL some tests don't set it, so we must bail here. | |
| 123 return; | |
| 124 } | |
| 125 static const size_t kLanguageListCallbackNameLength = | |
| 126 strlen(TranslateLanguageList::kLanguageListCallbackName); | |
| 127 std::string languages_json = language_list.substr( | |
| 128 kLanguageListCallbackNameLength, | |
| 129 language_list.size() - kLanguageListCallbackNameLength - 1); | |
| 130 scoped_ptr<Value> json_value( | |
| 131 base::JSONReader::Read(languages_json, base::JSON_ALLOW_TRAILING_COMMAS)); | |
| 132 if (json_value == NULL || !json_value->IsType(Value::TYPE_DICTIONARY)) { | |
| 133 NOTREACHED(); | |
| 134 return; | |
| 135 } | |
| 136 // The first level dictionary contains two sub-dict, one for source languages | |
| 137 // and the other for target languages, we want to use the target languages. | |
| 138 DictionaryValue* language_dict = | |
| 139 static_cast<DictionaryValue*>(json_value.get()); | |
| 140 DictionaryValue* target_languages = NULL; | |
| 141 if (!language_dict->GetDictionary(TranslateLanguageList::kTargetLanguagesKey, | |
| 142 &target_languages) || | |
| 143 target_languages == NULL) { | |
| 144 NOTREACHED(); | |
| 145 return; | |
| 146 } | |
| 147 | |
| 148 // Now we can clear language list. | |
| 149 set->clear(); | |
| 150 // ... and replace it with the values we just fetched from the server. | |
| 151 for (DictionaryValue::Iterator iter(*target_languages); | |
| 152 !iter.IsAtEnd(); | |
| 153 iter.Advance()) { | |
| 154 // TODO(toyoshim): Check if UI libraries support adding locale. | |
| 155 set->insert(iter.key()); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 net::URLFetcher* CreateAndStartFetch(const GURL& url, | |
| 160 net::URLFetcherDelegate* delegate) { | |
| 161 DCHECK(delegate); | |
| 162 VLOG(9) << "Fetch supporting language list from: " << url.spec().c_str(); | |
| 163 | |
| 164 scoped_ptr<net::URLFetcher> fetcher; | |
| 165 fetcher.reset(net::URLFetcher::Create(1, | |
| 166 url, | |
| 167 net::URLFetcher::GET, | |
| 168 delegate)); | |
| 169 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | |
| 170 net::LOAD_DO_NOT_SAVE_COOKIES); | |
| 171 fetcher->SetRequestContext(g_browser_process->system_request_context()); | |
| 172 fetcher->SetMaxRetriesOn5xx(kMaxRetryLanguageListFetch); | |
| 173 fetcher->Start(); | |
| 174 | |
| 175 return fetcher.release(); | |
| 176 } | |
| 177 | |
| 108 } // namespace | 178 } // namespace |
| 109 | 179 |
| 110 // This must be kept in sync with the &cb= value in the kLanguageListFetchURL. | 180 // This must be kept in sync with the &cb= value in the kLanguageListFetchURL. |
| 111 const char TranslateLanguageList::kLanguageListCallbackName[] = "sl("; | 181 const char TranslateLanguageList::kLanguageListCallbackName[] = "sl("; |
| 112 const char TranslateLanguageList::kTargetLanguagesKey[] = "tl"; | 182 const char TranslateLanguageList::kTargetLanguagesKey[] = "tl"; |
| 113 | 183 |
| 114 TranslateLanguageList::TranslateLanguageList() { | 184 TranslateLanguageList::TranslateLanguageList() { |
| 115 // We default to our hard coded list of languages in | 185 // We default to our hard coded list of languages in |
| 116 // |kDefaultSupportedLanguages|. This list will be overriden by a server | 186 // |kDefaultSupportedLanguages|. This list will be overriden by a server |
| 117 // providing supported langauges list. | 187 // providing supported langauges list. |
| 118 for (size_t i = 0; i < arraysize(kDefaultSupportedLanguages); ++i) | 188 for (size_t i = 0; i < arraysize(kDefaultSupportedLanguages); ++i) |
| 119 supported_languages_.insert(kDefaultSupportedLanguages[i]); | 189 supported_languages_.insert(kDefaultSupportedLanguages[i]); |
| 120 } | 190 } |
| 121 | 191 |
| 122 TranslateLanguageList::~TranslateLanguageList() {} | 192 TranslateLanguageList::~TranslateLanguageList() {} |
| 123 | 193 |
| 124 void TranslateLanguageList::OnURLFetchComplete(const net::URLFetcher* source) { | 194 void TranslateLanguageList::OnURLFetchComplete(const net::URLFetcher* source) { |
| 125 DCHECK(url_fetcher_.get() == source); | 195 scoped_ptr<const net::URLFetcher> delete_ptr; |
| 126 scoped_ptr<const net::URLFetcher> delete_ptr(url_fetcher_.release()); | |
| 127 | 196 |
| 128 if (source->GetStatus().status() == net::URLRequestStatus::SUCCESS && | 197 if (source->GetStatus().status() == net::URLRequestStatus::SUCCESS && |
| 129 source->GetResponseCode() == net::HTTP_OK) { | 198 source->GetResponseCode() == net::HTTP_OK) { |
| 130 std::string data; | 199 std::string data; |
| 131 source->GetResponseAsString(&data); | 200 source->GetResponseAsString(&data); |
| 132 SetSupportedLanguages(data); | 201 if (language_list_fetcher_.get() == source) { |
| 202 delete_ptr.reset(language_list_fetcher_.get()); | |
|
MAD
2013/05/30 14:17:59
Shouldn't the .get() be a .release()?
Takashi Toyoshima
2013/05/30 14:41:38
Thank you for catching this.
| |
| 203 SetSupportedLanguages(data, &supported_languages_); | |
| 204 } else if (alpha_language_list_fetcher_.get() == source) { | |
| 205 delete_ptr.reset(alpha_language_list_fetcher_.get()); | |
|
MAD
2013/05/30 14:17:59
Same here.
Takashi Toyoshima
2013/05/30 14:41:38
Done.
| |
| 206 SetSupportedLanguages(data, &supported_alpha_languages_); | |
| 207 } else { | |
| 208 NOTREACHED(); | |
| 209 } | |
| 133 } else { | 210 } else { |
| 134 // TODO(toyoshim): Try again. http://crbug.com/244202 . | 211 // TODO(toyoshim): Try again. http://crbug.com/244202 . |
| 212 // Also In CrOS, FetchLanguageList is not called at launching Chrome. It | |
| 213 // will solve this problem that check if FetchLanguageList is already | |
| 214 // called, and call it if needed in InitSupportedLanguage(). | |
| 135 VLOG(9) << "Failed to Fetch languages from: " << kLanguageListFetchURL; | 215 VLOG(9) << "Failed to Fetch languages from: " << kLanguageListFetchURL; |
| 136 } | 216 } |
| 137 } | 217 } |
| 138 | 218 |
| 139 void TranslateLanguageList::GetSupportedLanguages( | 219 void TranslateLanguageList::GetSupportedLanguages( |
| 140 std::vector<std::string>* languages) { | 220 std::vector<std::string>* languages) { |
| 141 DCHECK(languages && languages->empty()); | 221 DCHECK(languages && languages->empty()); |
| 142 std::set<std::string>::const_iterator iter = supported_languages_.begin(); | 222 std::set<std::string>& list = |
| 143 for (; iter != supported_languages_.end(); ++iter) | 223 supported_alpha_languages_.empty() ? supported_languages_ : |
|
MAD
2013/05/30 14:17:59
You used to always return the supported_laguages_
Takashi Toyoshima
2013/05/30 14:41:38
It's no problem that providing only supported_lang
MAD
2013/05/30 14:58:01
Sorry, I still don't understand.
What I was tryin
| |
| 224 supported_alpha_languages_; | |
| 225 for (std::set<std::string>::const_iterator iter = list.begin(); | |
| 226 iter != list.end(); ++iter) | |
| 144 languages->push_back(*iter); | 227 languages->push_back(*iter); |
| 145 } | 228 } |
| 146 | 229 |
| 147 std::string TranslateLanguageList::GetLanguageCode( | 230 std::string TranslateLanguageList::GetLanguageCode( |
| 148 const std::string& chrome_locale) { | 231 const std::string& chrome_locale) { |
| 149 // Only remove the country code for country specific languages we don't | 232 // Only remove the country code for country specific languages we don't |
| 150 // support specifically yet. | 233 // support specifically yet. |
| 151 if (IsSupportedLanguage(chrome_locale)) | 234 if (IsSupportedLanguage(chrome_locale)) |
| 152 return chrome_locale; | 235 return chrome_locale; |
| 153 | 236 |
| 154 size_t hypen_index = chrome_locale.find('-'); | 237 size_t hypen_index = chrome_locale.find('-'); |
| 155 if (hypen_index == std::string::npos) | 238 if (hypen_index == std::string::npos) |
| 156 return chrome_locale; | 239 return chrome_locale; |
| 157 return chrome_locale.substr(0, hypen_index); | 240 return chrome_locale.substr(0, hypen_index); |
| 158 } | 241 } |
| 159 | 242 |
| 160 bool TranslateLanguageList::IsSupportedLanguage( | 243 bool TranslateLanguageList::IsSupportedLanguage(const std::string& language) { |
| 161 const std::string& page_language) { | 244 // Langauge should exist at least one of these two language lists. |
| 162 return supported_languages_.count(page_language) != 0; | 245 return supported_alpha_languages_.count(language) != 0 || |
| 246 supported_languages_.count(language) != 0; | |
|
MAD
2013/05/30 14:17:59
I guess if we do this, we need to return the conte
Takashi Toyoshima
2013/05/30 14:41:38
When supported_alpha_languages_ is empty,
GetSupp
| |
| 247 } | |
| 248 | |
| 249 bool TranslateLanguageList::IsAlphaLanguage(const std::string& language) { | |
| 250 // Language should exist only in the alpha language list. | |
| 251 return supported_alpha_languages_.count(language) != 0 && | |
| 252 supported_languages_.count(language) == 0; | |
| 163 } | 253 } |
| 164 | 254 |
| 165 void TranslateLanguageList::RequestLanguageList() { | 255 void TranslateLanguageList::RequestLanguageList() { |
| 166 if (url_fetcher_.get()) | 256 // Fetch the stable language list. |
|
MAD
2013/05/30 14:17:59
Why didn't you keep this?
Takashi Toyoshima
2013/05/30 14:41:38
Oops, you are right. I should keep it here.
Done.
| |
| 167 return; | |
| 168 | |
| 169 GURL language_list_fetch_url = GURL(kLanguageListFetchURL); | 257 GURL language_list_fetch_url = GURL(kLanguageListFetchURL); |
| 170 language_list_fetch_url = | 258 language_list_fetch_url = |
| 171 TranslateURLUtil::AddHostLocaleToUrl(language_list_fetch_url); | 259 TranslateURLUtil::AddHostLocaleToUrl(language_list_fetch_url); |
| 172 language_list_fetch_url = | 260 language_list_fetch_url = |
| 173 TranslateURLUtil::AddApiKeyToUrl(language_list_fetch_url); | 261 TranslateURLUtil::AddApiKeyToUrl(language_list_fetch_url); |
| 174 | 262 |
| 263 language_list_fetcher_.reset( | |
| 264 CreateAndStartFetch(language_list_fetch_url, this)); | |
| 265 | |
| 266 // TODO(toyoshim): Make it enabled by default. http://crbug.com/242178 | |
| 175 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 267 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 176 if (command_line.HasSwitch(switches::kEnableTranslateAlphaLanguages)) { | 268 if (!command_line.HasSwitch(switches::kEnableTranslateAlphaLanguages)) |
| 177 language_list_fetch_url = net::AppendQueryParameter( | 269 return; |
| 178 language_list_fetch_url, | |
| 179 kAlphaLanguageQueryName, | |
| 180 kAlphaLanguageQueryValue); | |
| 181 } | |
| 182 | 270 |
| 183 VLOG(9) << "Fetch supporting language list from: " | 271 // Fetch the alpha language list. |
| 184 << language_list_fetch_url.spec().c_str(); | 272 language_list_fetch_url = net::AppendQueryParameter( |
| 273 language_list_fetch_url, | |
| 274 kAlphaLanguageQueryName, | |
| 275 kAlphaLanguageQueryValue); | |
| 185 | 276 |
| 186 url_fetcher_.reset(net::URLFetcher::Create(1, | 277 alpha_language_list_fetcher_.reset( |
| 187 language_list_fetch_url, | 278 CreateAndStartFetch(language_list_fetch_url, this)); |
| 188 net::URLFetcher::GET, | |
| 189 this)); | |
| 190 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | |
| 191 net::LOAD_DO_NOT_SAVE_COOKIES); | |
| 192 url_fetcher_->SetRequestContext(g_browser_process->system_request_context()); | |
| 193 url_fetcher_->SetMaxRetriesOn5xx(kMaxRetryLanguageListFetch); | |
| 194 url_fetcher_->Start(); | |
| 195 } | 279 } |
| 196 | |
| 197 void TranslateLanguageList::SetSupportedLanguages( | |
| 198 const std::string& language_list) { | |
| 199 // The format is: | |
| 200 // sl({"sl": {"XX": "LanguageName", ...}, "tl": {"XX": "LanguageName", ...}}) | |
| 201 // Where "sl(" is set in kLanguageListCallbackName | |
| 202 // and "tl" is kTargetLanguagesKey | |
| 203 if (!StartsWithASCII(language_list, | |
| 204 TranslateLanguageList::kLanguageListCallbackName, | |
| 205 false) || | |
| 206 !EndsWith(language_list, ")", false)) { | |
| 207 // We don't have a NOTREACHED here since this can happen in ui_tests, even | |
| 208 // though the the BrowserMain function won't call us with parameters.ui_task | |
| 209 // is NULL some tests don't set it, so we must bail here. | |
| 210 return; | |
| 211 } | |
| 212 static const size_t kLanguageListCallbackNameLength = | |
| 213 strlen(TranslateLanguageList::kLanguageListCallbackName); | |
| 214 std::string languages_json = language_list.substr( | |
| 215 kLanguageListCallbackNameLength, | |
| 216 language_list.size() - kLanguageListCallbackNameLength - 1); | |
| 217 scoped_ptr<Value> json_value( | |
| 218 base::JSONReader::Read(languages_json, base::JSON_ALLOW_TRAILING_COMMAS)); | |
| 219 if (json_value == NULL || !json_value->IsType(Value::TYPE_DICTIONARY)) { | |
| 220 NOTREACHED(); | |
| 221 return; | |
| 222 } | |
| 223 // The first level dictionary contains two sub-dict, one for source languages | |
| 224 // and the other for target languages, we want to use the target languages. | |
| 225 DictionaryValue* language_dict = | |
| 226 static_cast<DictionaryValue*>(json_value.get()); | |
| 227 DictionaryValue* target_languages = NULL; | |
| 228 if (!language_dict->GetDictionary(TranslateLanguageList::kTargetLanguagesKey, | |
| 229 &target_languages) || | |
| 230 target_languages == NULL) { | |
| 231 NOTREACHED(); | |
| 232 return; | |
| 233 } | |
| 234 // Now we can clear our current state... | |
| 235 supported_languages_.clear(); | |
| 236 // ... and replace it with the values we just fetched from the server. | |
| 237 for (DictionaryValue::Iterator iter(*target_languages); | |
| 238 !iter.IsAtEnd(); | |
| 239 iter.Advance()) { | |
| 240 supported_languages_.insert(iter.key()); | |
| 241 } | |
| 242 } | |
| OLD | NEW |