summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/automation/automation_provider_observers.cc7
-rw-r--r--chrome/browser/automation/automation_provider_observers.h5
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc144
-rw-r--r--chrome/browser/automation/testing_automation_provider.h26
-rw-r--r--chrome/test/functional/search_engines.py78
-rw-r--r--chrome/test/pyautolib/pyauto.py101
6 files changed, 296 insertions, 65 deletions
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index af0cac0..d836bee 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -1192,13 +1192,8 @@ void AutomationProviderDownloadModelChangedObserver::ModelChanged() {
void AutomationProviderSearchEngineObserver::OnTemplateURLModelChanged() {
TemplateURLModel* url_model = provider_->profile()->GetTemplateURLModel();
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- return_value->Set("search_engines",
- provider_->ExtractSearchEngineInfo(url_model));
-
url_model->RemoveObserver(this);
- AutomationJSONReply(provider_, reply_message_).SendSuccess(
- return_value.get());
+ AutomationJSONReply(provider_, reply_message_).SendSuccess(NULL);
delete this;
}
diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h
index bc2fdb7..8706d85 100644
--- a/chrome/browser/automation/automation_provider_observers.h
+++ b/chrome/browser/automation/automation_provider_observers.h
@@ -10,7 +10,6 @@
#include <map>
#include <set>
-#include "chrome/browser/automation/testing_automation_provider.h"
#include "chrome/browser/bookmarks/bookmark_model_observer.h"
#include "chrome/browser/browsing_data_remover.h"
#include "chrome/browser/download/download_item.h"
@@ -740,7 +739,7 @@ class AutomationProviderSearchEngineObserver
: public TemplateURLModelObserver {
public:
AutomationProviderSearchEngineObserver(
- TestingAutomationProvider* provider,
+ AutomationProvider* provider,
IPC::Message* reply_message)
: provider_(provider),
reply_message_(reply_message) {}
@@ -748,7 +747,7 @@ class AutomationProviderSearchEngineObserver
void OnTemplateURLModelChanged();
private:
- TestingAutomationProvider* provider_;
+ AutomationProvider* provider_;
IPC::Message* reply_message_;
DISALLOW_COPY_AND_ASSIGN(AutomationProviderSearchEngineObserver);
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index 14bc906..7e6ed0c 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -46,6 +46,7 @@
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/search_engines/keyword_editor_controller.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
@@ -430,25 +431,6 @@ void TestingAutomationProvider::OnChannelError() {
AutomationProvider::OnChannelError();
}
-ListValue* TestingAutomationProvider::ExtractSearchEngineInfo(
- TemplateURLModel* url_model) {
- ListValue* search_engines = new ListValue;
- std::vector<const TemplateURL*> template_urls = url_model->GetTemplateURLs();
- for (std::vector<const TemplateURL*>::const_iterator it =
- template_urls.begin();
- it != template_urls.end(); ++it) {
- DictionaryValue* search_engine = new DictionaryValue;
- search_engine->SetString("short_name", WideToUTF8((*it)->short_name()));
- search_engine->SetString("description", WideToUTF8((*it)->description()));
- search_engine->SetString("keyword", WideToUTF8((*it)->keyword()));
- search_engine->SetBoolean("in_default_list", (*it)->ShowInDefaultList());
- search_engine->SetBoolean("is_default",
- (*it) == url_model->GetDefaultSearchProvider());
- search_engines->Append(search_engine);
- }
- return search_engines;
-}
-
void TestingAutomationProvider::CloseBrowser(int browser_handle,
IPC::Message* reply_message) {
if (browser_tracker_->ContainsHandle(browser_handle)) {
@@ -2048,8 +2030,14 @@ void TestingAutomationProvider::SendJSONRequest(int handle,
handler_map["OmniboxMovePopupSelection"] =
&TestingAutomationProvider::OmniboxMovePopupSelection;
+ handler_map["LoadSearchEngineInfo"] =
+ &TestingAutomationProvider::LoadSearchEngineInfo;
handler_map["GetSearchEngineInfo"] =
&TestingAutomationProvider::GetSearchEngineInfo;
+ handler_map["AddOrEditSearchEngine"] =
+ &TestingAutomationProvider::AddOrEditSearchEngine;
+ handler_map["PerformActionOnSearchEngine"] =
+ &TestingAutomationProvider::PerformActionOnSearchEngine;
handler_map["GetPrefsInfo"] = &TestingAutomationProvider::GetPrefsInfo;
handler_map["SetPrefs"] = &TestingAutomationProvider::SetPrefs;
@@ -2675,19 +2663,127 @@ void TestingAutomationProvider::PerformActionOnDownload(
}
}
-void TestingAutomationProvider::GetSearchEngineInfo(
+// Sample JSON input { "command": "LoadSearchEngineInfo" }
+void TestingAutomationProvider::LoadSearchEngineInfo(
Browser* browser,
DictionaryValue* args,
IPC::Message* reply_message) {
TemplateURLModel* url_model(profile_->GetTemplateURLModel());
if (url_model->loaded()) {
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- return_value->Set("search_engines", ExtractSearchEngineInfo(url_model));
- AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
+ AutomationJSONReply(this, reply_message).SendSuccess(NULL);
+ return;
+ }
+ url_model->AddObserver(new AutomationProviderSearchEngineObserver(
+ this, reply_message));
+ url_model->Load();
+}
+
+// Sample JSON input { "command": "GetSearchEngineInfo" }
+// Refer to pyauto.py for sample output.
+void TestingAutomationProvider::GetSearchEngineInfo(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ TemplateURLModel* url_model(profile_->GetTemplateURLModel());
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ ListValue* search_engines = new ListValue;
+ std::vector<const TemplateURL*> template_urls = url_model->GetTemplateURLs();
+ for (std::vector<const TemplateURL*>::const_iterator it =
+ template_urls.begin(); it != template_urls.end(); ++it) {
+ DictionaryValue* search_engine = new DictionaryValue;
+ search_engine->SetString("short_name", WideToUTF8((*it)->short_name()));
+ search_engine->SetString("description", WideToUTF8((*it)->description()));
+ search_engine->SetString("keyword", WideToUTF8((*it)->keyword()));
+ search_engine->SetBoolean("in_default_list", (*it)->ShowInDefaultList());
+ search_engine->SetBoolean("is_default",
+ (*it) == url_model->GetDefaultSearchProvider());
+ search_engine->SetBoolean("is_valid", (*it)->url()->IsValid());
+ search_engine->SetBoolean("supports_replacement",
+ (*it)->url()->SupportsReplacement());
+ search_engine->SetString("url", (*it)->url()->url());
+ search_engine->SetString("host", (*it)->url()->GetHost());
+ search_engine->SetString("path", (*it)->url()->GetPath());
+ search_engine->SetString("display_url",
+ WideToUTF8((*it)->url()->DisplayURL()));
+ search_engines->Append(search_engine);
+ }
+ return_value->Set("search_engines", search_engines);
+ AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
+}
+
+// Refer to pyauto.py for sample JSON input.
+void TestingAutomationProvider::AddOrEditSearchEngine(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ TemplateURLModel* url_model(profile_->GetTemplateURLModel());
+ const TemplateURL* template_url;
+ string16 new_title;
+ string16 new_keyword;
+ std::string new_url;
+ std::string keyword;
+ if (!args->GetString("new_title", &new_title) ||
+ !args->GetString("new_keyword", &new_keyword) ||
+ !args->GetString("new_url", &new_url)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "One or more inputs invalid");
+ return;
+ }
+ std::string new_ref_url = TemplateURLRef::DisplayURLToURLRef(
+ UTF8ToWide(new_url));
+ scoped_ptr<KeywordEditorController> controller(
+ new KeywordEditorController(profile_));
+ if (args->GetString("keyword", &keyword)) {
+ template_url = url_model->GetTemplateURLForKeyword(UTF8ToWide(keyword));
+ if (template_url == NULL) {
+ AutomationJSONReply(this, reply_message).SendError(
+ StringPrintf("No match for keyword: %s", keyword.c_str()));
+ return;
+ }
+ url_model->AddObserver(new AutomationProviderSearchEngineObserver(
+ this, reply_message));
+ controller->ModifyTemplateURL(template_url, new_title, new_keyword,
+ new_ref_url);
} else {
url_model->AddObserver(new AutomationProviderSearchEngineObserver(
+ this, reply_message));
+ controller->AddTemplateURL(new_title, new_keyword, new_ref_url);
+ }
+}
+
+// Sample json input: { "command": "PerformActionOnSearchEngine",
+// "keyword": keyword, "action": action }
+void TestingAutomationProvider::PerformActionOnSearchEngine(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ TemplateURLModel* url_model(profile_->GetTemplateURLModel());
+ std::string keyword;
+ std::string action;
+ if (!args->GetString("keyword", &keyword) ||
+ !args->GetString("action", &action)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "One or more inputs invalid");
+ return;
+ }
+ const TemplateURL* template_url(
+ url_model->GetTemplateURLForKeyword(UTF8ToWide(keyword)));
+ if (template_url == NULL) {
+ AutomationJSONReply(this, reply_message).SendError(
+ StringPrintf("No match for keyword: %s", keyword.c_str()));
+ return;
+ }
+ if (action == "delete") {
+ url_model->AddObserver(new AutomationProviderSearchEngineObserver(
this, reply_message));
- url_model->Load();
+ url_model->Remove(template_url);
+ } else if (action == "default") {
+ url_model->AddObserver(new AutomationProviderSearchEngineObserver(
+ this, reply_message));
+ url_model->SetDefaultSearchProvider(template_url);
+ } else {
+ AutomationJSONReply(this, reply_message).SendError(
+ StringPrintf("Invalid action: %s", action.c_str()));
}
}
diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h
index 9449558..715a89f 100644
--- a/chrome/browser/automation/testing_automation_provider.h
+++ b/chrome/browser/automation/testing_automation_provider.h
@@ -32,11 +32,6 @@ class TestingAutomationProvider : public AutomationProvider,
virtual void OnMessageReceived(const IPC::Message& msg);
virtual void OnChannelError();
- // Helper to extract search engine info.
- // Caller owns returned DictionaryValue.
- // This will only yield data if url model has loaded.
- ListValue* ExtractSearchEngineInfo(TemplateURLModel* url_model);
-
private:
class PopupMenuWaiter;
@@ -426,12 +421,33 @@ class TestingAutomationProvider : public AutomationProvider,
DictionaryValue* args,
IPC::Message* reply_message);
+ // Invoke loading of template url model.
+ // Uses the JSON interface for input/output.
+ void LoadSearchEngineInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
// Get search engines list.
+ // Assumes that the profile's template url model is loaded.
// Uses the JSON interface for input/output.
void GetSearchEngineInfo(Browser* browser,
DictionaryValue* args,
IPC::Message* reply_message);
+ // Add or edit search engine.
+ // Assumes that the profile's template url model is loaded.
+ // Uses the JSON interface for input/output.
+ void AddOrEditSearchEngine(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Perform a given action on an existing search engine.
+ // Assumes that the profile's template url model is loaded.
+ // Uses the JSON interface for input/output.
+ void PerformActionOnSearchEngine(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
// Get info about preferences.
// Uses the JSON interface for input/output.
void GetPrefsInfo(Browser* browser,
diff --git a/chrome/test/functional/search_engines.py b/chrome/test/functional/search_engines.py
index ed90bb2..5d1082d 100644
--- a/chrome/test/functional/search_engines.py
+++ b/chrome/test/functional/search_engines.py
@@ -13,6 +13,21 @@ import pyauto
class SearchEnginesTest(pyauto.PyUITest):
"""TestCase for Search Engines."""
+ def _GetSearchEngineWithKeyword(self, keyword):
+ """Get search engine info and return an element that matches keyword.
+
+ Args:
+ keyword: Search engine keyword field.
+
+ Returns:
+ A search engine info dict or None.
+ """
+ match_list = ([x for x in self.GetSearchEngineInfo()
+ if x['keyword'] == keyword])
+ if match_list:
+ return match_list[0]
+ return None
+
def Debug(self):
"""Test method for experimentation.
@@ -47,20 +62,59 @@ class SearchEnginesTest(pyauto.PyUITest):
self.assertFalse(youtube['in_default_list'])
self.assertFalse(youtube['is_default'])
- def _GetSearchEngineWithKeyword(self, keyword):
- """Get search engine info and return an element that matches keyword.
+ def testAddSearchEngine(self):
+ """Test searching using keyword of user-added search engine."""
+ self.AddSearchEngine(title='foo',
+ keyword='foo.com',
+ url='http://foo/?q=%s')
+ self.SetOmniboxText('foo.com foobar')
+ self.OmniboxAcceptInput()
+ self.assertEqual('http://foo/?q=foobar', self.GetActiveTabURL().spec())
- Args:
- keyword: Search engine keyword field.
+ def testEditSearchEngine(self):
+ """Test editing a search engine's properties."""
+ self.AddSearchEngine(title='foo',
+ keyword='foo.com',
+ url='http://foo/?q=%s')
+ self.EditSearchEngine(keyword='foo.com',
+ new_title='bar',
+ new_keyword='bar.com',
+ new_url='http://foo/?bar=true&q=%s')
+ self.assertTrue(self._GetSearchEngineWithKeyword('bar.com'))
+ self.assertFalse(self._GetSearchEngineWithKeyword('foo.com'))
+ self.SetOmniboxText('bar.com foobar')
+ self.OmniboxAcceptInput()
+ self.assertEqual('http://foo/?bar=true&q=foobar',
+ self.GetActiveTabURL().spec())
- Returns:
- A search engine info dict or None.
- """
- match_list = ([x for x in self.GetSearchEngineInfo()
- if x['keyword'] == 'youtube.com'])
- if match_list:
- return match_list[0]
- return None
+ def testDeleteSearchEngine(self):
+ """Test adding then deleting a search engine."""
+ self.AddSearchEngine(title='foo',
+ keyword='foo.com',
+ url='http://foo/?q=%s')
+ foo = self._GetSearchEngineWithKeyword('foo.com')
+ self.assertTrue(foo)
+ self.DeleteSearchEngine('foo.com')
+ foo = self._GetSearchEngineWithKeyword('foo.com')
+ self.assertFalse(foo)
+
+ def testMakeSearchEngineDefault(self):
+ """Test adding then making a search engine default."""
+ self.AddSearchEngine(
+ title='foo',
+ keyword='foo.com',
+ url='http://foo/?q=%s')
+ foo = self._GetSearchEngineWithKeyword('foo.com')
+ self.assertTrue(foo)
+ self.assertFalse(foo['is_default'])
+ self.MakeSearchEngineDefault('foo.com')
+ foo = self._GetSearchEngineWithKeyword('foo.com')
+ self.assertTrue(foo)
+ self.assertTrue(foo['is_default'])
+ self.SetOmniboxText('foobar')
+ self.OmniboxAcceptInput()
+ self.assertEqual('http://foo/?q=foobar',
+ self.GetActiveTabURL().spec())
if __name__ == '__main__':
diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py
index f51c11d..9c52c34 100644
--- a/chrome/test/pyautolib/pyauto.py
+++ b/chrome/test/pyautolib/pyauto.py
@@ -398,6 +398,9 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase):
windex: the index of the browser window to work on.
Default: 0 (first window)
"""
+ # Ensure that keyword data is loaded from the profile.
+ # This would normally be triggered by the user inputting this text.
+ self._GetResultFromJSONRequest({'command': 'LoadSearchEngineInfo'})
cmd_dict = {
'command': 'SetOmniboxText',
'text': text,
@@ -454,25 +457,93 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase):
An ordered list of dictionaries describing info about each search engine.
Example:
- [ { u'description': u'',
- u'in_default_list': True,
- u'is_default': True,
- u'keyword': u'google.com',
- u'short_name': u'Google'},
- { u'description': u'',
- u'in_default_list': True,
- u'is_default': False,
- u'keyword': u'yahoo.com',
- u'short_name': u'Yahoo!'},
- { u'description': u'',
- u'in_default_list': True,
- u'is_default': False,
- u'keyword': u'bing.com',
- u'short_name': u'Bing'}]
+ [ { u'description': u'',
+ u'display_url': u'{google:baseURL}search?q=%s',
+ u'host': u'www.google.com',
+ u'in_default_list': True,
+ u'is_default': True,
+ u'is_valid': True,
+ u'keyword': u'google.com',
+ u'path': u'/search',
+ u'short_name': u'Google',
+ u'supports_replacement': True,
+ u'url': u'{google:baseURL}search?q={searchTerms}'},
+ { u'description': u'',
+ u'display_url': u'http://search.yahoo.com/search?p=%s',
+ u'host': u'search.yahoo.com',
+ u'in_default_list': True,
+ u'is_default': False,
+ u'is_valid': True,
+ u'keyword': u'yahoo.com',
+ u'path': u'/search',
+ u'short_name': u'Yahoo!',
+ u'supports_replacement': True,
+ u'url': u'http://search.yahoo.com/search?p={searchTerms}'},
"""
+ # Ensure that the search engine profile is loaded into data model.
+ self._GetResultFromJSONRequest({'command': 'LoadSearchEngineInfo'})
cmd_dict = {'command': 'GetSearchEngineInfo'}
return self._GetResultFromJSONRequest(cmd_dict)['search_engines']
+ def AddSearchEngine(self, title, keyword, url):
+ """Add a search engine, as done through the search engines UI.
+
+ Args:
+ title: name for search engine.
+ keyword: keyword, used to initiate a custom search from omnibox.
+ url: url template for this search engine's query.
+ '%s' is replaced by search query string when used to search.
+ """
+ # Ensure that the search engine profile is loaded into data model.
+ self._GetResultFromJSONRequest({'command': 'LoadSearchEngineInfo'})
+ cmd_dict = {'command': 'AddOrEditSearchEngine',
+ 'new_title': title,
+ 'new_keyword': keyword,
+ 'new_url': url}
+ self._GetResultFromJSONRequest(cmd_dict)
+
+ def EditSearchEngine(self, keyword, new_title, new_keyword, new_url):
+ """Edit info for existing search engine.
+
+ Args:
+ keyword: existing search engine keyword.
+ new_title: new name for this search engine.
+ new_keyword: new keyword for this search engine.
+ new_url: new url for this search engine.
+ """
+ # Ensure that the search engine profile is loaded into data model.
+ self._GetResultFromJSONRequest({'command': 'LoadSearchEngineInfo'})
+ cmd_dict = {'command': 'AddOrEditSearchEngine',
+ 'keyword': keyword,
+ 'new_title': new_title,
+ 'new_keyword': new_keyword,
+ 'new_url': new_url}
+ self._GetResultFromJSONRequest(cmd_dict)
+
+ def DeleteSearchEngine(self, keyword):
+ """Delete search engine with given keyword.
+
+ Args:
+ keyword: the keyword string of the search engine to delete.
+ """
+ # Ensure that the search engine profile is loaded into data model.
+ self._GetResultFromJSONRequest({'command': 'LoadSearchEngineInfo'})
+ cmd_dict = {'command': 'PerformActionOnSearchEngine', 'keyword': keyword,
+ 'action': 'delete'}
+ self._GetResultFromJSONRequest(cmd_dict)
+
+ def MakeSearchEngineDefault(self, keyword):
+ """Make search engine with given keyword the default search.
+
+ Args:
+ keyword: the keyword string of the search engine to make default.
+ """
+ # Ensure that the search engine profile is loaded into data model.
+ self._GetResultFromJSONRequest({'command': 'LoadSearchEngineInfo'})
+ cmd_dict = {'command': 'PerformActionOnSearchEngine', 'keyword': keyword,
+ 'action': 'default'}
+ self._GetResultFromJSONRequest(cmd_dict)
+
def GetPrefsInfo(self):
"""Return info about preferences.