Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2690)

Unified Diff: chrome/browser/translate/translate_manager.cc

Issue 7171002: Get the list of supported languages from the translate server. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/translate/translate_manager.cc
===================================================================
--- chrome/browser/translate/translate_manager.cc (revision 89207)
+++ chrome/browser/translate/translate_manager.cc (working copy)
@@ -6,10 +6,12 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
+#include "base/json/json_reader.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
#include "base/string_split.h"
#include "base/string_util.h"
+#include "base/values.h"
#include "chrome/browser/autofill/autofill_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/pref_service.h"
@@ -124,11 +126,17 @@
"Google-Translate-Element-Mode: library";
const char* const kReportLanguageDetectionErrorURL =
"http://translate.google.com/translate_error";
-
+const char* const kLanguageListFetchURL =
+ "http://translate.googleapis.com/translate_a/l?client=chrome&cb=sl";
+const int kMaxRetryLanguageListFetch = 5;
const int kTranslateScriptExpirationDelayMS = 24 * 60 * 60 * 1000; // 1 day.
} // namespace
+// This must be kept in sync with the &cb= value in the kLanguageListFetchURL.
+const char* const TranslateManager::kLanguageListCallbackName = "sl(";
+const char* const TranslateManager::kTargetLanguagesKey = "tl";
+
// static
base::LazyInstance<std::set<std::string> >
TranslateManager::supported_languages_(base::LINKER_INITIALIZED);
@@ -154,11 +162,69 @@
}
// static
+void TranslateManager::SetSupportedLanguages(const std::string& language_list) {
+ // The format is:
+ // sl({'sl': {'XX': 'LanguageName', ...}, 'tl': {'XX': 'LanguageName', ...}})
+ // Where "sl(" is set in kLanguageListCallbackName
+ // and 'tl' is kTargetLanguagesKey
+ if (!StartsWithASCII(language_list, kLanguageListCallbackName, false) ||
+ !EndsWith(language_list, ")", false)) {
+ // We don't have a NOTREACHED here since this can happen in ui_tests, even
+ // though the the BrowserMain function won't call us with parameters.ui_task
+ // is NULL some tests don't set it, so we must bail here.
+ return;
+ }
+ static const size_t kLanguageListCallbackNameLength =
+ strlen(kLanguageListCallbackName);
+ std::string languages_json = language_list.substr(
+ kLanguageListCallbackNameLength,
+ language_list.size() - kLanguageListCallbackNameLength - 1);
+ // JSON doesn't support single quotes though this is what is used on the
+ // translate server so we must replace them with double quotes.
+ ReplaceSubstringsAfterOffset(&languages_json, 0, "'", "\"");
+ scoped_ptr<Value> json_value(base::JSONReader::Read(languages_json, true));
+ if (json_value == NULL || !json_value->IsType(Value::TYPE_DICTIONARY)) {
+ NOTREACHED();
+ return;
+ }
+ // The first level dictionary contains two sub-dict, one for source languages
+ // and the other for target languages, we want to use the target languages.
+ DictionaryValue* language_dict =
+ static_cast<DictionaryValue*>(json_value.get());
+ DictionaryValue* target_languages = NULL;
+ if (!language_dict->GetDictionary(kTargetLanguagesKey, &target_languages) ||
+ target_languages == NULL) {
+ NOTREACHED();
+ return;
+ }
+ // Now we can clear our current state...
+ std::set<std::string>* supported_languages = supported_languages_.Pointer();
+ supported_languages->clear();
+ // ... and replace it with the values we just fetched from the server.
+ DictionaryValue::key_iterator iter = target_languages->begin_keys();
+ for (; iter != target_languages->end_keys(); ++iter)
+ supported_languages_.Pointer()->insert(*iter);
+}
+
+// static
+void TranslateManager::InitSupportedLanguages() {
+ // If our list of supported languages have not been set yet, we default
+ // to our hard coded list of languages in kSupportedLanguages.
+ if (supported_languages_.Pointer()->empty()) {
+ for (size_t i = 0; i < arraysize(kSupportedLanguages); ++i)
+ supported_languages_.Pointer()->insert(kSupportedLanguages[i]);
+ }
+}
+
+// static
void TranslateManager::GetSupportedLanguages(
std::vector<std::string>* languages) {
DCHECK(languages && languages->empty());
- for (size_t i = 0; i < arraysize(kSupportedLanguages); ++i)
- languages->push_back(kSupportedLanguages[i]);
+ InitSupportedLanguages();
+ std::set<std::string>* supported_languages = supported_languages_.Pointer();
+ std::set<std::string>::const_iterator iter = supported_languages->begin();
+ for (; iter != supported_languages->end(); ++iter)
+ languages->push_back(*iter);
}
// static
@@ -177,12 +243,8 @@
// static
bool TranslateManager::IsSupportedLanguage(const std::string& page_language) {
- std::set<std::string>* supported_languages = supported_languages_.Pointer();
- if (supported_languages->empty()) {
- for (size_t i = 0; i < arraysize(kSupportedLanguages); ++i)
- supported_languages->insert(kSupportedLanguages[i]);
- }
- return supported_languages->find(page_language) != supported_languages->end();
+ InitSupportedLanguages();
+ return supported_languages_.Pointer()->count(page_language) != 0;
}
void TranslateManager::Observe(NotificationType type,
@@ -288,54 +350,74 @@
const net::ResponseCookies& cookies,
const std::string& data) {
scoped_ptr<const URLFetcher> delete_ptr(source);
- DCHECK(translate_script_request_pending_);
- translate_script_request_pending_ = false;
+ DCHECK(translate_script_request_pending_ || language_list_request_pending_);
+ // We quickly recognize that we are handling a translate script request
+ // if we don't have a language_list_request_pending_. Otherwise we do the
+ // more expensive check of confirming we got the kTranslateScriptURL in the
+ // rare case where we would have both requests pending at the same time.
+ bool translate_script_request = !language_list_request_pending_ ||
+ url == GURL(kTranslateScriptURL);
+ // Here we make sure that if we didn't get the translate_script_request,
+ // we actually got a language_list_request.
+ DCHECK(translate_script_request || url == GURL(kLanguageListFetchURL));
+ if (translate_script_request)
+ translate_script_request_pending_ = false;
+ else
+ language_list_request_pending_ = false;
+
bool error =
(status.status() != net::URLRequestStatus::SUCCESS ||
response_code != 200);
- if (!error) {
- base::StringPiece str = ResourceBundle::GetSharedInstance().
- GetRawDataResource(IDR_TRANSLATE_JS);
- DCHECK(translate_script_.empty());
- str.CopyToString(&translate_script_);
- translate_script_ += "\n" + data;
- // We'll expire the cached script after some time, to make sure long running
- // browsers still get fixes that might get pushed with newer scripts.
- MessageLoop::current()->PostDelayedTask(FROM_HERE,
- method_factory_.NewRunnableMethod(
- &TranslateManager::ClearTranslateScript),
- translate_script_expiration_delay_);
- }
-
- // Process any pending requests.
- std::vector<PendingRequest>::const_iterator iter;
- for (iter = pending_requests_.begin(); iter != pending_requests_.end();
- ++iter) {
- const PendingRequest& request = *iter;
- TabContents* tab = tab_util::GetTabContentsByID(request.render_process_id,
- request.render_view_id);
- if (!tab) {
- // The tab went away while we were retrieving the script.
- continue;
+ if (translate_script_request) {
+ if (!error) {
+ base::StringPiece str = ResourceBundle::GetSharedInstance().
+ GetRawDataResource(IDR_TRANSLATE_JS);
+ DCHECK(translate_script_.empty());
+ str.CopyToString(&translate_script_);
+ translate_script_ += "\n" + data;
+ // We'll expire the cached script after some time, to make sure long
+ // running browsers still get fixes that might get pushed with newer
+ // scripts.
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &TranslateManager::ClearTranslateScript),
+ translate_script_expiration_delay_);
}
- NavigationEntry* entry = tab->controller().GetActiveEntry();
- if (!entry || entry->page_id() != request.page_id) {
- // We navigated away from the page the translation was triggered on.
- continue;
- }
+ // Process any pending requests.
+ std::vector<PendingRequest>::const_iterator iter;
+ for (iter = pending_requests_.begin(); iter != pending_requests_.end();
+ ++iter) {
+ const PendingRequest& request = *iter;
+ TabContents* tab = tab_util::GetTabContentsByID(request.render_process_id,
+ request.render_view_id);
+ if (!tab) {
+ // The tab went away while we were retrieving the script.
+ continue;
+ }
+ NavigationEntry* entry = tab->controller().GetActiveEntry();
+ if (!entry || entry->page_id() != request.page_id) {
+ // We navigated away from the page the translation was triggered on.
+ continue;
+ }
- if (error) {
- ShowInfoBar(tab, TranslateInfoBarDelegate::CreateErrorDelegate(
- TranslateErrors::NETWORK, tab,
- request.source_lang, request.target_lang));
- } else {
- // Translate the page.
- DoTranslatePage(tab, translate_script_,
- request.source_lang, request.target_lang);
+ if (error) {
+ ShowInfoBar(tab, TranslateInfoBarDelegate::CreateErrorDelegate(
+ TranslateErrors::NETWORK, tab,
+ request.source_lang, request.target_lang));
+ } else {
+ // Translate the page.
+ DoTranslatePage(tab, translate_script_,
+ request.source_lang, request.target_lang);
+ }
}
+ pending_requests_.clear();
+ } else { // if (translate_script_request)
+ if (!error)
+ SetSupportedLanguages(data);
+ else
+ VLOG(1) << "Failed to Fetch languages from: " << kLanguageListFetchURL;
}
- pending_requests_.clear();
}
// static
@@ -346,7 +428,8 @@
TranslateManager::TranslateManager()
: ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
translate_script_expiration_delay_(kTranslateScriptExpirationDelayMS),
- translate_script_request_pending_(false) {
+ translate_script_request_pending_(false),
+ language_list_request_pending_(false) {
notification_registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
NotificationService::AllSources());
notification_registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED,
@@ -619,6 +702,27 @@
accept_languages_[prefs] = accept_langs_set;
}
+void TranslateManager::FetchLanguageListFromTranslateServer(
+ PrefService* prefs) {
+ if (language_list_request_pending_)
+ return;
+
+ // We don't want to do this when translate is disabled.
+ DCHECK(prefs != NULL);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableTranslate) ||
+ (prefs != NULL && !prefs->GetBoolean(prefs::kEnableTranslate))) {
+ return;
+ }
+
+ language_list_request_pending_ = true;
+ URLFetcher* fetcher = URLFetcher::Create(1, GURL(kLanguageListFetchURL),
+ URLFetcher::GET, this);
+ fetcher->set_request_context(Profile::GetDefaultRequestContext());
+ fetcher->set_max_retries(kMaxRetryLanguageListFetch);
+ fetcher->Start();
+}
+
void TranslateManager::RequestTranslateScript() {
if (translate_script_request_pending_)
return;
« no previous file with comments | « chrome/browser/translate/translate_manager.h ('k') | chrome/browser/translate/translate_manager_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698