summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-01 08:45:15 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-01 08:45:15 +0000
commit7e0831b90c618af96931fcbd0908c4fd05ae0ec5 (patch)
tree6ae2ee1358ecb452ed7c06335ddd643ee47bc109
parent6db4b6c354f638cfe9beb849ca0ad0beb1bb4a8d (diff)
downloadchromium_src-7e0831b90c618af96931fcbd0908c4fd05ae0ec5.zip
chromium_src-7e0831b90c618af96931fcbd0908c4fd05ae0ec5.tar.gz
chromium_src-7e0831b90c618af96931fcbd0908c4fd05ae0ec5.tar.bz2
Relanding the hooking of the translate feature UI.
See http://codereview.chromium.org/549217 Review URL: http://codereview.chromium.org/558065 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37688 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/browser_main.cc8
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc2
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc12
-rw-r--r--chrome/browser/renderer_host/render_view_host.h3
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h5
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc36
-rw-r--r--chrome/browser/tab_contents/tab_contents.h7
-rw-r--r--chrome/browser/translate/translate_infobars_delegates.cc5
-rw-r--r--chrome/browser/translate/translate_manager.cc113
-rw-r--r--chrome/browser/translate/translate_manager.h47
-rwxr-xr-xchrome/chrome_browser.gypi2
-rw-r--r--chrome/common/chrome_switches.cc4
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/common/notification_type.h8
-rw-r--r--chrome/common/render_messages_internal.h6
-rw-r--r--chrome/renderer/render_view.cc11
-rw-r--r--chrome/renderer/render_view.h8
-rw-r--r--chrome/renderer/translate/page_translator.cc70
-rw-r--r--chrome/renderer/translate/page_translator.h41
-rw-r--r--chrome/renderer/translate/page_translator_unittest.cc4
-rw-r--r--chrome/test/ui_test_utils.cc7
21 files changed, 340 insertions, 60 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 42d2c14..a0ba774 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -46,6 +46,7 @@
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/shell_integration.h"
+#include "chrome/browser/translate/translate_manager.h"
#include "chrome/browser/user_data_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
@@ -803,6 +804,13 @@ int BrowserMain(const MainFunctionParams& parameters) {
process_singleton.Create();
+#if defined(OS_WIN)
+ // Create the TranslateManager singleton.
+ // TODO(jcampan): enable on non Windows platforms when the info-bars are
+ // implemented.
+ Singleton<TranslateManager>::get();
+#endif
+
// Show the First Run UI if this is the first time Chrome has been run on
// this computer, or we're being compelled to do so by a command line flag.
// Note that this be done _after_ the PrefService is initialized and all
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index 7b9aef0..f85f054 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -897,7 +897,7 @@ bool DetectTabLanguageFunction::RunImpl() {
// The tab contents does not know its language yet. Let's wait until it
// receives it, or until the tab is closed/navigates to some other page.
registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED,
- Source<RenderViewHost>(contents->render_view_host()));
+ Source<TabContents>(contents));
registrar_.Add(this, NotificationType::TAB_CLOSING,
Source<NavigationController>(&(contents->controller())));
registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index cb0eddf..820b575 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -825,6 +825,7 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
OnAccessibilityFocusChange)
IPC_MESSAGE_HANDLER(ViewHostMsg_OnCSSInserted, OnCSSInserted)
IPC_MESSAGE_HANDLER(ViewHostMsg_PageContents, OnPageContents)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_PageTranslated, OnPageTranslated)
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(RenderWidgetHost::OnMessageReceived(msg))
IPC_END_MESSAGE_MAP_EX()
@@ -1794,3 +1795,14 @@ void RenderViewHost::OnPageContents(const GURL& url,
integration_delegate->OnPageContents(url, process()->id(), page_id, contents,
language);
}
+
+void RenderViewHost::OnPageTranslated(int32 page_id,
+ const std::string& original_lang,
+ const std::string& translated_lang) {
+ RenderViewHostDelegate::BrowserIntegration* integration_delegate =
+ delegate_->GetBrowserIntegrationDelegate();
+ if (!integration_delegate)
+ return;
+ integration_delegate->OnPageTranslated(page_id,
+ original_lang, translated_lang);
+}
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 5890ae7..764be45 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -606,6 +606,9 @@ class RenderViewHost : public RenderWidgetHost {
int32 page_id,
const std::wstring& contents,
const std::string& language);
+ void OnPageTranslated(int32 page_id,
+ const std::string& original_lang,
+ const std::string& translated_lang);
private:
friend class TestRenderViewHost;
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index 680ff0f..892aa86 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -223,6 +223,11 @@ class RenderViewHostDelegate {
int32 page_id,
const std::wstring& contents,
const std::string& language) = 0;
+
+ // Notification that the page has been translated.
+ virtual void OnPageTranslated(int32 page_id,
+ const std::string& original_lang,
+ const std::string& translated_lang) = 0;
};
// Resource ------------------------------------------------------------------
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index a575ae5..4641f3b 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -772,6 +772,16 @@ void TabContents::ShowPageInfo(const GURL& url,
delegate_->ShowPageInfo(profile(), url, ssl, show_history);
}
+void TabContents::TranslatePage(const std::string& source_lang,
+ const std::string& target_lang) {
+ NavigationEntry* entry = controller_.GetActiveEntry();
+ if (!entry) {
+ NOTREACHED();
+ return;
+ }
+ render_view_host()->TranslatePage(entry->page_id(), source_lang, target_lang);
+}
+
ConstrainedWindow* TabContents::CreateConstrainedDialog(
ConstrainedWindowDelegate* delegate) {
ConstrainedWindow* window =
@@ -1813,26 +1823,24 @@ void TabContents::OnPageContents(const GURL& url,
entry->set_language(language);
}
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAutoPageTranslate) &&
- TranslationService::IsTranslationEnabled()) {
- std::string locale = g_browser_process->GetApplicationLocale();
- if (!locale.empty() && locale != language) {
- // Don't translate the NTP, download page, history...
- if (entry && !entry->url().SchemeIs("chrome") &&
- TranslationService::ShouldTranslatePage(language, locale)) {
- render_view_host()->TranslatePage(entry->page_id(), language, locale);
- }
- }
- }
-
std::string lang = language;
NotificationService::current()->Notify(
NotificationType::TAB_LANGUAGE_DETERMINED,
- Source<RenderViewHost>(render_view_host()),
+ Source<TabContents>(this),
Details<std::string>(&lang));
}
+void TabContents::OnPageTranslated(int32 page_id,
+ const std::string& original_lang,
+ const std::string& translated_lang) {
+ std::pair<std::string, std::string> lang_pair =
+ std::make_pair(original_lang, translated_lang);
+ NotificationService::current()->Notify(
+ NotificationType::PAGE_TRANSLATED,
+ Source<TabContents>(this),
+ Details<std::pair<std::string, std::string> >(&lang_pair));
+}
+
void TabContents::DidStartProvisionalLoadForFrame(
RenderViewHost* render_view_host,
bool is_main_frame,
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 9586f88..e42c1fb 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -350,6 +350,10 @@ class TabContents : public PageNavigator,
const NavigationEntry::SSLStatus& ssl,
bool show_history);
+ // Translates the page contents from |source_lang| to |target_lang|.
+ void TranslatePage(const std::string& source_lang,
+ const std::string& target_lang);
+
// Window management ---------------------------------------------------------
// Create a new window constrained to this TabContents' clip and visibility.
@@ -827,6 +831,9 @@ class TabContents : public PageNavigator,
int32 page_id,
const std::wstring& contents,
const std::string& language);
+ virtual void OnPageTranslated(int32 page_id,
+ const std::string& original_lang,
+ const std::string& translated_lang);
// RenderViewHostDelegate::Resource implementation.
virtual void DidStartProvisionalLoadForFrame(RenderViewHost* render_view_host,
diff --git a/chrome/browser/translate/translate_infobars_delegates.cc b/chrome/browser/translate/translate_infobars_delegates.cc
index ecf0a95..15d165b 100644
--- a/chrome/browser/translate/translate_infobars_delegates.cc
+++ b/chrome/browser/translate/translate_infobars_delegates.cc
@@ -93,10 +93,7 @@ void TranslateInfoBarDelegate::GetAvailableTargetLanguages(
}
void TranslateInfoBarDelegate::Translate() {
- // TODO(kuan): Call actual Translate method.
-/*
- Translate(WideToUTF8(original_language()), WideToUTF8(target_language()));
-*/
+ tab_contents_->TranslatePage(original_language_, target_language_);
}
bool TranslateInfoBarDelegate::IsLanguageBlacklisted() {
diff --git a/chrome/browser/translate/translate_manager.cc b/chrome/browser/translate/translate_manager.cc
new file mode 100644
index 0000000..5a7938a
--- /dev/null
+++ b/chrome/browser/translate/translate_manager.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2010 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/translate/translate_manager.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/translation_service.h"
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/navigation_entry.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/translate/translate_infobars_delegates.h"
+#include "chrome/browser/translate/translate_prefs.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_service.h"
+
+TranslateManager::~TranslateManager() {
+}
+
+void TranslateManager::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::NAV_ENTRY_COMMITTED: {
+ // We have navigated to a new page.
+ NavigationController* controller =
+ Source<NavigationController>(source).ptr();
+ NavigationEntry* entry = controller->GetActiveEntry();
+ if (!entry->language().empty()) {
+ // The language for that page is known (it must be a back/forward
+ // navigation to a page we already visited).
+ InitiateTranslation(controller->tab_contents(), entry->language());
+ }
+ break;
+ }
+ case NotificationType::TAB_LANGUAGE_DETERMINED: {
+ TabContents* tab = Source<TabContents>(source).ptr();
+ std::string language = *(Details<std::string>(details).ptr());
+ InitiateTranslation(tab, language);
+ break;
+ }
+ case NotificationType::PAGE_TRANSLATED: {
+ TabContents* tab = Source<TabContents>(source).ptr();
+ std::pair<std::string, std::string>* language_pair =
+ (Details<std::pair<std::string, std::string> >(details).ptr());
+ PrefService* prefs = GetPrefService(tab);
+ tab->AddInfoBar(new AfterTranslateInfoBarDelegate(tab, prefs,
+ language_pair->first,
+ language_pair->second));
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+TranslateManager::TranslateManager() {
+ if (!TranslationService::IsTranslationEnabled())
+ return;
+
+ notification_registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
+ NotificationService::AllSources());
+ notification_registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED,
+ NotificationService::AllSources());
+ notification_registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
+ NotificationService::AllSources());
+}
+
+void TranslateManager::InitiateTranslation(TabContents* tab,
+ const std::string& page_lang) {
+ PrefService* prefs = GetPrefService(tab);
+ NavigationEntry* entry = tab->controller().GetActiveEntry();
+ if (!entry) {
+ NOTREACHED();
+ return;
+ }
+
+ std::string chrome_lang = g_browser_process->GetApplicationLocale();
+
+ // We don't want to translate:
+ // - any Chrome specific page (New Tab Page, Download, History... pages).
+ // - similar languages (ex: en-US to en).
+ // - any user black-listed URLs or user selected language combination.
+ if (entry->url().SchemeIs("chrome") || page_lang == chrome_lang ||
+ !TranslationService::ShouldTranslatePage(page_lang, chrome_lang) ||
+ !TranslatePrefs::CanTranslate(prefs, page_lang, entry->url())) {
+ return;
+ }
+ if (TranslatePrefs::ShouldAutoTranslate(prefs, page_lang, chrome_lang)) {
+ // The user has previously select "always translate" for this language.
+ tab->TranslatePage(page_lang, chrome_lang);
+ return;
+ }
+
+ // Prompts the user if he/she wants the page translated.
+ tab->AddInfoBar(new BeforeTranslateInfoBarDelegate(tab, prefs,
+ entry->url(),
+ page_lang, chrome_lang));
+}
+
+PrefService* TranslateManager::GetPrefService(TabContents* tab) {
+ PrefService* prefs = NULL;
+ if (tab->profile())
+ prefs = tab->profile()->GetPrefs();
+ if (prefs)
+ return prefs;
+
+ return g_browser_process->local_state();
+}
diff --git a/chrome/browser/translate/translate_manager.h b/chrome/browser/translate/translate_manager.h
new file mode 100644
index 0000000..b51f089
--- /dev/null
+++ b/chrome/browser/translate/translate_manager.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_TRANSLATE_TRANSLATE_MANAGER_H_
+#define CHROME_BROWSER_TRANSLATE_TRANSLATE_MANAGER_H_
+
+#include <string>
+
+#include "base/singleton.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class PrefService;
+class TabContents;
+
+// The TranslateManager class is responsible for showing an info-bar when a page
+// in a language different than the user language is loaded. It triggers the
+// page translation the user requests.
+// It is a singleton.
+
+class TranslateManager : public NotificationObserver {
+ public:
+ virtual ~TranslateManager();
+
+ // NotificationObserver implementation:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+ private:
+ friend struct DefaultSingletonTraits<TranslateManager>;
+
+ TranslateManager();
+
+ // Starts the translation process on |tab| containing the page in the
+ // |page_lang| language.
+ void InitiateTranslation(TabContents* tab, const std::string& page_lang);
+
+ // Convenience method that retrieves the PrefService.
+ PrefService* GetPrefService(TabContents* tab);
+
+ NotificationRegistrar notification_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(TranslateManager);
+};
+
+#endif // CHROME_BROWSER_TRANSLATE_TRANSLATE_MANAGER_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index c3d1ba5..06ca294 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1677,6 +1677,8 @@
'browser/translate/options_menu_model.h',
'browser/translate/translate_infobars_delegates.cc',
'browser/translate/translate_infobars_delegates.h',
+ 'browser/translate/translate_manager.cc',
+ 'browser/translate/translate_manager.h',
'browser/translate/translate_prefs.cc',
'browser/translate/translate_prefs.h',
'browser/user_data_manager.cc',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 574752a..85739da 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -31,10 +31,6 @@ const char kApp[] = "app";
// automation-related messages on IPC channel with the given ID.
const char kAutomationClientChannelID[] = "automation-channel";
-// Makes Chrome translate any page loaded which is not in the locale Chrome
-// is running in.
-const char kAutoPageTranslate[] = "auto-translate";
-
// Enables the bookmark menu.
const char kBookmarkMenu[] = "bookmark-menu";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 4f8d4d6..69db6fa 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -24,7 +24,6 @@ extern const char kAllowSandboxDebugging[];
extern const char kAlwaysEnableDevTools[];
extern const char kApp[];
extern const char kAutomationClientChannelID[];
-extern const char kAutoPageTranslate[];
extern const char kBookmarkMenu[];
extern const char kBrowserAssertTest[];
extern const char kBrowserCrashTest[];
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index f05482f..9e336e0 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -225,9 +225,15 @@ class NotificationType {
// Sent when the language (English, French...) for a page has been detected.
// The details Details<std::string> contain the ISO 639-1 language code and
- // the source is Source<RenderViewHost>.
+ // the source is Source<TabContents>.
TAB_LANGUAGE_DETERMINED,
+ // Sent when a page has been translated. The source is the tab for that page
+ // (Source<TabContents>) and the details are the language the page was
+ // originally in and the language it was translated to
+ // (std::pair<std::string, std::string>).
+ PAGE_TRANSLATED,
+
// Sent after the renderer returns a snapshot of tab contents.
TAB_SNAPSHOT_TAKEN,
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 55414a7..b7ad8d4 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1989,6 +1989,12 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED1(ViewHostMsg_PageLanguageDetermined,
std::string /* the language */)
+ // Notifies the browser that a page has been translated.
+ IPC_MESSAGE_ROUTED3(ViewHostMsg_PageTranslated,
+ int, /* page id */
+ std::string /* the original language */,
+ std::string /* the translated language */)
+
//---------------------------------------------------------------------------
// Socket Stream messages:
// These are messages from the SocketStreamHandle to the browser.
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index d4c1c36..5eea4b3 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -312,7 +312,7 @@ RenderView::RenderView(RenderThreadBase* render_thread,
webkit_preferences_(webkit_preferences),
session_storage_namespace_id_(session_storage_namespace_id),
ALLOW_THIS_IN_INITIALIZER_LIST(text_translator_(this)) {
- page_translator_.reset(new PageTranslator(&text_translator_));
+ page_translator_.reset(new PageTranslator(&text_translator_, this));
}
RenderView::~RenderView() {
@@ -2872,6 +2872,13 @@ void RenderView::DidStopLoadingForPlugin() {
didStopLoading();
}
+void RenderView::PageTranslated(int page_id,
+ const std::string& original_lang,
+ const std::string& target_lang) {
+ Send(new ViewHostMsg_PageTranslated(routing_id_, page_id_,
+ original_lang, target_lang));
+}
+
void RenderView::ShowModalHTMLDialogForPlugin(
const GURL& url,
const gfx::Size& size,
@@ -3376,7 +3383,7 @@ void RenderView::OnTranslatePage(int page_id,
WebFrame* main_frame = webview()->mainFrame();
if (!main_frame)
return;
- page_translator_->Translate(main_frame, source_lang, target_lang);
+ page_translator_->Translate(page_id, main_frame, source_lang, target_lang);
}
void RenderView::OnTranslateTextResponse(
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index a96ee39..3523238 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -123,7 +123,8 @@ class RenderView : public RenderWidget,
public WebKit::WebFrameClient,
public WebKit::WebPageSerializerClient,
public webkit_glue::WebPluginPageDelegate,
- public base::SupportsWeakPtr<RenderView> {
+ public base::SupportsWeakPtr<RenderView>,
+ public PageTranslator::PageTranslatorDelegate {
public:
// Visit all RenderViews with a live WebView (i.e., RenderViews that have
// been closed but not yet destroyed are excluded).
@@ -387,6 +388,11 @@ class RenderView : public RenderWidget,
const std::string& json_arguments,
std::string* json_retval);
+ // PageTranslator::PageTranslatorDelegate implementation:
+ virtual void PageTranslated(int page_id,
+ const std::string& original_lang,
+ const std::string& target_lang);
+
// Do not delete directly. This class is reference counted.
virtual ~RenderView();
diff --git a/chrome/renderer/translate/page_translator.cc b/chrome/renderer/translate/page_translator.cc
index df0a59b..ab4d806 100644
--- a/chrome/renderer/translate/page_translator.cc
+++ b/chrome/renderer/translate/page_translator.cc
@@ -44,8 +44,11 @@ bool PageTranslator::WebStringCompare::operator()(
return len1 < len2;
}
-PageTranslator::PageTranslator(TextTranslator* text_translator)
- : text_translator_(text_translator) {
+PageTranslator::PageTranslator(TextTranslator* text_translator,
+ PageTranslatorDelegate* delegate)
+ : delegate_(delegate),
+ text_translator_(text_translator),
+ page_id_(-1) {
for (size_t i = 0; i < arraysize(kSkippedTags); ++i)
ignored_tags_.insert(WebKit::WebString(ASCIIToUTF16(kSkippedTags[i])));
for (size_t i = 0; i < arraysize(kInlineTags); ++i)
@@ -53,13 +56,35 @@ PageTranslator::PageTranslator(TextTranslator* text_translator)
}
PageTranslator::~PageTranslator() {
- STLDeleteContainerPairSecondPointers(pending_translations_.begin(),
- pending_translations_.end());
+ ResetPageStates(); // This deletes pending translations.
}
-void PageTranslator::Translate(WebKit::WebFrame* web_frame,
- std::string from_lang,
- std::string to_lang) {
+void PageTranslator::Translate(int page_id,
+ WebKit::WebFrame* web_frame,
+ std::string source_lang,
+ std::string target_lang) {
+ if (page_id != page_id_) {
+ // This is a new page, our states are invalid.
+ ResetPageStates();
+ page_id_ = page_id;
+ }
+ if (original_language_.empty()) {
+ original_language_ = source_lang;
+ current_language_ = source_lang;
+ }
+ if (original_language_ != current_language_) {
+ // The page has already been translated.
+ if (target_lang == current_language_) {
+ NOTREACHED();
+ return;
+ }
+ // TODO(jcampan): implement translation of an already translated page.
+ return;
+ }
+
+ // We are about to start the translation process.
+ current_language_ = target_lang;
+
std::stack<NodeList*> node_list_stack;
std::vector<NodeList*> text_node_lists;
TraverseNode(web_frame->document(), &node_list_stack, &text_node_lists);
@@ -85,15 +110,15 @@ void PageTranslator::Translate(WebKit::WebFrame* web_frame,
// Send the text for translation.
bool secure = static_cast<GURL>(web_frame->top()->url()).SchemeIsSecure();
int work_id =
- text_translator_->Translate(text_chunks, from_lang, to_lang, secure,
- this);
+ text_translator_->Translate(text_chunks, source_lang, target_lang,
+ secure, this);
pending_translations_[work_id] = *iter;
}
}
void PageTranslator::NavigatedToNewPage() {
// We can drop all our states, they were related to the previous page.
- ResetPageState();
+ ResetPageStates();
}
void PageTranslator::UndoTranslation() {
@@ -102,8 +127,11 @@ void PageTranslator::UndoTranslation() {
for (iter = text_nodes_.begin(); iter != text_nodes_.end(); ++iter)
iter->first.setNodeValue(iter->second);
- // The page is back to its original content, we can dop all our states.
- ResetPageState();
+ // The page is back to its original content, we can dop all our states but the
+ // page id.
+ int page_id = page_id_;
+ ResetPageStates();
+ page_id_ = page_id;
}
bool PageTranslator::ShouldElementBeTraversed(WebKit::WebElement element) {
@@ -125,11 +153,6 @@ void PageTranslator::ClearNodeZone(int work_id) {
pending_translations_.erase(iter);
}
-void PageTranslator::ResetPageState() {
- pending_translations_.clear();
- text_nodes_.clear();
-}
-
void PageTranslator::TranslationError(int work_id, int error_id) {
// TODO(jcampan): may be we should show somehow that something went wrong to
// the user?
@@ -152,6 +175,7 @@ void PageTranslator::TextTranslated(
// anchor tags.
// NOTREACHED() << "Translation results received are inconsistent with the "
// "request";
+ ClearNodeZone(work_id);
return;
}
@@ -159,6 +183,9 @@ void PageTranslator::TextTranslated(
(*nodes)[i].setNodeValue(WebKit::WebString(translated_text_chunks[i]));
ClearNodeZone(work_id);
+
+ if (delegate_ && pending_translations_.empty())
+ delegate_->PageTranslated(page_id_, original_language_, current_language_);
}
void PageTranslator::TraverseNode(WebKit::WebNode node,
@@ -208,3 +235,12 @@ void PageTranslator::TraverseNode(WebKit::WebNode node,
delete text_nodes;
}
}
+
+void PageTranslator::ResetPageStates() {
+ page_id_ = -1;
+ original_language_.clear();
+ current_language_.clear();
+ text_nodes_.clear();
+ // Remove pending translations.
+ STLDeleteValues(&pending_translations_);
+}
diff --git a/chrome/renderer/translate/page_translator.h b/chrome/renderer/translate/page_translator.h
index 14139227..08de0b1 100644
--- a/chrome/renderer/translate/page_translator.h
+++ b/chrome/renderer/translate/page_translator.h
@@ -31,15 +31,29 @@ class WebString;
// and delegates the actual text translation to a TextTranslator.
class PageTranslator : public TextTranslator::Delegate {
public:
+ // Note that we don't use the simpler name Delegate as it seems to freak-out
+ // the VisualStudio 2005 compiler in render_view.cc. (RenderView would be
+ // implementing PageTranslator::Delegate that somehow confuses the compiler
+ // into thinking we are talkin about TextTranslator::Delegate.)
+ class PageTranslatorDelegate {
+ public:
+ virtual ~PageTranslatorDelegate() {}
+ virtual void PageTranslated(int page_id,
+ const std::string& original_lang,
+ const std::string& target_lang) = 0;
+ };
+
// The caller remains the owner of |text_translator|.
- explicit PageTranslator(TextTranslator* text_translator);
+ PageTranslator(TextTranslator* text_translator,
+ PageTranslatorDelegate* delegate);
virtual ~PageTranslator();
- // Starts the translation process of |web_frame| from |from_lang| to |to_lang|
- // where the languages are the ISO codes (ex: en, fr...).
- void Translate(WebKit::WebFrame* web_frame,
- std::string from_lang,
- std::string to_lang);
+ // Starts the translation process of |web_frame| from |source_lang| to
+ // |target_lang| where the languages are the ISO codes (ex: en, fr...).
+ void Translate(int page_id,
+ WebKit::WebFrame* web_frame,
+ std::string source_lang,
+ std::string target_lang);
// Notification that the associated RenderView has navigated to a new page.
void NavigatedToNewPage();
@@ -80,10 +94,10 @@ class PageTranslator : public TextTranslator::Delegate {
void ClearNodeZone(int work_id);
// Clears all the states related to the page's contents.
- void ResetPageState();
+ void ResetPageStates();
- // The RenderView we are providing translations for.
- RenderView* render_view_;
+ // Our delegate (notified when a page is translated).
+ PageTranslatorDelegate* delegate_;
// The TextTranslator is responsible for translating the actual text chunks
// from one language to another.
@@ -98,6 +112,15 @@ class PageTranslator : public TextTranslator::Delegate {
// Mapping from a translation engine work id to the associated nodes.
std::map<int, NodeList*> pending_translations_;
+ // The language the page was in originally.
+ std::string original_language_;
+
+ // The language the page was translated to.
+ std::string current_language_;
+
+ // The page id of the page last time we translated.
+ int page_id_;
+
// The list of text nodes in the current page with their original text.
// Used to undo the translation.
typedef std::pair<WebKit::WebNode, WebKit::WebString> NodeTextPair;
diff --git a/chrome/renderer/translate/page_translator_unittest.cc b/chrome/renderer/translate/page_translator_unittest.cc
index 4bc1e02..4ab6c482 100644
--- a/chrome/renderer/translate/page_translator_unittest.cc
+++ b/chrome/renderer/translate/page_translator_unittest.cc
@@ -168,8 +168,8 @@ TEST_F(TranslatorTest, DISABLED_TranslatePages) {
// Translate it.
ReverseTextTranslator text_translator;
- PageTranslator translator(&text_translator);
- translator.Translate(web_frame, "en", "fr");
+ PageTranslator translator(&text_translator, NULL);
+ translator.Translate(0, web_frame, "en", "fr");
// Translation is asynchronous, so we need to process the pending messages
// to make it happen.
diff --git a/chrome/test/ui_test_utils.cc b/chrome/test/ui_test_utils.cc
index 4c04d20..3dc51ec 100644
--- a/chrome/test/ui_test_utils.cc
+++ b/chrome/test/ui_test_utils.cc
@@ -259,10 +259,9 @@ class SimpleNotificationObserver : public NotificationObserver {
class LanguageDetectionNotificationObserver : public NotificationObserver {
public:
- explicit LanguageDetectionNotificationObserver(
- RenderViewHost* render_view_host) {
+ explicit LanguageDetectionNotificationObserver(TabContents* tab) {
registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED,
- Source<RenderViewHost>(render_view_host));
+ Source<TabContents>(tab));
ui_test_utils::RunMessageLoop();
}
@@ -522,7 +521,7 @@ void WaitForFocusInBrowser(Browser* browser) {
}
std::string WaitForLanguageDetection(TabContents* tab) {
- LanguageDetectionNotificationObserver observer(tab->render_view_host());
+ LanguageDetectionNotificationObserver observer(tab);
return observer.language();
}