Commit 3dda5b0f authored by alyssad@chromium.org's avatar alyssad@chromium.org

New pyauto hook for the translate feature.

Review URL: http://codereview.chromium.org/3026016

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53791 0039d316-1c4b-4281-b951-d872f2087c98
parent 0f86277d
......@@ -2744,6 +2744,131 @@ void AutomationProvider::ClearBrowsingData(Browser* browser,
// The observer also deletes itself after sending the reply.
}
namespace {
// Get the TabContents from a dictionary of arguments.
TabContents* GetTabContentsFromDict(const Browser* browser,
const DictionaryValue* args,
std::string* error_message) {
int tab_index;
if (!args->GetInteger(L"tab_index", &tab_index)) {
*error_message = "Must include tab_index.";
return NULL;
}
TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
if (!tab_contents) {
*error_message = StringPrintf("No tab at index %d.", tab_index);
return NULL;
}
return tab_contents;
}
// Get the TranslateInfoBarDelegate from TabContents.
TranslateInfoBarDelegate* GetTranslateInfoBarDelegate(
TabContents* tab_contents) {
for (int i = 0; i < tab_contents->infobar_delegate_count(); i++) {
InfoBarDelegate* infobar = tab_contents->GetInfoBarDelegateAt(i);
if (infobar->AsTranslateInfoBarDelegate())
return infobar->AsTranslateInfoBarDelegate();
}
// No translate infobar.
return NULL;
}
} // namespace
// See GetTranslateInfo() in chrome/test/pyautolib/pyauto.py for sample json
// input and output.
void AutomationProvider::GetTranslateInfo(Browser* browser,
DictionaryValue* args,
IPC::Message* reply_message) {
std::string error_message;
TabContents* tab_contents = GetTabContentsFromDict(browser, args,
&error_message);
if (!tab_contents) {
AutomationJSONReply(this, reply_message).SendError(error_message);
return;
}
// Get the translate bar if there is one and pass it to the observer.
// The observer will check for null and populate the information accordingly.
TranslateInfoBarDelegate* translate_bar =
GetTranslateInfoBarDelegate(tab_contents);
TabLanguageDeterminedObserver* observer = new TabLanguageDeterminedObserver(
this, reply_message, tab_contents, translate_bar);
// If the language for the page hasn't been loaded yet, then just make
// the observer, otherwise call observe directly.
std::string language = tab_contents->language_state().original_language();
if (!language.empty()) {
observer->Observe(NotificationType::TAB_LANGUAGE_DETERMINED,
Source<TabContents>(tab_contents),
Details<std::string>(&language));
}
}
// See SelectTranslateOption() in chrome/test/pyautolib/pyauto.py for sample
// json input.
// Sample json output: {}
void AutomationProvider::SelectTranslateOption(Browser* browser,
DictionaryValue* args,
IPC::Message* reply_message) {
std::string option;
std::string error_message;
TabContents* tab_contents = GetTabContentsFromDict(browser, args,
&error_message);
if (!tab_contents) {
AutomationJSONReply(this, reply_message).SendError(error_message);
return;
}
TranslateInfoBarDelegate* translate_bar =
GetTranslateInfoBarDelegate(tab_contents);
if (!translate_bar) {
AutomationJSONReply(this, reply_message)
.SendError("There is no translate bar open.");
return;
}
if (!args->GetString(L"option", &option)) {
AutomationJSONReply(this, reply_message).SendError("Must include option");
return;
}
if (option == "translate_page") {
// Make a new notification observer which will send the reply.
new PageTranslatedObserver(this, reply_message, tab_contents);
translate_bar->Translate();
return;
}
AutomationJSONReply reply(this, reply_message);
if (option == "never_translate_language") {
if (translate_bar->IsLanguageBlacklisted()) {
reply.SendError("The language was already blacklisted.");
return;
}
translate_bar->ToggleLanguageBlacklist();
reply.SendSuccess(NULL);
} else if (option == "never_translate_site") {
if (translate_bar->IsSiteBlacklisted()) {
reply.SendError("The site was already blacklisted.");
return;
}
translate_bar->ToggleSiteBlacklist();
reply.SendSuccess(NULL);
} else if (option == "toggle_always_translate") {
translate_bar->ToggleAlwaysTranslate();
reply.SendSuccess(NULL);
} else if (option == "revert_translation") {
translate_bar->RevertTranslation();
reply.SendSuccess(NULL);
} else {
reply.SendError("Invalid string found for option.");
}
}
// Sample json input: { "command": "GetThemeInfo" }
// Refer GetThemeInfo() in chrome/test/pyautolib/pyauto.py for sample output.
void AutomationProvider::GetThemeInfo(Browser* browser,
......@@ -3091,6 +3216,10 @@ void AutomationProvider::SendJSONRequest(int handle,
// SetTheme() implemented using InstallExtension().
handler_map["GetThemeInfo"] = &AutomationProvider::GetThemeInfo;
handler_map["SelectTranslateOption"] =
&AutomationProvider::SelectTranslateOption;
handler_map["GetTranslateInfo"] = &AutomationProvider::GetTranslateInfo;
handler_map["GetAutoFillProfile"] = &AutomationProvider::GetAutoFillProfile;
handler_map["FillAutoFillProfile"] = &AutomationProvider::FillAutoFillProfile;
......
......@@ -57,6 +57,7 @@ class LoginHandler;
class MetricEventDurationObserver;
class InitialLoadObserver;
class NavigationControllerRestoredObserver;
class TranslateInfoBarDelegate;
struct AutocompleteMatchData;
namespace gfx {
......@@ -506,6 +507,18 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
DictionaryValue* args,
IPC::Message* reply_message);
// Returns information about translation for a given tab. Includes
// information about the translate bar if it is showing.
void GetTranslateInfo(Browser* browser,
DictionaryValue* args,
IPC::Message* reply_message);
// Takes the specified action on the translate bar.
// Uses the JSON interface for input/output.
void SelectTranslateOption(Browser* browser,
DictionaryValue* args,
IPC::Message* reply_message);
// Get the profiles that are currently saved to the DB.
// Uses the JSON interface for input/output.
void GetAutoFillProfile(Browser* browser,
......
......@@ -23,6 +23,8 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/translate/page_translated_details.h"
#include "chrome/browser/translate/translate_infobar_delegate.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/automation/automation_constants.h"
......@@ -929,6 +931,82 @@ void MetricEventDurationObserver::Observe(NotificationType type,
metric_event_duration->duration_ms;
}
PageTranslatedObserver::PageTranslatedObserver(AutomationProvider* automation,
IPC::Message* reply_message,
TabContents* tab_contents)
: automation_(automation),
reply_message_(reply_message) {
registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
Source<TabContents>(tab_contents));
}
void PageTranslatedObserver::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
DCHECK(type == NotificationType::PAGE_TRANSLATED);
AutomationJSONReply reply(automation_, reply_message_);
PageTranslatedDetails* translated_details =
Details<PageTranslatedDetails>(details).ptr();
scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
return_value->SetBoolean(
L"translation_success",
translated_details->error_type == TranslateErrors::NONE);
reply.SendSuccess(return_value.get());
delete this;
}
TabLanguageDeterminedObserver::TabLanguageDeterminedObserver(
AutomationProvider* automation, IPC::Message* reply_message,
TabContents* tab_contents, TranslateInfoBarDelegate* translate_bar)
: automation_(automation),
reply_message_(reply_message),
tab_contents_(tab_contents),
translate_bar_(translate_bar) {
registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED,
Source<TabContents>(tab_contents));
}
void TabLanguageDeterminedObserver::Observe(
NotificationType type, const NotificationSource& source,
const NotificationDetails& details) {
DCHECK(type == NotificationType::TAB_LANGUAGE_DETERMINED);
scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
return_value->SetBoolean(L"page_translated",
tab_contents_->language_state().IsPageTranslated());
return_value->SetBoolean(
L"can_translate_page", TranslatePrefs::CanTranslate(
automation_->profile()->GetPrefs(),
tab_contents_->language_state().original_language(),
tab_contents_->GetURL()));
return_value->SetString(
L"original_language",
tab_contents_->language_state().original_language());
if (translate_bar_) {
DictionaryValue* bar_info = new DictionaryValue;
std::map<TranslateInfoBarDelegate::Type, std::string> type_to_string;
type_to_string[TranslateInfoBarDelegate::BEFORE_TRANSLATE] =
"BEFORE_TRANSLATE";
type_to_string[TranslateInfoBarDelegate::TRANSLATING] =
"TRANSLATING";
type_to_string[TranslateInfoBarDelegate::AFTER_TRANSLATE] =
"AFTER_TRANSLATE";
type_to_string[TranslateInfoBarDelegate::TRANSLATION_ERROR] =
"TRANSLATION_ERROR";
bar_info->SetString(L"bar_state", type_to_string[translate_bar_->type()]);
bar_info->SetString(L"target_lang_code",
translate_bar_->GetTargetLanguageCode());
bar_info->SetString(L"original_lang_code",
translate_bar_->GetOriginalLanguageCode());
return_value->Set(L"translate_bar", bar_info);
}
AutomationJSONReply(automation_, reply_message_)
.SendSuccess(return_value.get());
delete this;
}
#if defined(OS_CHROMEOS)
LoginManagerObserver::LoginManagerObserver(
AutomationProvider* automation,
......
......@@ -30,6 +30,7 @@ class ExtensionProcessManager;
class NavigationController;
class SavePackage;
class TabContents;
class TranslateInfoBarDelegate;
namespace IPC {
class Message;
......@@ -487,6 +488,47 @@ class MetricEventDurationObserver : public NotificationObserver {
DISALLOW_COPY_AND_ASSIGN(MetricEventDurationObserver);
};
class PageTranslatedObserver : public NotificationObserver {
public:
PageTranslatedObserver(AutomationProvider* automation,
IPC::Message* reply_message,
TabContents* tab_contents);
// NotificationObserver interface.
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
private:
NotificationRegistrar registrar_;
scoped_refptr<AutomationProvider> automation_;
IPC::Message* reply_message_;
DISALLOW_COPY_AND_ASSIGN(PageTranslatedObserver);
};
class TabLanguageDeterminedObserver : public NotificationObserver {
public:
TabLanguageDeterminedObserver(AutomationProvider* automation,
IPC::Message* reply_message,
TabContents* tab_contents,
TranslateInfoBarDelegate* translate_bar);
// NotificationObserver interface.
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
private:
NotificationRegistrar registrar_;
AutomationProvider* automation_;
IPC::Message* reply_message_;
TabContents* tab_contents_;
TranslateInfoBarDelegate* translate_bar_;
DISALLOW_COPY_AND_ASSIGN(TabLanguageDeterminedObserver);
};
#if defined(OS_CHROMEOS)
// Collects LOGIN_AUTHENTICATION notifications and returns
// whether authentication succeeded to the automation provider.
......
......@@ -40,6 +40,7 @@
'special_tabs',
'test_basic.SimpleTest.testCanOpenGoogle',
'themes',
'translate',
],
'win': [
......
#!/usr/bin/python
# 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.
import pyauto_functional # Must be imported before pyauto
import pyauto
class TranslateTest(pyauto.PyUITest):
"""Tests that translate works correctly"""
spanish_google = 'http://www.google.com/webhp?hl=es'
spanish = 'es'
after_translate = 'AFTER_TRANSLATE'
before_translate = 'BEFORE_TRANSLATE'
translating = 'TRANSLATING'
translation_error = 'TRANSLATION_ERROR'
def Debug(self):
""" Test method for experimentation. """
import pprint
pp = pprint.PrettyPrinter(indent=2)
while True:
raw_input('Hit <enter> to dump translate info.. ')
pp.pprint(self.GetTranslateInfo())
def _NavigateAndWaitForBar(self, url):
self.NavigateToURL(url)
self.WaitForInfobarCount(1)
def _ClickTranslateUntilSuccess(self):
"""Since the translate can fail due to server error, continue trying until
it is successful or until it has tried too many times."""
max_tries = 10
curr_try = 0
while curr_try < max_tries and not self.ClickTranslateBarTranslate():
curr_try = curr_try + 1
if curr_try == 10:
self.fail('Translation failed more than %d times.' % max_tries)
def testTranslate(self):
"""Tests that a page was translated if the user chooses to translate."""
self._NavigateAndWaitForBar(self.spanish_google)
self._ClickTranslateUntilSuccess()
translate_info = self.GetTranslateInfo()
self.assertEqual(self.spanish, translate_info['original_language'])
self.assertTrue(translate_info['page_translated'])
self.assertTrue(translate_info['can_translate_page'])
self.assertTrue('translate_bar' in translate_info)
self.assertEquals(self.after_translate,
translate_info['translate_bar']['bar_state'])
def testNoTranslate(self):
"""Tests that a page isn't translated if the user declines translate."""
self._NavigateAndWaitForBar(self.spanish_google)
self.PerformActionOnInfobar('dismiss', 0)
translate_info = self.GetTranslateInfo()
self.assertEqual(self.spanish, translate_info['original_language'])
self.assertFalse(translate_info['page_translated'])
self.assertTrue(translate_info['can_translate_page'])
# If the user goes to the site again, the infobar should drop down but
# the page should not be automatically translated.
self._NavigateAndWaitForBar(self.spanish_google)
translate_info = self.GetTranslateInfo()
self.assertFalse(translate_info['page_translated'])
self.assertTrue(translate_info['can_translate_page'])
self.assertTrue('translate_bar' in translate_info)
self.assertEquals(self.before_translate,
translate_info['translate_bar']['bar_state'])
def testNeverTranslateLanguage(self):
"""Tests that blacklisting a language for translate works."""
self._NavigateAndWaitForBar(self.spanish_google)
self.SelectTranslateOption('never_translate_language')
translate_info = self.GetTranslateInfo()
self.assertEqual(self.spanish, translate_info['original_language'])
self.assertFalse(translate_info['page_translated'])
self.assertFalse(translate_info['can_translate_page'])
spanish_wikipedia = 'http://es.wikipedia.org/wiki/Wikipedia:Portada'
self.NavigateToURL(spanish_wikipedia)
translate_info = self.GetTranslateInfo()
self.assertEqual(self.spanish, translate_info['original_language'])
self.assertFalse(translate_info['page_translated'])
self.assertFalse(translate_info['can_translate_page'])
def testAlwaysTranslateLanguage(self):
"""Tests that the always translate a language option works."""
self._NavigateAndWaitForBar(self.spanish_google)
self.SelectTranslateOption('toggle_always_translate')
self._ClickTranslateUntilSuccess()
translate_info = self.GetTranslateInfo()
self.assertEquals(self.spanish, translate_info['original_language'])
self.assertTrue(translate_info['page_translated'])
self.assertTrue(translate_info['can_translate_page'])
self.assertTrue('translate_bar' in translate_info)
self.assertEquals(self.after_translate,
translate_info['translate_bar']['bar_state'])
# Go to another spanish site and verify that it is translated.
# Note that the 'This page has been translated..." bar will show up.
self._NavigateAndWaitForBar(
'http://es.wikipedia.org/wiki/Wikipedia:Portada')
translate_info = self.GetTranslateInfo()
self.assertTrue('translate_bar' in translate_info)
curr_bar_state = translate_info['translate_bar']['bar_state']
# We don't care whether the translation has finished, just that it is
# trying to translate.
self.assertTrue(curr_bar_state is self.after_translate or
self.translating or self.translation_error,
'Bar state was %s.' % curr_bar_state)
def testNeverTranslateSite(self):
"""Tests that blacklisting a site for translate works."""
self._NavigateAndWaitForBar(self.spanish_google)
self.SelectTranslateOption('never_translate_site')
translate_info = self.GetTranslateInfo()
self.assertFalse(translate_info['page_translated'])
self.assertFalse(translate_info['can_translate_page'])
french_google = 'http://www.google.com/webhp?hl=fr'
# Go to another page in the same site and verify that the page can't be
# translated even though it's in a different language.
self.NavigateToURL(french_google)
translate_info = self.GetTranslateInfo()
self.assertFalse(translate_info['page_translated'])
self.assertFalse(translate_info['can_translate_page'])
def testRevert(self):
"""Tests that reverting a site to its original language works."""
self._NavigateAndWaitForBar(self.spanish_google)
self._ClickTranslateUntilSuccess()
self.RevertPageTranslation()
translate_info = self.GetTranslateInfo()
self.assertFalse(translate_info['page_translated'])
self.assertTrue(translate_info['can_translate_page'])
if __name__ == '__main__':
pyauto_functional.Main()
......@@ -646,6 +646,101 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase):
return history_info.HistoryInfo(
self._SendJSONRequest(0, json.dumps(cmd_dict)))
def GetTranslateInfo(self, tab_index=0, window_index=0):
"""Returns info about translate for the given page.
If the translate bar is showing, also returns information about the bar.
Args:
tab_index: The tab index, default is 0.
window_index: The window index, default is 0.
Returns:
A dictionary of information about translate for the page. Example:
{ u'can_translate_page': True,
u'original_language': u'es',
u'page_translated': False,
# The below will only appear if the translate bar is showing.
u'translate_bar': { u'bar_state': u'BEFORE_TRANSLATE',
u'original_lang_code': u'es',
u'target_lang_code': u'en'}}
"""
cmd_dict = { # Prepare command for the json interface
'command': 'GetTranslateInfo',
'tab_index': tab_index
}
return self._GetResultFromJSONRequest(cmd_dict, windex=window_index)
def ClickTranslateBarTranslate(self, tab_index=0, window_index=0):
"""If the translate bar is showing, clicks the 'Translate' button on the
bar. This will show the 'this page has been translated...' infobar.
Args:
tab_index: The index of the tab, default is 0.
window_index: The index of the window, default is 0.
Returns:
True if the translation was successful or false if there was an error.
Note that an error shouldn't neccessarily mean a failed test - retry the
call on error.
Raises:
pyauto_errors.JSONInterfaceError if the automation returns an error.
"""
cmd_dict = { # Prepare command for the json interface
'command': 'SelectTranslateOption',
'tab_index': tab_index,
'option': 'translate_page'
}
return self._GetResultFromJSONRequest(
cmd_dict, windex=window_index)['translation_success']
def RevertPageTranslation(self, tab_index=0, window_index=0):
"""Select the 'Show original' button on the 'this page has been
translated...' infobar. This will remove the infobar and revert the
page translation.
Args:
tab_index: The index of the tab, default is 0.
window_index: The index of the window, default is 0.
"""
cmd_dict = { # Prepare command for the json interface
'command': 'SelectTranslateOption',
'tab_index': tab_index,
'option': 'revert_translation'
}
self._GetResultFromJSONRequest(cmd_dict, windex=window_index)
def SelectTranslateOption(self, option, tab_index=0, window_index=0):
"""Selects one of the options in the drop-down menu for the translate bar.
Args:
option: One of 'never_translate_language', 'never_translate_site', or
'toggle_always_translate'. See notes on each below.
tab_index: The index of the tab, default is 0.
window_index: The index of the window, default is 0.
*Notes*
never translate language: Selecting this means that no sites in this
language will be translated. This dismisses the infobar.
never translate site: Selecting this means that this site will never be
translated, regardless of the language. This dismisses the infobar.
toggle always translate: This does not dismiss the infobar or translate the
page. See ClickTranslateBarTranslate and PerformActioOnInfobar to do
those. If a language is selected to be always translated, then whenver
the user visits a page with that language, the infobar will show the
'This page has been translated...' message.
Raises:
pyauto_errors.JSONInterfaceError if the automation returns an error.
"""
cmd_dict = { # Prepare command for the json interface
'command': 'SelectTranslateOption',
'option': option,
'tab_index': tab_index
}
self._GetResultFromJSONRequest(cmd_dict, windex=window_index)
def FillAutoFillProfile(self, profiles=None, credit_cards=None,
tab_index=0, window_index=0):
"""Set the autofill profile to contain the given profiles and credit cards.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment