summaryrefslogtreecommitdiffstats
path: root/chrome/browser/automation
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-02 23:51:45 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-02 23:51:45 +0000
commite51cb6f8bcdec373ccabd5ea609bc7855eb6c070 (patch)
tree118b94ab588172b09a5aba90c42164c51b63d964 /chrome/browser/automation
parente10e3f1bc8cd6e15c6808e467919f7d6aa547180 (diff)
downloadchromium_src-e51cb6f8bcdec373ccabd5ea609bc7855eb6c070.zip
chromium_src-e51cb6f8bcdec373ccabd5ea609bc7855eb6c070.tar.gz
chromium_src-e51cb6f8bcdec373ccabd5ea609bc7855eb6c070.tar.bz2
GTTF: Move pyauto automation provider code to TestingAutomationProvider
BUG=52097 TEST=pyauto tests Review URL: http://codereview.chromium.org/3290008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@58430 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/automation')
-rw-r--r--chrome/browser/automation/automation_provider.cc1797
-rw-r--r--chrome/browser/automation/automation_provider.h251
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc1770
-rw-r--r--chrome/browser/automation/testing_automation_provider.h250
4 files changed, 2057 insertions, 2011 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index e2f5d12..61a179f 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -32,7 +32,6 @@
#include "chrome/browser/automation/automation_autocomplete_edit_tracker.h"
#include "chrome/browser/automation/automation_browser_tracker.h"
#include "chrome/browser/automation/automation_extension_tracker.h"
-#include "chrome/browser/automation/automation_provider_json.h"
#include "chrome/browser/automation/automation_provider_list.h"
#include "chrome/browser/automation/automation_provider_observers.h"
#include "chrome/browser/automation/automation_resource_message_filter.h"
@@ -258,6 +257,42 @@ int AutomationProvider::AddExtension(Extension* extension) {
return extension_tracker_->Add(extension);
}
+// TODO(phajdan.jr): move to TestingAutomationProvider.
+DictionaryValue* AutomationProvider::GetDictionaryFromDownloadItem(
+ const DownloadItem* download) {
+ std::map<DownloadItem::DownloadState, std::string> state_to_string;
+ state_to_string[DownloadItem::IN_PROGRESS] = std::string("IN_PROGRESS");
+ state_to_string[DownloadItem::CANCELLED] = std::string("CANCELLED");
+ state_to_string[DownloadItem::REMOVING] = std::string("REMOVING");
+ state_to_string[DownloadItem::COMPLETE] = std::string("COMPLETE");
+
+ std::map<DownloadItem::SafetyState, std::string> safety_state_to_string;
+ safety_state_to_string[DownloadItem::SAFE] = std::string("SAFE");
+ safety_state_to_string[DownloadItem::DANGEROUS] = std::string("DANGEROUS");
+ safety_state_to_string[DownloadItem::DANGEROUS_BUT_VALIDATED] =
+ std::string("DANGEROUS_BUT_VALIDATED");
+
+ DictionaryValue* dl_item_value = new DictionaryValue;
+ dl_item_value->SetInteger("id", static_cast<int>(download->id()));
+ dl_item_value->SetString("url", download->url().spec());
+ dl_item_value->SetString("referrer_url", download->referrer_url().spec());
+ dl_item_value->SetString("file_name", download->GetFileName().value());
+ dl_item_value->SetString("full_path", download->full_path().value());
+ dl_item_value->SetBoolean("is_paused", download->is_paused());
+ dl_item_value->SetBoolean("open_when_complete",
+ download->open_when_complete());
+ dl_item_value->SetBoolean("is_extension_install",
+ download->is_extension_install());
+ dl_item_value->SetBoolean("is_temporary", download->is_temporary());
+ dl_item_value->SetBoolean("is_otr", download->is_otr()); // off-the-record
+ dl_item_value->SetString("state", state_to_string[download->state()]);
+ dl_item_value->SetString("safety_state",
+ safety_state_to_string[download->safety_state()]);
+ dl_item_value->SetInteger("PercentComplete", download->PercentComplete());
+
+ return dl_item_value;
+}
+
Extension* AutomationProvider::GetExtension(int extension_handle) {
return extension_tracker_->GetResource(extension_handle);
}
@@ -294,8 +329,6 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(AutomationMsg_SetProxyConfig, SetProxyConfig);
IPC_MESSAGE_HANDLER(AutomationMsg_PrintAsync, PrintAsync)
IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Find, HandleFindRequest)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest,
- SendJSONRequest)
IPC_MESSAGE_HANDLER(AutomationMsg_GetPageCurrentEncoding,
GetPageCurrentEncoding)
IPC_MESSAGE_HANDLER(AutomationMsg_OverrideEncoding, OverrideEncoding)
@@ -458,1764 +491,6 @@ void AutomationProvider::HandleFindRequest(
params.find_next);
}
-// Sample json input: { "command": "SetWindowDimensions",
-// "x": 20, # optional
-// "y": 20, # optional
-// "width": 800, # optional
-// "height": 600 } # optional
-void AutomationProvider::SetWindowDimensions(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- gfx::Rect rect = browser->window()->GetRestoredBounds();
- int x, y, width, height;
- if (args->GetInteger("x", &x))
- rect.set_x(x);
- if (args->GetInteger("y", &y))
- rect.set_y(y);
- if (args->GetInteger("width", &width))
- rect.set_width(width);
- if (args->GetInteger("height", &height))
- rect.set_height(height);
- browser->window()->SetBounds(rect);
- AutomationJSONReply(this, reply_message).SendSuccess(NULL);
-}
-
-ListValue* AutomationProvider::GetInfobarsInfo(TabContents* tc) {
- // Each infobar may have different properties depending on the type.
- ListValue* infobars = new ListValue;
- for (int infobar_index = 0;
- infobar_index < tc->infobar_delegate_count();
- ++infobar_index) {
- DictionaryValue* infobar_item = new DictionaryValue;
- InfoBarDelegate* infobar = tc->GetInfoBarDelegateAt(infobar_index);
- if (infobar->AsConfirmInfoBarDelegate()) {
- // Also covers ThemeInstalledInfoBarDelegate and
- // CrashedExtensionInfoBarDelegate.
- infobar_item->SetString("type", "confirm_infobar");
- ConfirmInfoBarDelegate* confirm_infobar =
- infobar->AsConfirmInfoBarDelegate();
- infobar_item->SetString("text", confirm_infobar->GetMessageText());
- infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
- ListValue* buttons_list = new ListValue;
- int buttons = confirm_infobar->GetButtons();
- if (ConfirmInfoBarDelegate::BUTTON_OK & buttons) {
- StringValue* button_label = new StringValue(
- confirm_infobar->GetButtonLabel(
- ConfirmInfoBarDelegate::BUTTON_OK));
- buttons_list->Append(button_label);
- }
- if (ConfirmInfoBarDelegate::BUTTON_CANCEL & buttons) {
- StringValue* button_label = new StringValue(
- confirm_infobar->GetButtonLabel(
- ConfirmInfoBarDelegate::BUTTON_CANCEL));
- buttons_list->Append(button_label);
- }
- infobar_item->Set("buttons", buttons_list);
- } else if (infobar->AsAlertInfoBarDelegate()) {
- infobar_item->SetString("type", "alert_infobar");
- AlertInfoBarDelegate* alert_infobar =
- infobar->AsAlertInfoBarDelegate();
- infobar_item->SetString("text", alert_infobar->GetMessageText());
- } else if (infobar->AsLinkInfoBarDelegate()) {
- infobar_item->SetString("type", "link_infobar");
- LinkInfoBarDelegate* link_infobar = infobar->AsLinkInfoBarDelegate();
- infobar_item->SetString("link_text", link_infobar->GetLinkText());
- } else if (infobar->AsTranslateInfoBarDelegate()) {
- infobar_item->SetString("type", "translate_infobar");
- TranslateInfoBarDelegate* translate_infobar =
- infobar->AsTranslateInfoBarDelegate();
- infobar_item->SetString("original_lang_code",
- translate_infobar->GetOriginalLanguageCode());
- infobar_item->SetString("target_lang_code",
- translate_infobar->GetTargetLanguageCode());
- } else if (infobar->AsExtensionInfoBarDelegate()) {
- infobar_item->SetString("type", "extension_infobar");
- } else {
- infobar_item->SetString("type", "unknown_infobar");
- }
- infobars->Append(infobar_item);
- }
- return infobars;
-}
-
-// Sample json input: { "command": "PerformActionOnInfobar",
-// "action": "dismiss",
-// "infobar_index": 0,
-// "tab_index": 0 }
-// Sample output: {}
-void AutomationProvider::PerformActionOnInfobar(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
- int tab_index;
- int infobar_index;
- std::string action;
- if (!args->GetInteger("tab_index", &tab_index) ||
- !args->GetInteger("infobar_index", &infobar_index) ||
- !args->GetString("action", &action)) {
- reply.SendError("Invalid or missing args");
- return;
- }
- TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
- if (!tab_contents) {
- reply.SendError(StringPrintf("No such tab at index %d", tab_index));
- return;
- }
- InfoBarDelegate* infobar = NULL;
- if (infobar_index < 0 ||
- infobar_index >= tab_contents->infobar_delegate_count() ||
- !(infobar = tab_contents->GetInfoBarDelegateAt(infobar_index))) {
- reply.SendError(StringPrintf("No such infobar at index %d", infobar_index));
- return;
- }
- if ("dismiss" == action) {
- infobar->InfoBarDismissed();
- tab_contents->RemoveInfoBar(infobar);
- reply.SendSuccess(NULL);
- return;
- }
- if ("accept" == action || "cancel" == action) {
- ConfirmInfoBarDelegate* confirm_infobar;
- if (!(confirm_infobar = infobar->AsConfirmInfoBarDelegate())) {
- reply.SendError("Not a confirm infobar");
- return;
- }
- if ("accept" == action) {
- if (confirm_infobar->Accept())
- tab_contents->RemoveInfoBar(infobar);
- } else if ("cancel" == action) {
- if (confirm_infobar->Cancel())
- tab_contents->RemoveInfoBar(infobar);
- }
- reply.SendSuccess(NULL);
- return;
- }
- reply.SendError("Invalid action");
-}
-
-namespace {
-
-// Task to get info about BrowserChildProcessHost. Must run on IO thread to
-// honor the semantics of BrowserChildProcessHost.
-// Used by AutomationProvider::GetBrowserInfo().
-class GetChildProcessHostInfoTask : public Task {
- public:
- GetChildProcessHostInfoTask(base::WaitableEvent* event,
- ListValue* child_processes)
- : event_(event),
- child_processes_(child_processes) {}
-
- virtual void Run() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- for (BrowserChildProcessHost::Iterator iter; !iter.Done(); ++iter) {
- // Only add processes which are already started,
- // since we need their handle.
- if ((*iter)->handle() == base::kNullProcessHandle) {
- continue;
- }
- ChildProcessInfo* info = *iter;
- DictionaryValue* item = new DictionaryValue;
- item->SetString("name", WideToUTF16Hack(info->name()));
- item->SetString("type",
- ChildProcessInfo::GetTypeNameInEnglish(info->type()));
- item->SetInteger("pid", base::GetProcId(info->handle()));
- child_processes_->Append(item);
- }
- event_->Signal();
- }
-
- private:
- base::WaitableEvent* const event_; // weak
- ListValue* child_processes_;
-
- DISALLOW_COPY_AND_ASSIGN(GetChildProcessHostInfoTask);
-};
-
-} // namespace
-
-// Sample json input: { "command": "GetBrowserInfo" }
-// Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
-// sample json output.
-void AutomationProvider::GetBrowserInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- DictionaryValue* properties = new DictionaryValue;
- properties->SetString("ChromeVersion", chrome::kChromeVersion);
- properties->SetString("BrowserProcessExecutableName",
- WideToUTF16Hack(chrome::kBrowserProcessExecutableName));
- properties->SetString("HelperProcessExecutableName",
- WideToUTF16Hack(chrome::kHelperProcessExecutableName));
- properties->SetString("BrowserProcessExecutablePath",
- WideToUTF16Hack(chrome::kBrowserProcessExecutablePath));
- properties->SetString("HelperProcessExecutablePath",
- chrome::kHelperProcessExecutablePath);
- properties->SetString("command_line_string",
- CommandLine::ForCurrentProcess()->command_line_string());
- FilePath dumps_path;
- PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
- properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
-
- std::string branding;
-#if defined(GOOGLE_CHROME_BUILD)
- branding = "Google Chrome";
-#elif defined(CHROMIUM_BUILD)
- branding = "Chromium";
-#else
- branding = "Unknown Branding";
-#endif
- properties->SetString("branding", branding);
-
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- return_value->Set("properties", properties);
-
- return_value->SetInteger("browser_pid", base::GetCurrentProcId());
- // Add info about all windows in a list of dictionaries, one dictionary
- // item per window.
- ListValue* windows = new ListValue;
- int windex = 0;
- for (BrowserList::const_iterator it = BrowserList::begin();
- it != BrowserList::end();
- ++it, ++windex) {
- DictionaryValue* browser_item = new DictionaryValue;
- browser = *it;
- browser_item->SetInteger("index", windex);
- // Window properties
- gfx::Rect rect = browser->window()->GetRestoredBounds();
- browser_item->SetInteger("x", rect.x());
- browser_item->SetInteger("y", rect.y());
- browser_item->SetInteger("width", rect.width());
- browser_item->SetInteger("height", rect.height());
- browser_item->SetBoolean("fullscreen",
- browser->window()->IsFullscreen());
- browser_item->SetInteger("selected_tab", browser->selected_index());
- browser_item->SetBoolean("incognito",
- browser->profile()->IsOffTheRecord());
- // For each window, add info about all tabs in a list of dictionaries,
- // one dictionary item per tab.
- ListValue* tabs = new ListValue;
- for (int i = 0; i < browser->tab_count(); ++i) {
- TabContents* tc = browser->GetTabContentsAt(i);
- DictionaryValue* tab = new DictionaryValue;
- tab->SetInteger("index", i);
- tab->SetString("url", tc->GetURL().spec());
- tab->SetInteger("renderer_pid",
- base::GetProcId(tc->GetRenderProcessHost()->GetHandle()));
- tab->Set("infobars", GetInfobarsInfo(tc));
- tabs->Append(tab);
- }
- browser_item->Set("tabs", tabs);
-
- windows->Append(browser_item);
- }
- return_value->Set("windows", windows);
-
- return_value->SetString("child_process_path",
- ChildProcessHost::GetChildPath(true).value());
- // Child processes are the processes for plugins and other workers.
- // Add all child processes in a list of dictionaries, one dictionary item
- // per child process.
- ListValue* child_processes = new ListValue;
- base::WaitableEvent event(true /* manual reset */,
- false /* not initially signaled */);
- CHECK(ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- new GetChildProcessHostInfoTask(&event, child_processes)));
- event.Wait();
- return_value->Set("child_processes", child_processes);
-
- // Add all extension processes in a list of dictionaries, one dictionary
- // item per extension process.
- ListValue* extension_processes = new ListValue;
- ProfileManager* profile_manager = g_browser_process->profile_manager();
- for (ProfileManager::const_iterator it = profile_manager->begin();
- it != profile_manager->end(); ++it) {
- ExtensionProcessManager* process_manager =
- (*it)->GetExtensionProcessManager();
- ExtensionProcessManager::const_iterator jt;
- for (jt = process_manager->begin(); jt != process_manager->end(); ++jt) {
- ExtensionHost* ex_host = *jt;
- // Don't add dead extension processes.
- if (!ex_host->IsRenderViewLive())
- continue;
- DictionaryValue* item = new DictionaryValue;
- item->SetString("name", ex_host->extension()->name());
- item->SetInteger(
- "pid",
- base::GetProcId(ex_host->render_process_host()->GetHandle()));
- extension_processes->Append(item);
- }
- }
- return_value->Set("extension_processes", extension_processes);
- AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
-}
-
-// Sample json input: { "command": "GetNavigationInfo" }
-// Refer to GetNavigationInfo() in chrome/test/pyautolib/pyauto.py for
-// sample json output.
-void AutomationProvider::GetNavigationInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
- int tab_index;
- TabContents* tab_contents = NULL;
- if (!args->GetInteger("tab_index", &tab_index) ||
- !(tab_contents = browser->GetTabContentsAt(tab_index))) {
- reply.SendError("tab_index missing or invalid.");
- return;
- }
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- const NavigationController& controller = tab_contents->controller();
- NavigationEntry* nav_entry = controller.GetActiveEntry();
- DCHECK(nav_entry);
-
- // Security info.
- DictionaryValue* ssl = new DictionaryValue;
- std::map<SecurityStyle, std::string> style_to_string;
- style_to_string[SECURITY_STYLE_UNKNOWN] = "SECURITY_STYLE_UNKNOWN";
- style_to_string[SECURITY_STYLE_UNAUTHENTICATED] =
- "SECURITY_STYLE_UNAUTHENTICATED";
- style_to_string[SECURITY_STYLE_AUTHENTICATION_BROKEN] =
- "SECURITY_STYLE_AUTHENTICATION_BROKEN";
- style_to_string[SECURITY_STYLE_AUTHENTICATED] =
- "SECURITY_STYLE_AUTHENTICATED";
-
- NavigationEntry::SSLStatus ssl_status = nav_entry->ssl();
- ssl->SetString("security_style",
- style_to_string[ssl_status.security_style()]);
- ssl->SetBoolean("ran_insecure_content", ssl_status.ran_insecure_content());
- ssl->SetBoolean("displayed_insecure_content",
- ssl_status.displayed_insecure_content());
- return_value->Set("ssl", ssl);
-
- // Page type.
- std::map<NavigationEntry::PageType, std::string> pagetype_to_string;
- pagetype_to_string[NavigationEntry::NORMAL_PAGE] = "NORMAL_PAGE";
- pagetype_to_string[NavigationEntry::ERROR_PAGE] = "ERROR_PAGE";
- pagetype_to_string[NavigationEntry::INTERSTITIAL_PAGE] = "INTERSTITIAL_PAGE";
- return_value->SetString("page_type",
- pagetype_to_string[nav_entry->page_type()]);
-
- return_value->SetString("favicon_url", nav_entry->favicon().url().spec());
- reply.SendSuccess(return_value.get());
-}
-
-// Sample json input: { "command": "GetHistoryInfo",
-// "search_text": "some text" }
-// Refer chrome/test/pyautolib/history_info.py for sample json output.
-void AutomationProvider::GetHistoryInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- consumer_.CancelAllRequests();
-
- string16 search_text;
- args->GetString("search_text", &search_text);
-
- // Fetch history.
- HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
- history::QueryOptions options;
- // The observer owns itself. It deletes itself after it fetches history.
- AutomationProviderHistoryObserver* history_observer =
- new AutomationProviderHistoryObserver(this, reply_message);
- hs->QueryHistory(
- search_text,
- options,
- &consumer_,
- NewCallback(history_observer,
- &AutomationProviderHistoryObserver::HistoryQueryComplete));
-}
-
-// Sample json input: { "command": "AddHistoryItem",
-// "item": { "URL": "http://www.google.com",
-// "title": "Google", # optional
-// "time": 12345 # optional (time_t)
-// } }
-// Refer chrome/test/pyautolib/pyauto.py for details on input.
-void AutomationProvider::AddHistoryItem(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- DictionaryValue* item = NULL;
- args->GetDictionary("item", &item);
- string16 url_text;
- string16 title;
- base::Time time = base::Time::Now();
- AutomationJSONReply reply(this, reply_message);
-
- if (!item->GetString("url", &url_text)) {
- reply.SendError("bad args (no URL in dict?)");
- return;
- }
- GURL gurl(url_text);
- item->GetString("title", &title); // Don't care if it fails.
- int it;
- double dt;
- if (item->GetInteger("time", &it))
- time = base::Time::FromTimeT(it);
- else if (item->GetReal("time", &dt))
- time = base::Time::FromDoubleT(dt);
-
- // Ideas for "dummy" values (e.g. id_scope) came from
- // chrome/browser/autocomplete/history_contents_provider_unittest.cc
- HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
- const void* id_scope = reinterpret_cast<void*>(1);
- hs->AddPage(gurl, time,
- id_scope,
- 0,
- GURL(),
- PageTransition::LINK,
- history::RedirectList(),
- history::SOURCE_BROWSED,
- false);
- if (title.length())
- hs->SetPageTitle(gurl, title);
- reply.SendSuccess(NULL);
-}
-
-DictionaryValue* AutomationProvider::GetDictionaryFromDownloadItem(
- const DownloadItem* download) {
- std::map<DownloadItem::DownloadState, std::string> state_to_string;
- state_to_string[DownloadItem::IN_PROGRESS] = std::string("IN_PROGRESS");
- state_to_string[DownloadItem::CANCELLED] = std::string("CANCELLED");
- state_to_string[DownloadItem::REMOVING] = std::string("REMOVING");
- state_to_string[DownloadItem::COMPLETE] = std::string("COMPLETE");
-
- std::map<DownloadItem::SafetyState, std::string> safety_state_to_string;
- safety_state_to_string[DownloadItem::SAFE] = std::string("SAFE");
- safety_state_to_string[DownloadItem::DANGEROUS] = std::string("DANGEROUS");
- safety_state_to_string[DownloadItem::DANGEROUS_BUT_VALIDATED] =
- std::string("DANGEROUS_BUT_VALIDATED");
-
- DictionaryValue* dl_item_value = new DictionaryValue;
- dl_item_value->SetInteger("id", static_cast<int>(download->id()));
- dl_item_value->SetString("url", download->url().spec());
- dl_item_value->SetString("referrer_url", download->referrer_url().spec());
- dl_item_value->SetString("file_name", download->GetFileName().value());
- dl_item_value->SetString("full_path", download->full_path().value());
- dl_item_value->SetBoolean("is_paused", download->is_paused());
- dl_item_value->SetBoolean("open_when_complete",
- download->open_when_complete());
- dl_item_value->SetBoolean("is_extension_install",
- download->is_extension_install());
- dl_item_value->SetBoolean("is_temporary", download->is_temporary());
- dl_item_value->SetBoolean("is_otr", download->is_otr()); // off-the-record
- dl_item_value->SetString("state", state_to_string[download->state()]);
- dl_item_value->SetString("safety_state",
- safety_state_to_string[download->safety_state()]);
- dl_item_value->SetInteger("PercentComplete", download->PercentComplete());
-
- return dl_item_value;
-}
-
-// Sample json input: { "command": "GetDownloadsInfo" }
-// Refer chrome/test/pyautolib/download_info.py for sample json output.
-void AutomationProvider::GetDownloadsInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
-
- if (!profile_->HasCreatedDownloadManager()) {
- reply.SendError("no download manager");
- return;
- }
-
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- std::vector<DownloadItem*> downloads;
- profile_->GetDownloadManager()->GetAllDownloads(FilePath(), &downloads);
-
- ListValue* list_of_downloads = new ListValue;
- for (std::vector<DownloadItem*>::iterator it = downloads.begin();
- it != downloads.end();
- it++) { // Fill info about each download item.
- list_of_downloads->Append(GetDictionaryFromDownloadItem(*it));
- }
- return_value->Set("downloads", list_of_downloads);
- reply.SendSuccess(return_value.get());
- // All value objects allocated above are owned by |return_value|
- // and get freed by it.
-}
-
-void AutomationProvider::WaitForDownloadsToComplete(
- Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
-
- // Look for a quick return.
- if (!profile_->HasCreatedDownloadManager()) {
- reply.SendSuccess(NULL); // No download manager.
- return;
- }
- std::vector<DownloadItem*> downloads;
- profile_->GetDownloadManager()->GetCurrentDownloads(FilePath(), &downloads);
- if (downloads.empty()) {
- reply.SendSuccess(NULL);
- return;
- }
-
- // The observer owns itself. When the last observed item pings, it
- // deletes itself.
- AutomationProviderDownloadItemObserver* item_observer =
- new AutomationProviderDownloadItemObserver(
- this, reply_message, downloads.size());
- for (std::vector<DownloadItem*>::iterator i = downloads.begin();
- i != downloads.end();
- i++) {
- (*i)->AddObserver(item_observer);
- }
-}
-
-namespace {
-
-DownloadItem* GetDownloadItemFromId(int id, DownloadManager* download_manager) {
- std::vector<DownloadItem*> downloads;
- download_manager->GetAllDownloads(FilePath(), &downloads);
- DownloadItem* selected_item = NULL;
-
- for (std::vector<DownloadItem*>::iterator it = downloads.begin();
- it != downloads.end();
- it++) {
- DownloadItem* curr_item = *it;
- if (curr_item->id() == id) {
- selected_item = curr_item;
- break;
- }
- }
- return selected_item;
-}
-
-} // namespace
-
-// See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
-// json input and output.
-void AutomationProvider::PerformActionOnDownload(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- int id;
- std::string action;
-
- if (!profile_->HasCreatedDownloadManager()) {
- AutomationJSONReply(this, reply_message).SendError("No download manager.");
- return;
- }
- if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) {
- AutomationJSONReply(this, reply_message).SendError(
- "Must include int id and string action.");
- return;
- }
-
- DownloadManager* download_manager = profile_->GetDownloadManager();
- DownloadItem* selected_item = GetDownloadItemFromId(id, download_manager);
- if (!selected_item) {
- AutomationJSONReply(this, reply_message).SendError(
- StringPrintf("No download with an id of %d\n", id));
- return;
- }
-
- if (action == "open") {
- selected_item->AddObserver(
- new AutomationProviderDownloadUpdatedObserver(
- this, reply_message, true));
- selected_item->OpenDownload();
- } else if (action == "toggle_open_files_like_this") {
- selected_item->OpenFilesBasedOnExtension(
- !selected_item->ShouldOpenFileBasedOnExtension());
- AutomationJSONReply(this, reply_message).SendSuccess(NULL);
- } else if (action == "remove") {
- download_manager->AddObserver(
- new AutomationProviderDownloadModelChangedObserver(
- this, reply_message, download_manager));
- selected_item->Remove(false);
- } else if (action == "decline_dangerous_download") {
- // This is the same as removing the file with delete_file=true.
- download_manager->AddObserver(
- new AutomationProviderDownloadModelChangedObserver(
- this, reply_message, download_manager));
- selected_item->Remove(true);
- } else if (action == "save_dangerous_download") {
- selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
- this, reply_message, false));
- selected_item->DangerousDownloadValidated();
- } else if (action == "toggle_pause") {
- selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
- this, reply_message, false));
- // This will still return if download has already completed.
- selected_item->TogglePause();
- } else if (action == "cancel") {
- selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
- this, reply_message, false));
- selected_item->Cancel(true);
- } else {
- AutomationJSONReply(this, reply_message).SendError(
- StringPrintf("Invalid action '%s' given.", action.c_str()));
- }
-}
-
-// Sample json input: { "command": "GetPrefsInfo" }
-// Refer chrome/test/pyautolib/prefs_info.py for sample json output.
-void AutomationProvider::GetPrefsInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- const PrefService::PreferenceSet& prefs =
- profile_->GetPrefs()->preference_set();
- DictionaryValue* items = new DictionaryValue;
- for (PrefService::PreferenceSet::const_iterator it = prefs.begin();
- it != prefs.end(); ++it) {
- items->Set((*it)->name(), (*it)->GetValue()->DeepCopy());
- }
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- return_value->Set("prefs", items); // return_value owns items.
- AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
-}
-
-// Sample json input: { "command": "SetPrefs", "path": path, "value": value }
-void AutomationProvider::SetPrefs(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- std::string path;
- Value* val;
- AutomationJSONReply reply(this, reply_message);
- if (args->GetString("path", &path) && args->Get("value", &val)) {
- PrefService* pref_service = profile_->GetPrefs();
- const PrefService::Preference* pref =
- pref_service->FindPreference(path.c_str());
- if (!pref) { // Not a registered pref.
- reply.SendError("pref not registered.");
- return;
- } else if (pref->IsManaged()) { // Do not attempt to change a managed pref.
- reply.SendError("pref is managed. cannot be changed.");
- return;
- } else { // Set the pref.
- pref_service->Set(path.c_str(), *val);
- }
- } else {
- reply.SendError("no pref path or value given.");
- return;
- }
-
- reply.SendSuccess(NULL);
-}
-
-// Sample json input: { "command": "GetOmniboxInfo" }
-// Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
-void AutomationProvider::GetOmniboxInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
-
- LocationBar* loc_bar = browser->window()->GetLocationBar();
- AutocompleteEditView* edit_view = loc_bar->location_entry();
- AutocompleteEditModel* model = edit_view->model();
-
- // Fill up matches.
- ListValue* matches = new ListValue;
- const AutocompleteResult& result = model->result();
- for (AutocompleteResult::const_iterator i = result.begin();
- i != result.end(); ++i) {
- const AutocompleteMatch& match = *i;
- DictionaryValue* item = new DictionaryValue; // owned by return_value
- item->SetString("type", AutocompleteMatch::TypeToString(match.type));
- item->SetBoolean("starred", match.starred);
- item->SetString("destination_url", match.destination_url.spec());
- item->SetString("contents", WideToUTF16Hack(match.contents));
- item->SetString("description", WideToUTF16Hack(match.description));
- matches->Append(item);
- }
- return_value->Set("matches", matches);
-
- // Fill up other properties.
- DictionaryValue* properties = new DictionaryValue; // owned by return_value
- properties->SetBoolean("has_focus", model->has_focus());
- properties->SetBoolean("query_in_progress", model->query_in_progress());
- properties->SetString("keyword", WideToUTF16Hack(model->keyword()));
- properties->SetString("text", WideToUTF16Hack(edit_view->GetText()));
- return_value->Set("properties", properties);
-
- AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
-}
-
-// Sample json input: { "command": "SetOmniboxText",
-// "text": "goog" }
-void AutomationProvider::SetOmniboxText(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- string16 text;
- AutomationJSONReply reply(this, reply_message);
- if (!args->GetString("text", &text)) {
- reply.SendError("text missing");
- return;
- }
- browser->FocusLocationBar();
- LocationBar* loc_bar = browser->window()->GetLocationBar();
- AutocompleteEditView* edit_view = loc_bar->location_entry();
- edit_view->model()->OnSetFocus(false);
- edit_view->SetUserText(UTF16ToWideHack(text));
- reply.SendSuccess(NULL);
-}
-
-// Sample json input: { "command": "OmniboxMovePopupSelection",
-// "count": 1 }
-// Negative count implies up, positive implies down. Count values will be
-// capped by the size of the popup list.
-void AutomationProvider::OmniboxMovePopupSelection(
- Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- int count;
- AutomationJSONReply reply(this, reply_message);
- if (!args->GetInteger("count", &count)) {
- reply.SendError("count missing");
- return;
- }
- LocationBar* loc_bar = browser->window()->GetLocationBar();
- AutocompleteEditModel* model = loc_bar->location_entry()->model();
- model->OnUpOrDownKeyPressed(count);
- reply.SendSuccess(NULL);
-}
-
-// Sample json input: { "command": "OmniboxAcceptInput" }
-void AutomationProvider::OmniboxAcceptInput(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- NavigationController& controller =
- browser->GetSelectedTabContents()->controller();
- // Setup observer to wait until the selected item loads.
- NotificationObserver* observer =
- new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
- notification_observer_list_.AddObserver(observer);
-
- browser->window()->GetLocationBar()->AcceptInput();
-}
-
-// Sample json input: { "command": "GetInitialLoadTimes" }
-// Refer to InitialLoadObserver::GetTimingInformation() for sample output.
-void AutomationProvider::GetInitialLoadTimes(
- Browser*,
- DictionaryValue*,
- IPC::Message* reply_message) {
- scoped_ptr<DictionaryValue> return_value(
- initial_load_observer_->GetTimingInformation());
-
- std::string json_return;
- base::JSONWriter::Write(return_value.get(), false, &json_return);
- AutomationMsg_SendJSONRequest::WriteReplyParams(
- reply_message, json_return, true);
- Send(reply_message);
-}
-
-// Sample json input: { "command": "GetPluginsInfo" }
-// Refer chrome/test/pyautolib/plugins_info.py for sample json output.
-void AutomationProvider::GetPluginsInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- std::vector<WebPluginInfo> plugins;
- NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
- ListValue* items = new ListValue;
- for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
- it != plugins.end();
- ++it) {
- DictionaryValue* item = new DictionaryValue;
- item->SetString("name", it->name);
- item->SetString("path", it->path.value());
- item->SetString("version", it->version);
- item->SetString("desc", it->desc);
- item->SetBoolean("enabled", it->enabled);
- // Add info about mime types.
- ListValue* mime_types = new ListValue();
- for (std::vector<WebPluginMimeType>::const_iterator type_it =
- it->mime_types.begin();
- type_it != it->mime_types.end();
- ++type_it) {
- DictionaryValue* mime_type = new DictionaryValue();
- mime_type->SetString("mimeType", type_it->mime_type);
- mime_type->SetString("description", type_it->description);
-
- ListValue* file_extensions = new ListValue();
- for (std::vector<std::string>::const_iterator ext_it =
- type_it->file_extensions.begin();
- ext_it != type_it->file_extensions.end();
- ++ext_it) {
- file_extensions->Append(new StringValue(*ext_it));
- }
- mime_type->Set("fileExtensions", file_extensions);
-
- mime_types->Append(mime_type);
- }
- item->Set("mimeTypes", mime_types);
- items->Append(item);
- }
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- return_value->Set("plugins", items); // return_value owns items.
-
- AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
-}
-
-// Sample json input:
-// { "command": "EnablePlugin",
-// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
-void AutomationProvider::EnablePlugin(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- FilePath::StringType path;
- AutomationJSONReply reply(this, reply_message);
- if (!args->GetString("path", &path)) {
- reply.SendError("path not specified.");
- return;
- } else if (!NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(path))) {
- reply.SendError(StringPrintf("Could not enable plugin for path %s.",
- path.c_str()));
- return;
- }
- reply.SendSuccess(NULL);
-}
-
-// Sample json input:
-// { "command": "DisablePlugin",
-// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
-void AutomationProvider::DisablePlugin(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- FilePath::StringType path;
- AutomationJSONReply reply(this, reply_message);
- if (!args->GetString("path", &path)) {
- reply.SendError("path not specified.");
- return;
- } else if (!NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(path))) {
- reply.SendError(StringPrintf("Could not disable plugin for path %s.",
- path.c_str()));
- return;
- }
- reply.SendSuccess(NULL);
-}
-
-// Sample json input:
-// { "command": "SaveTabContents",
-// "tab_index": 0,
-// "filename": <a full pathname> }
-// Sample json output:
-// {}
-void AutomationProvider::SaveTabContents(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- int tab_index = 0;
- FilePath::StringType filename;
- FilePath::StringType parent_directory;
- TabContents* tab_contents = NULL;
-
- if (!args->GetInteger("tab_index", &tab_index) ||
- !args->GetString("filename", &filename)) {
- AutomationJSONReply(this, reply_message).SendError(
- "tab_index or filename param missing");
- return;
- } else {
- tab_contents = browser->GetTabContentsAt(tab_index);
- if (!tab_contents) {
- AutomationJSONReply(this, reply_message).SendError(
- "no tab at tab_index");
- return;
- }
- }
- // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
- // used. Nevertheless, SavePackage requires it be valid. Sigh.
- parent_directory = FilePath(filename).DirName().value();
- if (!tab_contents->SavePage(FilePath(filename), FilePath(parent_directory),
- SavePackage::SAVE_AS_ONLY_HTML)) {
- AutomationJSONReply(this, reply_message).SendError(
- "Could not initiate SavePage");
- return;
- }
- // The observer will delete itself when done.
- new SavePackageNotificationObserver(tab_contents->save_package(),
- this, reply_message);
-}
-
-// Refer to ImportSettings() in chrome/test/pyautolib/pyauto.py for sample
-// json input.
-// Sample json output: "{}"
-void AutomationProvider::ImportSettings(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- // Map from the json string passed over to the import item masks.
- std::map<std::string, ImportItem> string_to_import_item;
- string_to_import_item["HISTORY"] = importer::HISTORY;
- string_to_import_item["FAVORITES"] = importer::FAVORITES;
- string_to_import_item["COOKIES"] = importer::COOKIES;
- string_to_import_item["PASSWORDS"] = importer::PASSWORDS;
- string_to_import_item["SEARCH_ENGINES"] = importer::SEARCH_ENGINES;
- string_to_import_item["HOME_PAGE"] = importer::HOME_PAGE;
- string_to_import_item["ALL"] = importer::ALL;
-
- string16 browser_name;
- int import_items = 0;
- ListValue* import_items_list = NULL;
- bool first_run;
-
- if (!args->GetString("import_from", &browser_name) ||
- !args->GetBoolean("first_run", &first_run) ||
- !args->GetList("import_items", &import_items_list)) {
- AutomationJSONReply(this, reply_message).SendError(
- "Incorrect type for one or more of the arguments.");
- return;
- }
-
- int num_items = import_items_list->GetSize();
- for (int i = 0; i < num_items; i++) {
- std::string item;
- import_items_list->GetString(i, &item);
- // If the provided string is not part of the map, error out.
- if (!ContainsKey(string_to_import_item, item)) {
- AutomationJSONReply(this, reply_message).SendError(
- "Invalid item string found in import_items.");
- return;
- }
- import_items |= string_to_import_item[item];
- }
-
- ImporterHost* importer_host = new ImporterHost();
- // Get the correct ProfileInfo based on the browser they user provided.
- importer::ProfileInfo profile_info;
- int num_browsers = importer_host->GetAvailableProfileCount();
- int i = 0;
- for ( ; i < num_browsers; i++) {
- string16 name = WideToUTF16Hack(importer_host->GetSourceProfileNameAt(i));
- if (name == browser_name) {
- profile_info = importer_host->GetSourceProfileInfoAt(i);
- break;
- }
- }
- // If we made it to the end of the loop, then the input was bad.
- if (i == num_browsers) {
- AutomationJSONReply(this, reply_message).SendError(
- "Invalid browser name string found.");
- return;
- }
-
- Profile* profile = browser->profile();
-
- importer_host->SetObserver(
- new AutomationProviderImportSettingsObserver(this, reply_message));
- importer_host->StartImportSettings(profile_info, profile, import_items,
- new ProfileWriter(profile), first_run);
-}
-
-namespace {
-
-// Translates a dictionary password to a PasswordForm struct.
-webkit_glue::PasswordForm GetPasswordFormFromDict(
- const DictionaryValue& password_dict) {
-
- // If the time is specified, change time to the specified time.
- base::Time time = base::Time::Now();
- int it;
- double dt;
- if (password_dict.GetInteger("time", &it))
- time = base::Time::FromTimeT(it);
- else if (password_dict.GetReal("time", &dt))
- time = base::Time::FromDoubleT(dt);
-
- std::string signon_realm;
- string16 username_value;
- string16 password_value;
- string16 origin_url_text;
- string16 username_element;
- string16 password_element;
- string16 submit_element;
- string16 action_target_text;
- bool blacklist = false;
- string16 old_password_element;
- string16 old_password_value;
-
- // We don't care if any of these fail - they are either optional or checked
- // before this function is called.
- password_dict.GetString("signon_realm", &signon_realm);
- password_dict.GetString("username_value", &username_value);
- password_dict.GetString("password_value", &password_value);
- password_dict.GetString("origin_url", &origin_url_text);
- password_dict.GetString("username_element", &username_element);
- password_dict.GetString("password_element", &password_element);
- password_dict.GetString("submit_element", &submit_element);
- password_dict.GetString("action_target", &action_target_text);
- password_dict.GetBoolean("blacklist", &blacklist);
-
- GURL origin_gurl(origin_url_text);
- GURL action_target(action_target_text);
-
- webkit_glue::PasswordForm password_form;
- password_form.signon_realm = signon_realm;
- password_form.username_value = username_value;
- password_form.password_value = password_value;
- password_form.origin = origin_gurl;
- password_form.username_element = username_element;
- password_form.password_element = password_element;
- password_form.submit_element = submit_element;
- password_form.action = action_target;
- password_form.blacklisted_by_user = blacklist;
- password_form.date_created = time;
-
- return password_form;
-}
-
-} // namespace
-
-// See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
-// input.
-// Sample json output: { "password_added": true }
-void AutomationProvider::AddSavedPassword(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
- DictionaryValue* password_dict = NULL;
-
- if (!args->GetDictionary("password", &password_dict)) {
- reply.SendError("Password must be a dictionary.");
- return;
- }
-
- // The signon realm is effectively the primary key and must be included.
- // Check here before calling GetPasswordFormFromDict.
- if (!password_dict->HasKey("signon_realm")) {
- reply.SendError("Password must include signon_realm.");
- return;
- }
- webkit_glue::PasswordForm new_password =
- GetPasswordFormFromDict(*password_dict);
-
- Profile* profile = browser->profile();
- // Use IMPLICIT_ACCESS since new passwords aren't added off the record.
- PasswordStore* password_store =
- profile->GetPasswordStore(Profile::IMPLICIT_ACCESS);
-
- // Set the return based on whether setting the password succeeded.
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
-
- // It will be null if it's accessed in an incognito window.
- if (password_store != NULL) {
- password_store->AddLogin(new_password);
- return_value->SetBoolean("password_added", true);
- } else {
- return_value->SetBoolean("password_added", false);
- }
-
- reply.SendSuccess(return_value.get());
-}
-
-// See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
-// json input.
-// Sample json output: {}
-void AutomationProvider::RemoveSavedPassword(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
- DictionaryValue* password_dict = NULL;
-
- if (!args->GetDictionary("password", &password_dict)) {
- reply.SendError("Password must be a dictionary.");
- return;
- }
-
- // The signon realm is effectively the primary key and must be included.
- // Check here before calling GetPasswordFormFromDict.
- if (!password_dict->HasKey("signon_realm")) {
- reply.SendError("Password must include signon_realm.");
- return;
- }
- webkit_glue::PasswordForm to_remove =
- GetPasswordFormFromDict(*password_dict);
-
- Profile* profile = browser->profile();
- // Use EXPLICIT_ACCESS since passwords can be removed off the record.
- PasswordStore* password_store =
- profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
-
- password_store->RemoveLogin(to_remove);
- reply.SendSuccess(NULL);
-}
-
-// Sample json input: { "command": "GetSavedPasswords" }
-// Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
-// json output.
-void AutomationProvider::GetSavedPasswords(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- Profile* profile = browser->profile();
- // Use EXPLICIT_ACCESS since saved passwords can be retreived off the record.
- PasswordStore* password_store =
- profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
- password_store->GetAutofillableLogins(
- new AutomationProviderGetPasswordsObserver(this, reply_message));
- // Observer deletes itself after returning.
-}
-
-// Refer to ClearBrowsingData() in chrome/test/pyautolib/pyauto.py for sample
-// json input.
-// Sample json output: {}
-void AutomationProvider::ClearBrowsingData(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- std::map<std::string, BrowsingDataRemover::TimePeriod> string_to_time_period;
- string_to_time_period["LAST_HOUR"] = BrowsingDataRemover::LAST_HOUR;
- string_to_time_period["LAST_DAY"] = BrowsingDataRemover::LAST_DAY;
- string_to_time_period["LAST_WEEK"] = BrowsingDataRemover::LAST_WEEK;
- string_to_time_period["FOUR_WEEKS"] = BrowsingDataRemover::FOUR_WEEKS;
- string_to_time_period["EVERYTHING"] = BrowsingDataRemover::EVERYTHING;
-
- std::map<std::string, int> string_to_mask_value;
- string_to_mask_value["HISTORY"] = BrowsingDataRemover::REMOVE_HISTORY;
- string_to_mask_value["DOWNLOADS"] = BrowsingDataRemover::REMOVE_DOWNLOADS;
- string_to_mask_value["COOKIES"] = BrowsingDataRemover::REMOVE_COOKIES;
- string_to_mask_value["PASSWORDS"] = BrowsingDataRemover::REMOVE_PASSWORDS;
- string_to_mask_value["FORM_DATA"] = BrowsingDataRemover::REMOVE_FORM_DATA;
- string_to_mask_value["CACHE"] = BrowsingDataRemover::REMOVE_CACHE;
-
- std::string time_period;
- ListValue* to_remove;
- if (!args->GetString("time_period", &time_period) ||
- !args->GetList("to_remove", &to_remove)) {
- AutomationJSONReply(this, reply_message).SendError(
- "time_period must be a string and to_remove a list.");
- return;
- }
-
- int remove_mask = 0;
- int num_removals = to_remove->GetSize();
- for (int i = 0; i < num_removals; i++) {
- std::string removal;
- to_remove->GetString(i, &removal);
- // If the provided string is not part of the map, then error out.
- if (!ContainsKey(string_to_mask_value, removal)) {
- AutomationJSONReply(this, reply_message).SendError(
- "Invalid browsing data string found in to_remove.");
- return;
- }
- remove_mask |= string_to_mask_value[removal];
- }
-
- if (!ContainsKey(string_to_time_period, time_period)) {
- AutomationJSONReply(this, reply_message).SendError(
- "Invalid string for time_period.");
- return;
- }
-
- BrowsingDataRemover* remover = new BrowsingDataRemover(
- profile(), string_to_time_period[time_period], base::Time());
-
- remover->AddObserver(
- new AutomationProviderBrowsingDataObserver(this, reply_message));
- remover->Remove(remove_mask);
- // BrowsingDataRemover deletes itself using DeleteTask.
- // 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("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("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;
- } else if (option == "set_target_language") {
- string16 target_language;
- if (!args->GetString("target_language", &target_language)) {
- AutomationJSONReply(this, reply_message).
- SendError("Must include target_language string.");
- return;
- }
- // Get the target language index based off of the language name.
- int target_language_index = -1;
- for (int i = 0; i < translate_bar->GetLanguageCount(); i++) {
- if (translate_bar->GetLanguageDisplayableNameAt(i) == target_language) {
- target_language_index = i;
- break;
- }
- }
- if (target_language_index == -1) {
- AutomationJSONReply(this, reply_message)
- .SendError("Invalid target language string.");
- return;
- }
- // If the page has already been translated it will be translated again to
- // the new language. The observer will wait until the page has been
- // translated to reply.
- if (translate_bar->type() == TranslateInfoBarDelegate::AFTER_TRANSLATE) {
- new PageTranslatedObserver(this, reply_message, tab_contents);
- translate_bar->SetTargetLanguage(target_language_index);
- return;
- }
- // Otherwise just send the reply back immediately.
- translate_bar->SetTargetLanguage(target_language_index);
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- return_value->SetBoolean("translation_success", true);
- AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
- return;
- } else if (option == "click_always_translate_lang_button") {
- if (!translate_bar->ShouldShowAlwaysTranslateButton()) {
- AutomationJSONReply(this, reply_message)
- .SendError("Always translate button not showing.");
- return;
- }
- // Clicking 'Always Translate' triggers a translation. The observer will
- // wait until the translation is complete before sending the reply.
- new PageTranslatedObserver(this, reply_message, tab_contents);
- translate_bar->AlwaysTranslatePageLanguage();
- 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 if (option == "click_never_translate_lang_button") {
- if (!translate_bar->ShouldShowNeverTranslateButton()) {
- reply.SendError("Always translate button not showing.");
- return;
- }
- translate_bar->NeverTranslatePageLanguage();
- reply.SendSuccess(NULL);
- } else if (option == "decline_translation") {
- // This is the function called when an infobar is dismissed or when the
- // user clicks the 'Nope' translate button.
- translate_bar->TranslationDeclined();
- tab_contents->RemoveInfoBar(translate_bar);
- 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,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- Extension* theme = browser->profile()->GetTheme();
- if (theme) {
- return_value->SetString("name", theme->name());
- return_value->Set("images", theme->GetThemeImages()->DeepCopy());
- return_value->Set("colors", theme->GetThemeColors()->DeepCopy());
- return_value->Set("tints", theme->GetThemeTints()->DeepCopy());
- }
- AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
-}
-
-// Sample json input: { "command": "GetExtensionsInfo" }
-// See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
-// output.
-void AutomationProvider::GetExtensionsInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
- ExtensionsService* service = profile()->GetExtensionsService();
- if (!service) {
- reply.SendError("No extensions service.");
- }
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
- ListValue* extensions_values = new ListValue;
- const ExtensionList* extensions = service->extensions();
- for (ExtensionList::const_iterator it = extensions->begin();
- it != extensions->end(); ++it) {
- const Extension* extension = *it;
- DictionaryValue* extension_value = new DictionaryValue;
- extension_value->SetString("id", extension->id());
- extension_value->SetString("version", extension->VersionString());
- extension_value->SetString("name", extension->name());
- extension_value->SetString("public_key", extension->public_key());
- extension_value->SetString("description", extension->description());
- extension_value->SetString("background_url",
- extension->background_url().spec());
- extension_value->SetString("options_url",
- extension->options_url().spec());
- extensions_values->Append(extension_value);
- }
- return_value->Set("extensions", extensions_values);
- reply.SendSuccess(return_value.get());
-}
-
-// See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
-// json input.
-// Sample json output: {}
-void AutomationProvider::UninstallExtensionById(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
- std::string id;
- if (!args->GetString("id", &id)) {
- reply.SendError("Must include string id.");
- return;
- }
- ExtensionsService* service = profile()->GetExtensionsService();
- if (!service) {
- reply.SendError("No extensions service.");
- return;
- }
- ExtensionUnloadNotificationObserver observer;
- service->UninstallExtension(id, false);
- reply.SendSuccess(NULL);
-}
-
-// Sample json input:
-// { "command": "GetAutoFillProfile" }
-// Refer to GetAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample
-// json output.
-void AutomationProvider::GetAutoFillProfile(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- // Get the AutoFillProfiles currently in the database.
- int tab_index = 0;
- args->GetInteger("tab_index", &tab_index);
- TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
- AutomationJSONReply reply(this, reply_message);
-
- if (tab_contents) {
- PersonalDataManager* pdm = tab_contents->profile()->GetOriginalProfile()
- ->GetPersonalDataManager();
- if (pdm) {
- std::vector<AutoFillProfile*> autofill_profiles = pdm->profiles();
- std::vector<CreditCard*> credit_cards = pdm->credit_cards();
-
- ListValue* profiles = GetListFromAutoFillProfiles(autofill_profiles);
- ListValue* cards = GetListFromCreditCards(credit_cards);
-
- scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
-
- return_value->Set("profiles", profiles);
- return_value->Set("credit_cards", cards);
- reply.SendSuccess(return_value.get());
- } else {
- reply.SendError("No PersonalDataManager.");
- return;
- }
- } else {
- reply.SendError("No tab at that index.");
- return;
- }
-}
-
-// Refer to FillAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample
-// json input.
-// Sample json output: {}
-void AutomationProvider::FillAutoFillProfile(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
- ListValue* profiles = NULL;
- ListValue* cards = NULL;
- args->GetList("profiles", &profiles);
- args->GetList("credit_cards", &cards);
- std::string error_mesg;
-
- std::vector<AutoFillProfile> autofill_profiles;
- std::vector<CreditCard> credit_cards;
- // Create an AutoFillProfile for each of the dictionary profiles.
- if (profiles) {
- autofill_profiles = GetAutoFillProfilesFromList(*profiles, &error_mesg);
- }
- // Create a CreditCard for each of the dictionary values.
- if (cards) {
- credit_cards = GetCreditCardsFromList(*cards, &error_mesg);
- }
- if (!error_mesg.empty()) {
- reply.SendError(error_mesg);
- return;
- }
-
- // Save the AutoFillProfiles.
- int tab_index = 0;
- args->GetInteger("tab_index", &tab_index);
- TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
-
- if (tab_contents) {
- PersonalDataManager* pdm = tab_contents->profile()
- ->GetPersonalDataManager();
- if (pdm) {
- pdm->OnAutoFillDialogApply(profiles? &autofill_profiles : NULL,
- cards? &credit_cards : NULL);
- } else {
- reply.SendError("No PersonalDataManager.");
- return;
- }
- } else {
- reply.SendError("No tab at that index.");
- return;
- }
- reply.SendSuccess(NULL);
-}
-
-/* static */
-ListValue* AutomationProvider::GetListFromAutoFillProfiles(
- std::vector<AutoFillProfile*> autofill_profiles) {
- ListValue* profiles = new ListValue;
-
- std::map<AutoFillFieldType, std::wstring> autofill_type_to_string
- = GetAutoFillFieldToStringMap();
-
- // For each AutoFillProfile, transform it to a dictionary object to return.
- for (std::vector<AutoFillProfile*>::iterator it = autofill_profiles.begin();
- it != autofill_profiles.end(); ++it) {
- AutoFillProfile* profile = *it;
- DictionaryValue* profile_info = new DictionaryValue;
- profile_info->SetString("label", profile->Label());
- // For each of the types, if it has a value, add it to the dictionary.
- for (std::map<AutoFillFieldType, std::wstring>::iterator
- type_it = autofill_type_to_string.begin();
- type_it != autofill_type_to_string.end(); ++type_it) {
- string16 value = profile->GetFieldText(AutoFillType(type_it->first));
- if (value.length()) { // If there was something stored for that value.
- profile_info->SetString(WideToUTF8(type_it->second), value);
- }
- }
- profiles->Append(profile_info);
- }
- return profiles;
-}
-
-/* static */
-ListValue* AutomationProvider::GetListFromCreditCards(
- std::vector<CreditCard*> credit_cards) {
- ListValue* cards = new ListValue;
-
- std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
- GetCreditCardFieldToStringMap();
-
- // For each AutoFillProfile, transform it to a dictionary object to return.
- for (std::vector<CreditCard*>::iterator it = credit_cards.begin();
- it != credit_cards.end(); ++it) {
- CreditCard* card = *it;
- DictionaryValue* card_info = new DictionaryValue;
- card_info->SetString("label", card->Label());
- // For each of the types, if it has a value, add it to the dictionary.
- for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
- credit_card_type_to_string.begin();
- type_it != credit_card_type_to_string.end(); ++type_it) {
- string16 value = card->GetFieldText(AutoFillType(type_it->first));
- // If there was something stored for that value.
- if (value.length()) {
- card_info->SetString(WideToUTF8(type_it->second), value);
- }
- }
- cards->Append(card_info);
- }
- return cards;
-}
-
-/* static */
-std::vector<AutoFillProfile> AutomationProvider::GetAutoFillProfilesFromList(
- const ListValue& profiles, std::string* error_message) {
- std::vector<AutoFillProfile> autofill_profiles;
- DictionaryValue* profile_info = NULL;
- string16 profile_label;
- string16 current_value;
-
- std::map<AutoFillFieldType, std::wstring> autofill_type_to_string =
- GetAutoFillFieldToStringMap();
-
- int num_profiles = profiles.GetSize();
- for (int i = 0; i < num_profiles; i++) {
- profiles.GetDictionary(i, &profile_info);
- profile_info->GetString("label", &profile_label);
- // Choose an id of 0 so that a unique id will be created.
- AutoFillProfile profile(profile_label, 0);
- // Loop through the possible profile types and add those provided.
- for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
- autofill_type_to_string.begin();
- type_it != autofill_type_to_string.end(); ++type_it) {
- if (profile_info->HasKey(WideToUTF8(type_it->second))) {
- if (profile_info->GetString(WideToUTF8(type_it->second),
- &current_value)) {
- profile.SetInfo(AutoFillType(type_it->first), current_value);
- } else {
- *error_message= "All values must be strings";
- break;
- }
- }
- }
- autofill_profiles.push_back(profile);
- }
- return autofill_profiles;
-}
-
-/* static */
-std::vector<CreditCard> AutomationProvider::GetCreditCardsFromList(
- const ListValue& cards, std::string* error_message) {
- std::vector<CreditCard> credit_cards;
- DictionaryValue* card_info = NULL;
- string16 card_label;
- string16 current_value;
-
- std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
- GetCreditCardFieldToStringMap();
-
- int num_credit_cards = cards.GetSize();
- for (int i = 0; i < num_credit_cards; i++) {
- cards.GetDictionary(i, &card_info);
- card_info->GetString("label", &card_label);
- CreditCard card(card_label, 0);
- // Loop through the possible credit card fields and add those provided.
- for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
- credit_card_type_to_string.begin();
- type_it != credit_card_type_to_string.end(); ++type_it) {
- if (card_info->HasKey(WideToUTF8(type_it->second))) {
- if (card_info->GetString(WideToUTF8(type_it->second), &current_value)) {
- card.SetInfo(AutoFillType(type_it->first), current_value);
- } else {
- *error_message= "All values must be strings";
- break;
- }
- }
- }
- credit_cards.push_back(card);
- }
- return credit_cards;
-}
-
-/* static */
-std::map<AutoFillFieldType, std::wstring>
- AutomationProvider::GetAutoFillFieldToStringMap() {
- std::map<AutoFillFieldType, std::wstring> autofill_type_to_string;
- autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
- autofill_type_to_string[NAME_MIDDLE] = L"NAME_MIDDLE";
- autofill_type_to_string[NAME_LAST] = L"NAME_LAST";
- autofill_type_to_string[COMPANY_NAME] = L"COMPANY_NAME";
- autofill_type_to_string[EMAIL_ADDRESS] = L"EMAIL_ADDRESS";
- autofill_type_to_string[ADDRESS_HOME_LINE1] = L"ADDRESS_HOME_LINE1";
- autofill_type_to_string[ADDRESS_HOME_LINE2] = L"ADDRESS_HOME_LINE2";
- autofill_type_to_string[ADDRESS_HOME_CITY] = L"ADDRESS_HOME_CITY";
- autofill_type_to_string[ADDRESS_HOME_STATE] = L"ADDRESS_HOME_STATE";
- autofill_type_to_string[ADDRESS_HOME_ZIP] = L"ADDRESS_HOME_ZIP";
- autofill_type_to_string[ADDRESS_HOME_COUNTRY] = L"ADDRESS_HOME_COUNTRY";
- autofill_type_to_string[PHONE_HOME_NUMBER] = L"PHONE_HOME_NUMBER";
- autofill_type_to_string[PHONE_FAX_NUMBER] = L"PHONE_FAX_NUMBER";
- autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
- return autofill_type_to_string;
-}
-
-/* static */
-std::map<AutoFillFieldType, std::wstring>
- AutomationProvider::GetCreditCardFieldToStringMap() {
- std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string;
- credit_card_type_to_string[CREDIT_CARD_NAME] = L"CREDIT_CARD_NAME";
- credit_card_type_to_string[CREDIT_CARD_NUMBER] = L"CREDIT_CARD_NUMBER";
- credit_card_type_to_string[CREDIT_CARD_EXP_MONTH] = L"CREDIT_CARD_EXP_MONTH";
- credit_card_type_to_string[CREDIT_CARD_EXP_4_DIGIT_YEAR] =
- L"CREDIT_CARD_EXP_4_DIGIT_YEAR";
- return credit_card_type_to_string;
-}
-
-void AutomationProvider::SendJSONRequest(int handle,
- std::string json_request,
- IPC::Message* reply_message) {
- Browser* browser = NULL;
- scoped_ptr<Value> values;
-
- // Basic error checking.
- if (browser_tracker_->ContainsHandle(handle)) {
- browser = browser_tracker_->GetResource(handle);
- }
- if (!browser) {
- AutomationJSONReply(this, reply_message).SendError("no browser object");
- return;
- }
- base::JSONReader reader;
- std::string error;
- values.reset(reader.ReadAndReturnError(json_request, true, NULL, &error));
- if (!error.empty()) {
- AutomationJSONReply(this, reply_message).SendError(error);
- return;
- }
-
- // Make sure input is a dict with a string command.
- std::string command;
- DictionaryValue* dict_value = NULL;
- if (values->GetType() != Value::TYPE_DICTIONARY) {
- AutomationJSONReply(this, reply_message).SendError("not a dict");
- return;
- }
- // Ownership remains with "values" variable.
- dict_value = static_cast<DictionaryValue*>(values.get());
- if (!dict_value->GetStringASCII(std::string("command"), &command)) {
- AutomationJSONReply(this, reply_message).SendError(
- "no command key in dict or not a string command");
- return;
- }
-
- // Map json commands to their handlers.
- std::map<std::string, JsonHandler> handler_map;
- handler_map["DisablePlugin"] = &AutomationProvider::DisablePlugin;
- handler_map["EnablePlugin"] = &AutomationProvider::EnablePlugin;
- handler_map["GetPluginsInfo"] = &AutomationProvider::GetPluginsInfo;
-
- handler_map["GetBrowserInfo"] = &AutomationProvider::GetBrowserInfo;
-
- handler_map["GetNavigationInfo"] = &AutomationProvider::GetNavigationInfo;
-
- handler_map["PerformActionOnInfobar"] =
- &AutomationProvider::PerformActionOnInfobar;
-
- handler_map["GetHistoryInfo"] = &AutomationProvider::GetHistoryInfo;
- handler_map["AddHistoryItem"] = &AutomationProvider::AddHistoryItem;
-
- handler_map["GetOmniboxInfo"] = &AutomationProvider::GetOmniboxInfo;
- handler_map["SetOmniboxText"] = &AutomationProvider::SetOmniboxText;
- handler_map["OmniboxAcceptInput"] = &AutomationProvider::OmniboxAcceptInput;
- handler_map["OmniboxMovePopupSelection"] =
- &AutomationProvider::OmniboxMovePopupSelection;
-
- handler_map["GetPrefsInfo"] = &AutomationProvider::GetPrefsInfo;
- handler_map["SetPrefs"] = &AutomationProvider::SetPrefs;
-
- handler_map["SetWindowDimensions"] = &AutomationProvider::SetWindowDimensions;
-
- handler_map["GetDownloadsInfo"] = &AutomationProvider::GetDownloadsInfo;
- handler_map["WaitForAllDownloadsToComplete"] =
- &AutomationProvider::WaitForDownloadsToComplete;
- handler_map["PerformActionOnDownload"] =
- &AutomationProvider::PerformActionOnDownload;
-
- handler_map["GetInitialLoadTimes"] = &AutomationProvider::GetInitialLoadTimes;
-
- handler_map["SaveTabContents"] = &AutomationProvider::SaveTabContents;
-
- handler_map["ImportSettings"] = &AutomationProvider::ImportSettings;
-
- handler_map["AddSavedPassword"] = &AutomationProvider::AddSavedPassword;
- handler_map["RemoveSavedPassword"] =
- &AutomationProvider::RemoveSavedPassword;
- handler_map["GetSavedPasswords"] = &AutomationProvider::GetSavedPasswords;
-
- handler_map["ClearBrowsingData"] = &AutomationProvider::ClearBrowsingData;
-
- // SetTheme() implemented using InstallExtension().
- handler_map["GetThemeInfo"] = &AutomationProvider::GetThemeInfo;
-
- // InstallExtension() present in pyauto.py.
- handler_map["GetExtensionsInfo"] = &AutomationProvider::GetExtensionsInfo;
- handler_map["UninstallExtensionById"] =
- &AutomationProvider::UninstallExtensionById;
-
- handler_map["SelectTranslateOption"] =
- &AutomationProvider::SelectTranslateOption;
- handler_map["GetTranslateInfo"] = &AutomationProvider::GetTranslateInfo;
-
- handler_map["GetAutoFillProfile"] = &AutomationProvider::GetAutoFillProfile;
- handler_map["FillAutoFillProfile"] = &AutomationProvider::FillAutoFillProfile;
-
- if (handler_map.find(std::string(command)) != handler_map.end()) {
- (this->*handler_map[command])(browser, dict_value, reply_message);
- } else {
- std::string error_string = "Unknown command. Options: ";
- for (std::map<std::string, JsonHandler>::const_iterator it =
- handler_map.begin(); it != handler_map.end(); ++it) {
- error_string += it->first + ", ";
- }
- AutomationJSONReply(this, reply_message).SendError(error_string);
- }
-}
-
class SetProxyConfigTask : public Task {
public:
SetProxyConfigTask(URLRequestContextGetter* request_context_getter,
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index 00cc478..508e067 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -169,6 +169,7 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
scoped_ptr<AutomationAutocompleteEditTracker> autocomplete_edit_tracker_;
scoped_ptr<AutomationBrowserTracker> browser_tracker_;
+ scoped_ptr<InitialLoadObserver> initial_load_observer_;
scoped_ptr<MetricEventDurationObserver> metric_event_duration_observer_;
scoped_ptr<NavigationControllerRestoredObserver> restore_tracker_;
scoped_ptr<AutomationTabTracker> tab_tracker_;
@@ -221,255 +222,6 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
const AutomationMsg_Find_Params& params,
IPC::Message* reply_message);
- // Set window dimensions.
- // Uses the JSON interface for input/output.
- void SetWindowDimensions(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about infobars in the given TabContents object.
- // This includes info about the type of infobars, the message text,
- // buttons, etc.
- // Caller owns the returned object.
- ListValue* GetInfobarsInfo(TabContents* tc);
-
- // Perform actions on an infobar like dismiss, accept, cancel.
- // Uses the JSON interface for input/output.
- void PerformActionOnInfobar(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about the chromium/chrome in use.
- // This includes things like version, executable name, executable path.
- // Uses the JSON interface for input/output.
- void GetBrowserInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about the state of navigation in a given tab.
- // This includes ssl info.
- // Uses the JSON interface for input/output.
- void GetNavigationInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about downloads. This includes only ones that have been
- // registered by the history system.
- // Uses the JSON interface for input/output.
- void GetDownloadsInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Wait for all downloads to complete.
- // Uses the JSON interface for input/output.
- void WaitForDownloadsToComplete(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Performs the given action on the specified download.
- // Uses the JSON interface for input/output.
- void PerformActionOnDownload(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about history.
- // Uses the JSON interface for input/output.
- void GetHistoryInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Add an item to the history service.
- // Uses the JSON interface for input/output.
- void AddHistoryItem(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about preferences.
- // Uses the JSON interface for input/output.
- void GetPrefsInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Set prefs.
- // Uses the JSON interface for input/output.
- void SetPrefs(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Return load times of initial tabs.
- // Uses the JSON interface for input/output.
- // Only includes tabs from command line arguments or session restore.
- // See declaration of InitialLoadObserver in automation_provider_observers.h
- // for example response.
- void GetInitialLoadTimes(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about plugins.
- // Uses the JSON interface for input/output.
- void GetPluginsInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Enable a plugin.
- // Uses the JSON interface for input/output.
- void EnablePlugin(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Disable a plugin.
- // Uses the JSON interface for input/output.
- void DisablePlugin(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about omnibox.
- // Contains data about the matches (url, content, description)
- // in the omnibox popup, the text in the omnibox.
- // Uses the JSON interface for input/output.
- void GetOmniboxInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Set text in the omnibox. This sets focus to the omnibox.
- // Uses the JSON interface for input/output.
- void SetOmniboxText(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Move omnibox popup selection up or down.
- // Uses the JSON interface for input/output.
- void OmniboxMovePopupSelection(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Accept the current string of text in the omnibox.
- // This is equivalent to clicking or hiting enter on a popup selection.
- // Blocks until the page loads.
- // Uses the JSON interface for input/output.
- void OmniboxAcceptInput(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Save the contents of a tab into a file.
- // Uses the JSON interface for input/output.
- void SaveTabContents(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Import the given settings from the given browser.
- // Uses the JSON interface for input/output.
- void ImportSettings(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Add a new entry to the password store based on the password information
- // provided. This method can also be used to add a blacklisted site (which
- // will never fill in the password).
- // Uses the JSON interface for input/output.
- void AddSavedPassword(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Removes the password matching the information provided. This method can
- // also be used to remove a blacklisted site.
- // Uses the JSON interface for input/output.
- void RemoveSavedPassword(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Return the saved username/password combinations.
- // Uses the JSON interface for input/output.
- void GetSavedPasswords(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Clear the specified browsing data. This call provides similar
- // functionality to RemoveBrowsingData but is synchronous.
- // Uses the JSON interface for input/output.
- void ClearBrowsingData(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about theme.
- // Uses the JSON interface for input/output.
- void GetThemeInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Get info about all intalled extensions.
- // Uses the JSON interface for input/output.
- void GetExtensionsInfo(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Uninstalls the extension with the given id.
- // Uses the JSON interface for input/output.
- void UninstallExtensionById(Browser* browser,
- 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,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Fill in an AutoFillProfile with the given profile information.
- // Uses the JSON interface for input/output.
- void FillAutoFillProfile(Browser* browser,
- DictionaryValue* args,
- IPC::Message* reply_message);
-
- // Translate DictionaryValues of autofill profiles and credit cards to the
- // data structure used in the browser.
- // Args:
- // profiles/cards: the ListValue of profiles/credit cards to translate.
- // error_message: a pointer to the return string in case of error.
- static std::vector<AutoFillProfile> GetAutoFillProfilesFromList(
- const ListValue& profiles, std::string* error_message);
- static std::vector<CreditCard> GetCreditCardsFromList(
- const ListValue& cards, std::string* error_message);
-
- // The opposite of the above: translates from the internal data structure
- // for profiles and credit cards to a ListValue of DictionaryValues. The
- // caller owns the returned object.
- static ListValue* GetListFromAutoFillProfiles(
- std::vector<AutoFillProfile*> autofill_profiles);
- static ListValue* GetListFromCreditCards(
- std::vector<CreditCard*> credit_cards);
-
- // Return the map from the internal data representation to the string value
- // of auto fill fields and credit card fields.
- static std::map<AutoFillFieldType, std::wstring>
- GetAutoFillFieldToStringMap();
- static std::map<AutoFillFieldType, std::wstring>
- GetCreditCardFieldToStringMap();
-
- // Generic pattern for pyautolib
- // Uses the JSON interface for input/output.
- void SendJSONRequest(int handle,
- std::string json_request,
- IPC::Message* reply_message);
-
- // Method ptr for json handlers.
- // Uses the JSON interface for input/output.
- typedef void (AutomationProvider::*JsonHandler)(Browser* browser,
- DictionaryValue*,
- IPC::Message*);
-
void OnSetPageFontSize(int tab_handle, int font_size);
// See browsing_data_remover.h for explanation of bitmap fields.
@@ -632,7 +384,6 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
typedef std::map<int, ExtensionPortContainer*> PortContainerMap;
scoped_ptr<IPC::ChannelProxy> channel_;
- scoped_ptr<InitialLoadObserver> initial_load_observer_;
scoped_ptr<NotificationObserver> new_tab_ui_load_observer_;
scoped_ptr<NotificationObserver> find_in_page_observer_;
scoped_ptr<NotificationObserver> dom_operation_observer_;
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index b5cb004..89c69f0 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -6,14 +6,20 @@
#include "app/message_box_flags.h"
#include "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/json/string_escape.h"
+#include "base/path_service.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/app_modal_dialog.h"
#include "chrome/browser/app_modal_dialog_queue.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
+#include "chrome/browser/autofill/autofill_manager.h"
#include "chrome/browser/automation/automation_autocomplete_edit_tracker.h"
#include "chrome/browser/automation/automation_browser_tracker.h"
+#include "chrome/browser/automation/automation_provider_json.h"
#include "chrome/browser/automation/automation_provider_list.h"
#include "chrome/browser/automation/automation_provider_observers.h"
#include "chrome/browser/automation/automation_tab_tracker.h"
@@ -27,16 +33,22 @@
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/download/download_shelf.h"
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/find_bar.h"
#include "chrome/browser/location_bar.h"
#include "chrome/browser/login_prompt.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/prefs/pref_service.h"
+#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/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/interstitial_page.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "chrome/common/notification_service.h"
@@ -45,6 +57,7 @@
#include "net/base/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "views/event.h"
+#include "webkit/glue/plugins/plugin_list.h"
namespace {
@@ -388,6 +401,8 @@ void TestingAutomationProvider::OnMessageReceived(
IPC_MESSAGE_HANDLER(AutomationMsg_WindowTitle, GetWindowTitle)
IPC_MESSAGE_HANDLER(AutomationMsg_SetShelfVisibility, SetShelfVisibility)
IPC_MESSAGE_HANDLER(AutomationMsg_BlockedPopupCount, GetBlockedPopupCount)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest,
+ SendJSONRequest)
IPC_MESSAGE_UNHANDLED(AutomationProvider::OnMessageReceived(message));
IPC_END_MESSAGE_MAP()
@@ -1919,6 +1934,1761 @@ void TestingAutomationProvider::GetBlockedPopupCount(int handle, int* count) {
}
}
+void TestingAutomationProvider::SendJSONRequest(int handle,
+ std::string json_request,
+ IPC::Message* reply_message) {
+ Browser* browser = NULL;
+ scoped_ptr<Value> values;
+
+ // Basic error checking.
+ if (browser_tracker_->ContainsHandle(handle)) {
+ browser = browser_tracker_->GetResource(handle);
+ }
+ if (!browser) {
+ AutomationJSONReply(this, reply_message).SendError("no browser object");
+ return;
+ }
+ base::JSONReader reader;
+ std::string error;
+ values.reset(reader.ReadAndReturnError(json_request, true, NULL, &error));
+ if (!error.empty()) {
+ AutomationJSONReply(this, reply_message).SendError(error);
+ return;
+ }
+
+ // Make sure input is a dict with a string command.
+ std::string command;
+ DictionaryValue* dict_value = NULL;
+ if (values->GetType() != Value::TYPE_DICTIONARY) {
+ AutomationJSONReply(this, reply_message).SendError("not a dict");
+ return;
+ }
+ // Ownership remains with "values" variable.
+ dict_value = static_cast<DictionaryValue*>(values.get());
+ if (!dict_value->GetStringASCII(std::string("command"), &command)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "no command key in dict or not a string command");
+ return;
+ }
+
+ // Map json commands to their handlers.
+ std::map<std::string, JsonHandler> handler_map;
+ handler_map["DisablePlugin"] = &TestingAutomationProvider::DisablePlugin;
+ handler_map["EnablePlugin"] = &TestingAutomationProvider::EnablePlugin;
+ handler_map["GetPluginsInfo"] = &TestingAutomationProvider::GetPluginsInfo;
+
+ handler_map["GetBrowserInfo"] = &TestingAutomationProvider::GetBrowserInfo;
+
+ handler_map["GetNavigationInfo"] =
+ &TestingAutomationProvider::GetNavigationInfo;
+
+ handler_map["PerformActionOnInfobar"] =
+ &TestingAutomationProvider::PerformActionOnInfobar;
+
+ handler_map["GetHistoryInfo"] = &TestingAutomationProvider::GetHistoryInfo;
+ handler_map["AddHistoryItem"] = &TestingAutomationProvider::AddHistoryItem;
+
+ handler_map["GetOmniboxInfo"] = &TestingAutomationProvider::GetOmniboxInfo;
+ handler_map["SetOmniboxText"] = &TestingAutomationProvider::SetOmniboxText;
+ handler_map["OmniboxAcceptInput"] =
+ &TestingAutomationProvider::OmniboxAcceptInput;
+ handler_map["OmniboxMovePopupSelection"] =
+ &TestingAutomationProvider::OmniboxMovePopupSelection;
+
+ handler_map["GetPrefsInfo"] = &TestingAutomationProvider::GetPrefsInfo;
+ handler_map["SetPrefs"] = &TestingAutomationProvider::SetPrefs;
+
+ handler_map["SetWindowDimensions"] =
+ &TestingAutomationProvider::SetWindowDimensions;
+
+ handler_map["GetDownloadsInfo"] =
+ &TestingAutomationProvider::GetDownloadsInfo;
+ handler_map["WaitForAllDownloadsToComplete"] =
+ &TestingAutomationProvider::WaitForDownloadsToComplete;
+ handler_map["PerformActionOnDownload"] =
+ &TestingAutomationProvider::PerformActionOnDownload;
+
+ handler_map["GetInitialLoadTimes"] =
+ &TestingAutomationProvider::GetInitialLoadTimes;
+
+ handler_map["SaveTabContents"] = &TestingAutomationProvider::SaveTabContents;
+
+ handler_map["ImportSettings"] = &TestingAutomationProvider::ImportSettings;
+
+ handler_map["AddSavedPassword"] =
+ &TestingAutomationProvider::AddSavedPassword;
+ handler_map["RemoveSavedPassword"] =
+ &TestingAutomationProvider::RemoveSavedPassword;
+ handler_map["GetSavedPasswords"] =
+ &TestingAutomationProvider::GetSavedPasswords;
+
+ handler_map["ClearBrowsingData"] =
+ &TestingAutomationProvider::ClearBrowsingData;
+
+ // SetTheme() implemented using InstallExtension().
+ handler_map["GetThemeInfo"] = &TestingAutomationProvider::GetThemeInfo;
+
+ // InstallExtension() present in pyauto.py.
+ handler_map["GetExtensionsInfo"] =
+ &TestingAutomationProvider::GetExtensionsInfo;
+ handler_map["UninstallExtensionById"] =
+ &TestingAutomationProvider::UninstallExtensionById;
+
+ handler_map["SelectTranslateOption"] =
+ &TestingAutomationProvider::SelectTranslateOption;
+ handler_map["GetTranslateInfo"] =
+ &TestingAutomationProvider::GetTranslateInfo;
+
+ handler_map["GetAutoFillProfile"] =
+ &TestingAutomationProvider::GetAutoFillProfile;
+ handler_map["FillAutoFillProfile"] =
+ &TestingAutomationProvider::FillAutoFillProfile;
+
+ if (handler_map.find(std::string(command)) != handler_map.end()) {
+ (this->*handler_map[command])(browser, dict_value, reply_message);
+ } else {
+ std::string error_string = "Unknown command. Options: ";
+ for (std::map<std::string, JsonHandler>::const_iterator it =
+ handler_map.begin(); it != handler_map.end(); ++it) {
+ error_string += it->first + ", ";
+ }
+ AutomationJSONReply(this, reply_message).SendError(error_string);
+ }
+}
+
+// Sample json input: { "command": "SetWindowDimensions",
+// "x": 20, # optional
+// "y": 20, # optional
+// "width": 800, # optional
+// "height": 600 } # optional
+void TestingAutomationProvider::SetWindowDimensions(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ gfx::Rect rect = browser->window()->GetRestoredBounds();
+ int x, y, width, height;
+ if (args->GetInteger("x", &x))
+ rect.set_x(x);
+ if (args->GetInteger("y", &y))
+ rect.set_y(y);
+ if (args->GetInteger("width", &width))
+ rect.set_width(width);
+ if (args->GetInteger("height", &height))
+ rect.set_height(height);
+ browser->window()->SetBounds(rect);
+ AutomationJSONReply(this, reply_message).SendSuccess(NULL);
+}
+
+ListValue* TestingAutomationProvider::GetInfobarsInfo(TabContents* tc) {
+ // Each infobar may have different properties depending on the type.
+ ListValue* infobars = new ListValue;
+ for (int infobar_index = 0;
+ infobar_index < tc->infobar_delegate_count();
+ ++infobar_index) {
+ DictionaryValue* infobar_item = new DictionaryValue;
+ InfoBarDelegate* infobar = tc->GetInfoBarDelegateAt(infobar_index);
+ if (infobar->AsConfirmInfoBarDelegate()) {
+ // Also covers ThemeInstalledInfoBarDelegate and
+ // CrashedExtensionInfoBarDelegate.
+ infobar_item->SetString("type", "confirm_infobar");
+ ConfirmInfoBarDelegate* confirm_infobar =
+ infobar->AsConfirmInfoBarDelegate();
+ infobar_item->SetString("text", confirm_infobar->GetMessageText());
+ infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
+ ListValue* buttons_list = new ListValue;
+ int buttons = confirm_infobar->GetButtons();
+ if (ConfirmInfoBarDelegate::BUTTON_OK & buttons) {
+ StringValue* button_label = new StringValue(
+ confirm_infobar->GetButtonLabel(
+ ConfirmInfoBarDelegate::BUTTON_OK));
+ buttons_list->Append(button_label);
+ }
+ if (ConfirmInfoBarDelegate::BUTTON_CANCEL & buttons) {
+ StringValue* button_label = new StringValue(
+ confirm_infobar->GetButtonLabel(
+ ConfirmInfoBarDelegate::BUTTON_CANCEL));
+ buttons_list->Append(button_label);
+ }
+ infobar_item->Set("buttons", buttons_list);
+ } else if (infobar->AsAlertInfoBarDelegate()) {
+ infobar_item->SetString("type", "alert_infobar");
+ AlertInfoBarDelegate* alert_infobar =
+ infobar->AsAlertInfoBarDelegate();
+ infobar_item->SetString("text", alert_infobar->GetMessageText());
+ } else if (infobar->AsLinkInfoBarDelegate()) {
+ infobar_item->SetString("type", "link_infobar");
+ LinkInfoBarDelegate* link_infobar = infobar->AsLinkInfoBarDelegate();
+ infobar_item->SetString("link_text", link_infobar->GetLinkText());
+ } else if (infobar->AsTranslateInfoBarDelegate()) {
+ infobar_item->SetString("type", "translate_infobar");
+ TranslateInfoBarDelegate* translate_infobar =
+ infobar->AsTranslateInfoBarDelegate();
+ infobar_item->SetString("original_lang_code",
+ translate_infobar->GetOriginalLanguageCode());
+ infobar_item->SetString("target_lang_code",
+ translate_infobar->GetTargetLanguageCode());
+ } else if (infobar->AsExtensionInfoBarDelegate()) {
+ infobar_item->SetString("type", "extension_infobar");
+ } else {
+ infobar_item->SetString("type", "unknown_infobar");
+ }
+ infobars->Append(infobar_item);
+ }
+ return infobars;
+}
+
+// Sample json input: { "command": "PerformActionOnInfobar",
+// "action": "dismiss",
+// "infobar_index": 0,
+// "tab_index": 0 }
+// Sample output: {}
+void TestingAutomationProvider::PerformActionOnInfobar(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ int tab_index;
+ int infobar_index;
+ std::string action;
+ if (!args->GetInteger("tab_index", &tab_index) ||
+ !args->GetInteger("infobar_index", &infobar_index) ||
+ !args->GetString("action", &action)) {
+ reply.SendError("Invalid or missing args");
+ return;
+ }
+ TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
+ if (!tab_contents) {
+ reply.SendError(StringPrintf("No such tab at index %d", tab_index));
+ return;
+ }
+ InfoBarDelegate* infobar = NULL;
+ if (infobar_index < 0 ||
+ infobar_index >= tab_contents->infobar_delegate_count() ||
+ !(infobar = tab_contents->GetInfoBarDelegateAt(infobar_index))) {
+ reply.SendError(StringPrintf("No such infobar at index %d", infobar_index));
+ return;
+ }
+ if ("dismiss" == action) {
+ infobar->InfoBarDismissed();
+ tab_contents->RemoveInfoBar(infobar);
+ reply.SendSuccess(NULL);
+ return;
+ }
+ if ("accept" == action || "cancel" == action) {
+ ConfirmInfoBarDelegate* confirm_infobar;
+ if (!(confirm_infobar = infobar->AsConfirmInfoBarDelegate())) {
+ reply.SendError("Not a confirm infobar");
+ return;
+ }
+ if ("accept" == action) {
+ if (confirm_infobar->Accept())
+ tab_contents->RemoveInfoBar(infobar);
+ } else if ("cancel" == action) {
+ if (confirm_infobar->Cancel())
+ tab_contents->RemoveInfoBar(infobar);
+ }
+ reply.SendSuccess(NULL);
+ return;
+ }
+ reply.SendError("Invalid action");
+}
+
+namespace {
+
+// Task to get info about BrowserChildProcessHost. Must run on IO thread to
+// honor the semantics of BrowserChildProcessHost.
+// Used by AutomationProvider::GetBrowserInfo().
+class GetChildProcessHostInfoTask : public Task {
+ public:
+ GetChildProcessHostInfoTask(base::WaitableEvent* event,
+ ListValue* child_processes)
+ : event_(event),
+ child_processes_(child_processes) {}
+
+ virtual void Run() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ for (BrowserChildProcessHost::Iterator iter; !iter.Done(); ++iter) {
+ // Only add processes which are already started,
+ // since we need their handle.
+ if ((*iter)->handle() == base::kNullProcessHandle) {
+ continue;
+ }
+ ChildProcessInfo* info = *iter;
+ DictionaryValue* item = new DictionaryValue;
+ item->SetString("name", WideToUTF16Hack(info->name()));
+ item->SetString("type",
+ ChildProcessInfo::GetTypeNameInEnglish(info->type()));
+ item->SetInteger("pid", base::GetProcId(info->handle()));
+ child_processes_->Append(item);
+ }
+ event_->Signal();
+ }
+
+ private:
+ base::WaitableEvent* const event_; // weak
+ ListValue* child_processes_;
+
+ DISALLOW_COPY_AND_ASSIGN(GetChildProcessHostInfoTask);
+};
+
+} // namespace
+
+// Sample json input: { "command": "GetBrowserInfo" }
+// Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
+// sample json output.
+void TestingAutomationProvider::GetBrowserInfo(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ DictionaryValue* properties = new DictionaryValue;
+ properties->SetString("ChromeVersion", chrome::kChromeVersion);
+ properties->SetString("BrowserProcessExecutableName",
+ WideToUTF16Hack(chrome::kBrowserProcessExecutableName));
+ properties->SetString("HelperProcessExecutableName",
+ WideToUTF16Hack(chrome::kHelperProcessExecutableName));
+ properties->SetString("BrowserProcessExecutablePath",
+ WideToUTF16Hack(chrome::kBrowserProcessExecutablePath));
+ properties->SetString("HelperProcessExecutablePath",
+ chrome::kHelperProcessExecutablePath);
+ properties->SetString("command_line_string",
+ CommandLine::ForCurrentProcess()->command_line_string());
+ FilePath dumps_path;
+ PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
+ properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
+
+ std::string branding;
+#if defined(GOOGLE_CHROME_BUILD)
+ branding = "Google Chrome";
+#elif defined(CHROMIUM_BUILD)
+ branding = "Chromium";
+#else
+ branding = "Unknown Branding";
+#endif
+ properties->SetString("branding", branding);
+
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ return_value->Set("properties", properties);
+
+ return_value->SetInteger("browser_pid", base::GetCurrentProcId());
+ // Add info about all windows in a list of dictionaries, one dictionary
+ // item per window.
+ ListValue* windows = new ListValue;
+ int windex = 0;
+ for (BrowserList::const_iterator it = BrowserList::begin();
+ it != BrowserList::end();
+ ++it, ++windex) {
+ DictionaryValue* browser_item = new DictionaryValue;
+ browser = *it;
+ browser_item->SetInteger("index", windex);
+ // Window properties
+ gfx::Rect rect = browser->window()->GetRestoredBounds();
+ browser_item->SetInteger("x", rect.x());
+ browser_item->SetInteger("y", rect.y());
+ browser_item->SetInteger("width", rect.width());
+ browser_item->SetInteger("height", rect.height());
+ browser_item->SetBoolean("fullscreen",
+ browser->window()->IsFullscreen());
+ browser_item->SetInteger("selected_tab", browser->selected_index());
+ browser_item->SetBoolean("incognito",
+ browser->profile()->IsOffTheRecord());
+ // For each window, add info about all tabs in a list of dictionaries,
+ // one dictionary item per tab.
+ ListValue* tabs = new ListValue;
+ for (int i = 0; i < browser->tab_count(); ++i) {
+ TabContents* tc = browser->GetTabContentsAt(i);
+ DictionaryValue* tab = new DictionaryValue;
+ tab->SetInteger("index", i);
+ tab->SetString("url", tc->GetURL().spec());
+ tab->SetInteger("renderer_pid",
+ base::GetProcId(tc->GetRenderProcessHost()->GetHandle()));
+ tab->Set("infobars", GetInfobarsInfo(tc));
+ tabs->Append(tab);
+ }
+ browser_item->Set("tabs", tabs);
+
+ windows->Append(browser_item);
+ }
+ return_value->Set("windows", windows);
+
+ return_value->SetString("child_process_path",
+ ChildProcessHost::GetChildPath(true).value());
+ // Child processes are the processes for plugins and other workers.
+ // Add all child processes in a list of dictionaries, one dictionary item
+ // per child process.
+ ListValue* child_processes = new ListValue;
+ base::WaitableEvent event(true /* manual reset */,
+ false /* not initially signaled */);
+ CHECK(ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ new GetChildProcessHostInfoTask(&event, child_processes)));
+ event.Wait();
+ return_value->Set("child_processes", child_processes);
+
+ // Add all extension processes in a list of dictionaries, one dictionary
+ // item per extension process.
+ ListValue* extension_processes = new ListValue;
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ for (ProfileManager::const_iterator it = profile_manager->begin();
+ it != profile_manager->end(); ++it) {
+ ExtensionProcessManager* process_manager =
+ (*it)->GetExtensionProcessManager();
+ ExtensionProcessManager::const_iterator jt;
+ for (jt = process_manager->begin(); jt != process_manager->end(); ++jt) {
+ ExtensionHost* ex_host = *jt;
+ // Don't add dead extension processes.
+ if (!ex_host->IsRenderViewLive())
+ continue;
+ DictionaryValue* item = new DictionaryValue;
+ item->SetString("name", ex_host->extension()->name());
+ item->SetInteger(
+ "pid",
+ base::GetProcId(ex_host->render_process_host()->GetHandle()));
+ extension_processes->Append(item);
+ }
+ }
+ return_value->Set("extension_processes", extension_processes);
+ AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
+}
+
+// Sample json input: { "command": "GetNavigationInfo" }
+// Refer to GetNavigationInfo() in chrome/test/pyautolib/pyauto.py for
+// sample json output.
+void TestingAutomationProvider::GetNavigationInfo(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ int tab_index;
+ TabContents* tab_contents = NULL;
+ if (!args->GetInteger("tab_index", &tab_index) ||
+ !(tab_contents = browser->GetTabContentsAt(tab_index))) {
+ reply.SendError("tab_index missing or invalid.");
+ return;
+ }
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ const NavigationController& controller = tab_contents->controller();
+ NavigationEntry* nav_entry = controller.GetActiveEntry();
+ DCHECK(nav_entry);
+
+ // Security info.
+ DictionaryValue* ssl = new DictionaryValue;
+ std::map<SecurityStyle, std::string> style_to_string;
+ style_to_string[SECURITY_STYLE_UNKNOWN] = "SECURITY_STYLE_UNKNOWN";
+ style_to_string[SECURITY_STYLE_UNAUTHENTICATED] =
+ "SECURITY_STYLE_UNAUTHENTICATED";
+ style_to_string[SECURITY_STYLE_AUTHENTICATION_BROKEN] =
+ "SECURITY_STYLE_AUTHENTICATION_BROKEN";
+ style_to_string[SECURITY_STYLE_AUTHENTICATED] =
+ "SECURITY_STYLE_AUTHENTICATED";
+
+ NavigationEntry::SSLStatus ssl_status = nav_entry->ssl();
+ ssl->SetString("security_style",
+ style_to_string[ssl_status.security_style()]);
+ ssl->SetBoolean("ran_insecure_content", ssl_status.ran_insecure_content());
+ ssl->SetBoolean("displayed_insecure_content",
+ ssl_status.displayed_insecure_content());
+ return_value->Set("ssl", ssl);
+
+ // Page type.
+ std::map<NavigationEntry::PageType, std::string> pagetype_to_string;
+ pagetype_to_string[NavigationEntry::NORMAL_PAGE] = "NORMAL_PAGE";
+ pagetype_to_string[NavigationEntry::ERROR_PAGE] = "ERROR_PAGE";
+ pagetype_to_string[NavigationEntry::INTERSTITIAL_PAGE] = "INTERSTITIAL_PAGE";
+ return_value->SetString("page_type",
+ pagetype_to_string[nav_entry->page_type()]);
+
+ return_value->SetString("favicon_url", nav_entry->favicon().url().spec());
+ reply.SendSuccess(return_value.get());
+}
+
+// Sample json input: { "command": "GetHistoryInfo",
+// "search_text": "some text" }
+// Refer chrome/test/pyautolib/history_info.py for sample json output.
+void TestingAutomationProvider::GetHistoryInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ consumer_.CancelAllRequests();
+
+ string16 search_text;
+ args->GetString("search_text", &search_text);
+
+ // Fetch history.
+ HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ history::QueryOptions options;
+ // The observer owns itself. It deletes itself after it fetches history.
+ AutomationProviderHistoryObserver* history_observer =
+ new AutomationProviderHistoryObserver(this, reply_message);
+ hs->QueryHistory(
+ search_text,
+ options,
+ &consumer_,
+ NewCallback(history_observer,
+ &AutomationProviderHistoryObserver::HistoryQueryComplete));
+}
+
+// Sample json input: { "command": "AddHistoryItem",
+// "item": { "URL": "http://www.google.com",
+// "title": "Google", # optional
+// "time": 12345 # optional (time_t)
+// } }
+// Refer chrome/test/pyautolib/pyauto.py for details on input.
+void TestingAutomationProvider::AddHistoryItem(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ DictionaryValue* item = NULL;
+ args->GetDictionary("item", &item);
+ string16 url_text;
+ string16 title;
+ base::Time time = base::Time::Now();
+ AutomationJSONReply reply(this, reply_message);
+
+ if (!item->GetString("url", &url_text)) {
+ reply.SendError("bad args (no URL in dict?)");
+ return;
+ }
+ GURL gurl(url_text);
+ item->GetString("title", &title); // Don't care if it fails.
+ int it;
+ double dt;
+ if (item->GetInteger("time", &it))
+ time = base::Time::FromTimeT(it);
+ else if (item->GetReal("time", &dt))
+ time = base::Time::FromDoubleT(dt);
+
+ // Ideas for "dummy" values (e.g. id_scope) came from
+ // chrome/browser/autocomplete/history_contents_provider_unittest.cc
+ HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ const void* id_scope = reinterpret_cast<void*>(1);
+ hs->AddPage(gurl, time,
+ id_scope,
+ 0,
+ GURL(),
+ PageTransition::LINK,
+ history::RedirectList(),
+ history::SOURCE_BROWSED,
+ false);
+ if (title.length())
+ hs->SetPageTitle(gurl, title);
+ reply.SendSuccess(NULL);
+}
+
+// Sample json input: { "command": "GetDownloadsInfo" }
+// Refer chrome/test/pyautolib/download_info.py for sample json output.
+void TestingAutomationProvider::GetDownloadsInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+
+ if (!profile_->HasCreatedDownloadManager()) {
+ reply.SendError("no download manager");
+ return;
+ }
+
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ std::vector<DownloadItem*> downloads;
+ profile_->GetDownloadManager()->GetAllDownloads(FilePath(), &downloads);
+
+ ListValue* list_of_downloads = new ListValue;
+ for (std::vector<DownloadItem*>::iterator it = downloads.begin();
+ it != downloads.end();
+ it++) { // Fill info about each download item.
+ list_of_downloads->Append(GetDictionaryFromDownloadItem(*it));
+ }
+ return_value->Set("downloads", list_of_downloads);
+ reply.SendSuccess(return_value.get());
+ // All value objects allocated above are owned by |return_value|
+ // and get freed by it.
+}
+
+void TestingAutomationProvider::WaitForDownloadsToComplete(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+
+ // Look for a quick return.
+ if (!profile_->HasCreatedDownloadManager()) {
+ reply.SendSuccess(NULL); // No download manager.
+ return;
+ }
+ std::vector<DownloadItem*> downloads;
+ profile_->GetDownloadManager()->GetCurrentDownloads(FilePath(), &downloads);
+ if (downloads.empty()) {
+ reply.SendSuccess(NULL);
+ return;
+ }
+
+ // The observer owns itself. When the last observed item pings, it
+ // deletes itself.
+ AutomationProviderDownloadItemObserver* item_observer =
+ new AutomationProviderDownloadItemObserver(
+ this, reply_message, downloads.size());
+ for (std::vector<DownloadItem*>::iterator i = downloads.begin();
+ i != downloads.end();
+ i++) {
+ (*i)->AddObserver(item_observer);
+ }
+}
+
+namespace {
+
+DownloadItem* GetDownloadItemFromId(int id, DownloadManager* download_manager) {
+ std::vector<DownloadItem*> downloads;
+ download_manager->GetAllDownloads(FilePath(), &downloads);
+ DownloadItem* selected_item = NULL;
+
+ for (std::vector<DownloadItem*>::iterator it = downloads.begin();
+ it != downloads.end();
+ it++) {
+ DownloadItem* curr_item = *it;
+ if (curr_item->id() == id) {
+ selected_item = curr_item;
+ break;
+ }
+ }
+ return selected_item;
+}
+
+} // namespace
+
+// See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
+// json input and output.
+void TestingAutomationProvider::PerformActionOnDownload(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ int id;
+ std::string action;
+
+ if (!profile_->HasCreatedDownloadManager()) {
+ AutomationJSONReply(this, reply_message).SendError("No download manager.");
+ return;
+ }
+ if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "Must include int id and string action.");
+ return;
+ }
+
+ DownloadManager* download_manager = profile_->GetDownloadManager();
+ DownloadItem* selected_item = GetDownloadItemFromId(id, download_manager);
+ if (!selected_item) {
+ AutomationJSONReply(this, reply_message).SendError(
+ StringPrintf("No download with an id of %d\n", id));
+ return;
+ }
+
+ if (action == "open") {
+ selected_item->AddObserver(
+ new AutomationProviderDownloadUpdatedObserver(
+ this, reply_message, true));
+ selected_item->OpenDownload();
+ } else if (action == "toggle_open_files_like_this") {
+ selected_item->OpenFilesBasedOnExtension(
+ !selected_item->ShouldOpenFileBasedOnExtension());
+ AutomationJSONReply(this, reply_message).SendSuccess(NULL);
+ } else if (action == "remove") {
+ download_manager->AddObserver(
+ new AutomationProviderDownloadModelChangedObserver(
+ this, reply_message, download_manager));
+ selected_item->Remove(false);
+ } else if (action == "decline_dangerous_download") {
+ // This is the same as removing the file with delete_file=true.
+ download_manager->AddObserver(
+ new AutomationProviderDownloadModelChangedObserver(
+ this, reply_message, download_manager));
+ selected_item->Remove(true);
+ } else if (action == "save_dangerous_download") {
+ selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
+ this, reply_message, false));
+ selected_item->DangerousDownloadValidated();
+ } else if (action == "toggle_pause") {
+ selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
+ this, reply_message, false));
+ // This will still return if download has already completed.
+ selected_item->TogglePause();
+ } else if (action == "cancel") {
+ selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
+ this, reply_message, false));
+ selected_item->Cancel(true);
+ } else {
+ AutomationJSONReply(this, reply_message).SendError(
+ StringPrintf("Invalid action '%s' given.", action.c_str()));
+ }
+}
+
+// Sample json input: { "command": "GetPrefsInfo" }
+// Refer chrome/test/pyautolib/prefs_info.py for sample json output.
+void TestingAutomationProvider::GetPrefsInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ const PrefService::PreferenceSet& prefs =
+ profile_->GetPrefs()->preference_set();
+ DictionaryValue* items = new DictionaryValue;
+ for (PrefService::PreferenceSet::const_iterator it = prefs.begin();
+ it != prefs.end(); ++it) {
+ items->Set((*it)->name(), (*it)->GetValue()->DeepCopy());
+ }
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ return_value->Set("prefs", items); // return_value owns items.
+ AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
+}
+
+// Sample json input: { "command": "SetPrefs", "path": path, "value": value }
+void TestingAutomationProvider::SetPrefs(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ std::string path;
+ Value* val;
+ AutomationJSONReply reply(this, reply_message);
+ if (args->GetString("path", &path) && args->Get("value", &val)) {
+ PrefService* pref_service = profile_->GetPrefs();
+ const PrefService::Preference* pref =
+ pref_service->FindPreference(path.c_str());
+ if (!pref) { // Not a registered pref.
+ reply.SendError("pref not registered.");
+ return;
+ } else if (pref->IsManaged()) { // Do not attempt to change a managed pref.
+ reply.SendError("pref is managed. cannot be changed.");
+ return;
+ } else { // Set the pref.
+ pref_service->Set(path.c_str(), *val);
+ }
+ } else {
+ reply.SendError("no pref path or value given.");
+ return;
+ }
+
+ reply.SendSuccess(NULL);
+}
+
+// Sample json input: { "command": "GetOmniboxInfo" }
+// Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
+void TestingAutomationProvider::GetOmniboxInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+
+ LocationBar* loc_bar = browser->window()->GetLocationBar();
+ AutocompleteEditView* edit_view = loc_bar->location_entry();
+ AutocompleteEditModel* model = edit_view->model();
+
+ // Fill up matches.
+ ListValue* matches = new ListValue;
+ const AutocompleteResult& result = model->result();
+ for (AutocompleteResult::const_iterator i = result.begin();
+ i != result.end(); ++i) {
+ const AutocompleteMatch& match = *i;
+ DictionaryValue* item = new DictionaryValue; // owned by return_value
+ item->SetString("type", AutocompleteMatch::TypeToString(match.type));
+ item->SetBoolean("starred", match.starred);
+ item->SetString("destination_url", match.destination_url.spec());
+ item->SetString("contents", WideToUTF16Hack(match.contents));
+ item->SetString("description", WideToUTF16Hack(match.description));
+ matches->Append(item);
+ }
+ return_value->Set("matches", matches);
+
+ // Fill up other properties.
+ DictionaryValue* properties = new DictionaryValue; // owned by return_value
+ properties->SetBoolean("has_focus", model->has_focus());
+ properties->SetBoolean("query_in_progress", model->query_in_progress());
+ properties->SetString("keyword", WideToUTF16Hack(model->keyword()));
+ properties->SetString("text", WideToUTF16Hack(edit_view->GetText()));
+ return_value->Set("properties", properties);
+
+ AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
+}
+
+// Sample json input: { "command": "SetOmniboxText",
+// "text": "goog" }
+void TestingAutomationProvider::SetOmniboxText(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ string16 text;
+ AutomationJSONReply reply(this, reply_message);
+ if (!args->GetString("text", &text)) {
+ reply.SendError("text missing");
+ return;
+ }
+ browser->FocusLocationBar();
+ LocationBar* loc_bar = browser->window()->GetLocationBar();
+ AutocompleteEditView* edit_view = loc_bar->location_entry();
+ edit_view->model()->OnSetFocus(false);
+ edit_view->SetUserText(UTF16ToWideHack(text));
+ reply.SendSuccess(NULL);
+}
+
+// Sample json input: { "command": "OmniboxMovePopupSelection",
+// "count": 1 }
+// Negative count implies up, positive implies down. Count values will be
+// capped by the size of the popup list.
+void TestingAutomationProvider::OmniboxMovePopupSelection(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ int count;
+ AutomationJSONReply reply(this, reply_message);
+ if (!args->GetInteger("count", &count)) {
+ reply.SendError("count missing");
+ return;
+ }
+ LocationBar* loc_bar = browser->window()->GetLocationBar();
+ AutocompleteEditModel* model = loc_bar->location_entry()->model();
+ model->OnUpOrDownKeyPressed(count);
+ reply.SendSuccess(NULL);
+}
+
+// Sample json input: { "command": "OmniboxAcceptInput" }
+void TestingAutomationProvider::OmniboxAcceptInput(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ NavigationController& controller =
+ browser->GetSelectedTabContents()->controller();
+ // Setup observer to wait until the selected item loads.
+ NotificationObserver* observer =
+ new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
+ notification_observer_list_.AddObserver(observer);
+
+ browser->window()->GetLocationBar()->AcceptInput();
+}
+
+// Sample json input: { "command": "GetInitialLoadTimes" }
+// Refer to InitialLoadObserver::GetTimingInformation() for sample output.
+void TestingAutomationProvider::GetInitialLoadTimes(
+ Browser*,
+ DictionaryValue*,
+ IPC::Message* reply_message) {
+ scoped_ptr<DictionaryValue> return_value(
+ initial_load_observer_->GetTimingInformation());
+
+ std::string json_return;
+ base::JSONWriter::Write(return_value.get(), false, &json_return);
+ AutomationMsg_SendJSONRequest::WriteReplyParams(
+ reply_message, json_return, true);
+ Send(reply_message);
+}
+
+// Sample json input: { "command": "GetPluginsInfo" }
+// Refer chrome/test/pyautolib/plugins_info.py for sample json output.
+void TestingAutomationProvider::GetPluginsInfo(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ std::vector<WebPluginInfo> plugins;
+ NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
+ ListValue* items = new ListValue;
+ for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
+ it != plugins.end();
+ ++it) {
+ DictionaryValue* item = new DictionaryValue;
+ item->SetString("name", it->name);
+ item->SetString("path", it->path.value());
+ item->SetString("version", it->version);
+ item->SetString("desc", it->desc);
+ item->SetBoolean("enabled", it->enabled);
+ // Add info about mime types.
+ ListValue* mime_types = new ListValue();
+ for (std::vector<WebPluginMimeType>::const_iterator type_it =
+ it->mime_types.begin();
+ type_it != it->mime_types.end();
+ ++type_it) {
+ DictionaryValue* mime_type = new DictionaryValue();
+ mime_type->SetString("mimeType", type_it->mime_type);
+ mime_type->SetString("description", type_it->description);
+
+ ListValue* file_extensions = new ListValue();
+ for (std::vector<std::string>::const_iterator ext_it =
+ type_it->file_extensions.begin();
+ ext_it != type_it->file_extensions.end();
+ ++ext_it) {
+ file_extensions->Append(new StringValue(*ext_it));
+ }
+ mime_type->Set("fileExtensions", file_extensions);
+
+ mime_types->Append(mime_type);
+ }
+ item->Set("mimeTypes", mime_types);
+ items->Append(item);
+ }
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ return_value->Set("plugins", items); // return_value owns items.
+
+ AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
+}
+
+// Sample json input:
+// { "command": "EnablePlugin",
+// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
+void TestingAutomationProvider::EnablePlugin(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ FilePath::StringType path;
+ AutomationJSONReply reply(this, reply_message);
+ if (!args->GetString("path", &path)) {
+ reply.SendError("path not specified.");
+ return;
+ } else if (!NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(path))) {
+ reply.SendError(StringPrintf("Could not enable plugin for path %s.",
+ path.c_str()));
+ return;
+ }
+ reply.SendSuccess(NULL);
+}
+
+// Sample json input:
+// { "command": "DisablePlugin",
+// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
+void TestingAutomationProvider::DisablePlugin(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ FilePath::StringType path;
+ AutomationJSONReply reply(this, reply_message);
+ if (!args->GetString("path", &path)) {
+ reply.SendError("path not specified.");
+ return;
+ } else if (!NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(path))) {
+ reply.SendError(StringPrintf("Could not disable plugin for path %s.",
+ path.c_str()));
+ return;
+ }
+ reply.SendSuccess(NULL);
+}
+
+// Sample json input:
+// { "command": "SaveTabContents",
+// "tab_index": 0,
+// "filename": <a full pathname> }
+// Sample json output:
+// {}
+void TestingAutomationProvider::SaveTabContents(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ int tab_index = 0;
+ FilePath::StringType filename;
+ FilePath::StringType parent_directory;
+ TabContents* tab_contents = NULL;
+
+ if (!args->GetInteger("tab_index", &tab_index) ||
+ !args->GetString("filename", &filename)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "tab_index or filename param missing");
+ return;
+ } else {
+ tab_contents = browser->GetTabContentsAt(tab_index);
+ if (!tab_contents) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "no tab at tab_index");
+ return;
+ }
+ }
+ // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
+ // used. Nevertheless, SavePackage requires it be valid. Sigh.
+ parent_directory = FilePath(filename).DirName().value();
+ if (!tab_contents->SavePage(FilePath(filename), FilePath(parent_directory),
+ SavePackage::SAVE_AS_ONLY_HTML)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "Could not initiate SavePage");
+ return;
+ }
+ // The observer will delete itself when done.
+ new SavePackageNotificationObserver(tab_contents->save_package(),
+ this, reply_message);
+}
+
+// Refer to ImportSettings() in chrome/test/pyautolib/pyauto.py for sample
+// json input.
+// Sample json output: "{}"
+void TestingAutomationProvider::ImportSettings(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ // Map from the json string passed over to the import item masks.
+ std::map<std::string, ImportItem> string_to_import_item;
+ string_to_import_item["HISTORY"] = importer::HISTORY;
+ string_to_import_item["FAVORITES"] = importer::FAVORITES;
+ string_to_import_item["COOKIES"] = importer::COOKIES;
+ string_to_import_item["PASSWORDS"] = importer::PASSWORDS;
+ string_to_import_item["SEARCH_ENGINES"] = importer::SEARCH_ENGINES;
+ string_to_import_item["HOME_PAGE"] = importer::HOME_PAGE;
+ string_to_import_item["ALL"] = importer::ALL;
+
+ string16 browser_name;
+ int import_items = 0;
+ ListValue* import_items_list = NULL;
+ bool first_run;
+
+ if (!args->GetString("import_from", &browser_name) ||
+ !args->GetBoolean("first_run", &first_run) ||
+ !args->GetList("import_items", &import_items_list)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "Incorrect type for one or more of the arguments.");
+ return;
+ }
+
+ int num_items = import_items_list->GetSize();
+ for (int i = 0; i < num_items; i++) {
+ std::string item;
+ import_items_list->GetString(i, &item);
+ // If the provided string is not part of the map, error out.
+ if (!ContainsKey(string_to_import_item, item)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "Invalid item string found in import_items.");
+ return;
+ }
+ import_items |= string_to_import_item[item];
+ }
+
+ ImporterHost* importer_host = new ImporterHost();
+ // Get the correct ProfileInfo based on the browser they user provided.
+ importer::ProfileInfo profile_info;
+ int num_browsers = importer_host->GetAvailableProfileCount();
+ int i = 0;
+ for ( ; i < num_browsers; i++) {
+ string16 name = WideToUTF16Hack(importer_host->GetSourceProfileNameAt(i));
+ if (name == browser_name) {
+ profile_info = importer_host->GetSourceProfileInfoAt(i);
+ break;
+ }
+ }
+ // If we made it to the end of the loop, then the input was bad.
+ if (i == num_browsers) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "Invalid browser name string found.");
+ return;
+ }
+
+ Profile* profile = browser->profile();
+
+ importer_host->SetObserver(
+ new AutomationProviderImportSettingsObserver(this, reply_message));
+ importer_host->StartImportSettings(profile_info, profile, import_items,
+ new ProfileWriter(profile), first_run);
+}
+
+namespace {
+
+// Translates a dictionary password to a PasswordForm struct.
+webkit_glue::PasswordForm GetPasswordFormFromDict(
+ const DictionaryValue& password_dict) {
+
+ // If the time is specified, change time to the specified time.
+ base::Time time = base::Time::Now();
+ int it;
+ double dt;
+ if (password_dict.GetInteger("time", &it))
+ time = base::Time::FromTimeT(it);
+ else if (password_dict.GetReal("time", &dt))
+ time = base::Time::FromDoubleT(dt);
+
+ std::string signon_realm;
+ string16 username_value;
+ string16 password_value;
+ string16 origin_url_text;
+ string16 username_element;
+ string16 password_element;
+ string16 submit_element;
+ string16 action_target_text;
+ bool blacklist = false;
+ string16 old_password_element;
+ string16 old_password_value;
+
+ // We don't care if any of these fail - they are either optional or checked
+ // before this function is called.
+ password_dict.GetString("signon_realm", &signon_realm);
+ password_dict.GetString("username_value", &username_value);
+ password_dict.GetString("password_value", &password_value);
+ password_dict.GetString("origin_url", &origin_url_text);
+ password_dict.GetString("username_element", &username_element);
+ password_dict.GetString("password_element", &password_element);
+ password_dict.GetString("submit_element", &submit_element);
+ password_dict.GetString("action_target", &action_target_text);
+ password_dict.GetBoolean("blacklist", &blacklist);
+
+ GURL origin_gurl(origin_url_text);
+ GURL action_target(action_target_text);
+
+ webkit_glue::PasswordForm password_form;
+ password_form.signon_realm = signon_realm;
+ password_form.username_value = username_value;
+ password_form.password_value = password_value;
+ password_form.origin = origin_gurl;
+ password_form.username_element = username_element;
+ password_form.password_element = password_element;
+ password_form.submit_element = submit_element;
+ password_form.action = action_target;
+ password_form.blacklisted_by_user = blacklist;
+ password_form.date_created = time;
+
+ return password_form;
+}
+
+} // namespace
+
+// See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
+// input.
+// Sample json output: { "password_added": true }
+void TestingAutomationProvider::AddSavedPassword(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ DictionaryValue* password_dict = NULL;
+
+ if (!args->GetDictionary("password", &password_dict)) {
+ reply.SendError("Password must be a dictionary.");
+ return;
+ }
+
+ // The signon realm is effectively the primary key and must be included.
+ // Check here before calling GetPasswordFormFromDict.
+ if (!password_dict->HasKey("signon_realm")) {
+ reply.SendError("Password must include signon_realm.");
+ return;
+ }
+ webkit_glue::PasswordForm new_password =
+ GetPasswordFormFromDict(*password_dict);
+
+ Profile* profile = browser->profile();
+ // Use IMPLICIT_ACCESS since new passwords aren't added off the record.
+ PasswordStore* password_store =
+ profile->GetPasswordStore(Profile::IMPLICIT_ACCESS);
+
+ // Set the return based on whether setting the password succeeded.
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+
+ // It will be null if it's accessed in an incognito window.
+ if (password_store != NULL) {
+ password_store->AddLogin(new_password);
+ return_value->SetBoolean("password_added", true);
+ } else {
+ return_value->SetBoolean("password_added", false);
+ }
+
+ reply.SendSuccess(return_value.get());
+}
+
+// See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
+// json input.
+// Sample json output: {}
+void TestingAutomationProvider::RemoveSavedPassword(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ DictionaryValue* password_dict = NULL;
+
+ if (!args->GetDictionary("password", &password_dict)) {
+ reply.SendError("Password must be a dictionary.");
+ return;
+ }
+
+ // The signon realm is effectively the primary key and must be included.
+ // Check here before calling GetPasswordFormFromDict.
+ if (!password_dict->HasKey("signon_realm")) {
+ reply.SendError("Password must include signon_realm.");
+ return;
+ }
+ webkit_glue::PasswordForm to_remove =
+ GetPasswordFormFromDict(*password_dict);
+
+ Profile* profile = browser->profile();
+ // Use EXPLICIT_ACCESS since passwords can be removed off the record.
+ PasswordStore* password_store =
+ profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+
+ password_store->RemoveLogin(to_remove);
+ reply.SendSuccess(NULL);
+}
+
+// Sample json input: { "command": "GetSavedPasswords" }
+// Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
+// json output.
+void TestingAutomationProvider::GetSavedPasswords(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ Profile* profile = browser->profile();
+ // Use EXPLICIT_ACCESS since saved passwords can be retreived off the record.
+ PasswordStore* password_store =
+ profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+ password_store->GetAutofillableLogins(
+ new AutomationProviderGetPasswordsObserver(this, reply_message));
+ // Observer deletes itself after returning.
+}
+
+// Refer to ClearBrowsingData() in chrome/test/pyautolib/pyauto.py for sample
+// json input.
+// Sample json output: {}
+void TestingAutomationProvider::ClearBrowsingData(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ std::map<std::string, BrowsingDataRemover::TimePeriod> string_to_time_period;
+ string_to_time_period["LAST_HOUR"] = BrowsingDataRemover::LAST_HOUR;
+ string_to_time_period["LAST_DAY"] = BrowsingDataRemover::LAST_DAY;
+ string_to_time_period["LAST_WEEK"] = BrowsingDataRemover::LAST_WEEK;
+ string_to_time_period["FOUR_WEEKS"] = BrowsingDataRemover::FOUR_WEEKS;
+ string_to_time_period["EVERYTHING"] = BrowsingDataRemover::EVERYTHING;
+
+ std::map<std::string, int> string_to_mask_value;
+ string_to_mask_value["HISTORY"] = BrowsingDataRemover::REMOVE_HISTORY;
+ string_to_mask_value["DOWNLOADS"] = BrowsingDataRemover::REMOVE_DOWNLOADS;
+ string_to_mask_value["COOKIES"] = BrowsingDataRemover::REMOVE_COOKIES;
+ string_to_mask_value["PASSWORDS"] = BrowsingDataRemover::REMOVE_PASSWORDS;
+ string_to_mask_value["FORM_DATA"] = BrowsingDataRemover::REMOVE_FORM_DATA;
+ string_to_mask_value["CACHE"] = BrowsingDataRemover::REMOVE_CACHE;
+
+ std::string time_period;
+ ListValue* to_remove;
+ if (!args->GetString("time_period", &time_period) ||
+ !args->GetList("to_remove", &to_remove)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "time_period must be a string and to_remove a list.");
+ return;
+ }
+
+ int remove_mask = 0;
+ int num_removals = to_remove->GetSize();
+ for (int i = 0; i < num_removals; i++) {
+ std::string removal;
+ to_remove->GetString(i, &removal);
+ // If the provided string is not part of the map, then error out.
+ if (!ContainsKey(string_to_mask_value, removal)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "Invalid browsing data string found in to_remove.");
+ return;
+ }
+ remove_mask |= string_to_mask_value[removal];
+ }
+
+ if (!ContainsKey(string_to_time_period, time_period)) {
+ AutomationJSONReply(this, reply_message).SendError(
+ "Invalid string for time_period.");
+ return;
+ }
+
+ BrowsingDataRemover* remover = new BrowsingDataRemover(
+ profile(), string_to_time_period[time_period], base::Time());
+
+ remover->AddObserver(
+ new AutomationProviderBrowsingDataObserver(this, reply_message));
+ remover->Remove(remove_mask);
+ // BrowsingDataRemover deletes itself using DeleteTask.
+ // 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("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 TestingAutomationProvider::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 TestingAutomationProvider::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("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;
+ } else if (option == "set_target_language") {
+ string16 target_language;
+ if (!args->GetString("target_language", &target_language)) {
+ AutomationJSONReply(this, reply_message).
+ SendError("Must include target_language string.");
+ return;
+ }
+ // Get the target language index based off of the language name.
+ int target_language_index = -1;
+ for (int i = 0; i < translate_bar->GetLanguageCount(); i++) {
+ if (translate_bar->GetLanguageDisplayableNameAt(i) == target_language) {
+ target_language_index = i;
+ break;
+ }
+ }
+ if (target_language_index == -1) {
+ AutomationJSONReply(this, reply_message)
+ .SendError("Invalid target language string.");
+ return;
+ }
+ // If the page has already been translated it will be translated again to
+ // the new language. The observer will wait until the page has been
+ // translated to reply.
+ if (translate_bar->type() == TranslateInfoBarDelegate::AFTER_TRANSLATE) {
+ new PageTranslatedObserver(this, reply_message, tab_contents);
+ translate_bar->SetTargetLanguage(target_language_index);
+ return;
+ }
+ // Otherwise just send the reply back immediately.
+ translate_bar->SetTargetLanguage(target_language_index);
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ return_value->SetBoolean("translation_success", true);
+ AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
+ return;
+ } else if (option == "click_always_translate_lang_button") {
+ if (!translate_bar->ShouldShowAlwaysTranslateButton()) {
+ AutomationJSONReply(this, reply_message)
+ .SendError("Always translate button not showing.");
+ return;
+ }
+ // Clicking 'Always Translate' triggers a translation. The observer will
+ // wait until the translation is complete before sending the reply.
+ new PageTranslatedObserver(this, reply_message, tab_contents);
+ translate_bar->AlwaysTranslatePageLanguage();
+ 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 if (option == "click_never_translate_lang_button") {
+ if (!translate_bar->ShouldShowNeverTranslateButton()) {
+ reply.SendError("Always translate button not showing.");
+ return;
+ }
+ translate_bar->NeverTranslatePageLanguage();
+ reply.SendSuccess(NULL);
+ } else if (option == "decline_translation") {
+ // This is the function called when an infobar is dismissed or when the
+ // user clicks the 'Nope' translate button.
+ translate_bar->TranslationDeclined();
+ tab_contents->RemoveInfoBar(translate_bar);
+ 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 TestingAutomationProvider::GetThemeInfo(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ Extension* theme = browser->profile()->GetTheme();
+ if (theme) {
+ return_value->SetString("name", theme->name());
+ return_value->Set("images", theme->GetThemeImages()->DeepCopy());
+ return_value->Set("colors", theme->GetThemeColors()->DeepCopy());
+ return_value->Set("tints", theme->GetThemeTints()->DeepCopy());
+ }
+ AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
+}
+
+// Sample json input: { "command": "GetExtensionsInfo" }
+// See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
+// output.
+void TestingAutomationProvider::GetExtensionsInfo(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ ExtensionsService* service = profile()->GetExtensionsService();
+ if (!service) {
+ reply.SendError("No extensions service.");
+ }
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+ ListValue* extensions_values = new ListValue;
+ const ExtensionList* extensions = service->extensions();
+ for (ExtensionList::const_iterator it = extensions->begin();
+ it != extensions->end(); ++it) {
+ const Extension* extension = *it;
+ DictionaryValue* extension_value = new DictionaryValue;
+ extension_value->SetString("id", extension->id());
+ extension_value->SetString("version", extension->VersionString());
+ extension_value->SetString("name", extension->name());
+ extension_value->SetString("public_key", extension->public_key());
+ extension_value->SetString("description", extension->description());
+ extension_value->SetString("background_url",
+ extension->background_url().spec());
+ extension_value->SetString("options_url",
+ extension->options_url().spec());
+ extensions_values->Append(extension_value);
+ }
+ return_value->Set("extensions", extensions_values);
+ reply.SendSuccess(return_value.get());
+}
+
+// See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
+// json input.
+// Sample json output: {}
+void TestingAutomationProvider::UninstallExtensionById(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ std::string id;
+ if (!args->GetString("id", &id)) {
+ reply.SendError("Must include string id.");
+ return;
+ }
+ ExtensionsService* service = profile()->GetExtensionsService();
+ if (!service) {
+ reply.SendError("No extensions service.");
+ return;
+ }
+ ExtensionUnloadNotificationObserver observer;
+ service->UninstallExtension(id, false);
+ reply.SendSuccess(NULL);
+}
+
+// Sample json input:
+// { "command": "GetAutoFillProfile" }
+// Refer to GetAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample
+// json output.
+void TestingAutomationProvider::GetAutoFillProfile(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ // Get the AutoFillProfiles currently in the database.
+ int tab_index = 0;
+ args->GetInteger("tab_index", &tab_index);
+ TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
+ AutomationJSONReply reply(this, reply_message);
+
+ if (tab_contents) {
+ PersonalDataManager* pdm = tab_contents->profile()->GetOriginalProfile()
+ ->GetPersonalDataManager();
+ if (pdm) {
+ std::vector<AutoFillProfile*> autofill_profiles = pdm->profiles();
+ std::vector<CreditCard*> credit_cards = pdm->credit_cards();
+
+ ListValue* profiles = GetListFromAutoFillProfiles(autofill_profiles);
+ ListValue* cards = GetListFromCreditCards(credit_cards);
+
+ scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
+
+ return_value->Set("profiles", profiles);
+ return_value->Set("credit_cards", cards);
+ reply.SendSuccess(return_value.get());
+ } else {
+ reply.SendError("No PersonalDataManager.");
+ return;
+ }
+ } else {
+ reply.SendError("No tab at that index.");
+ return;
+ }
+}
+
+// Refer to FillAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample
+// json input.
+// Sample json output: {}
+void TestingAutomationProvider::FillAutoFillProfile(
+ Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ ListValue* profiles = NULL;
+ ListValue* cards = NULL;
+ args->GetList("profiles", &profiles);
+ args->GetList("credit_cards", &cards);
+ std::string error_mesg;
+
+ std::vector<AutoFillProfile> autofill_profiles;
+ std::vector<CreditCard> credit_cards;
+ // Create an AutoFillProfile for each of the dictionary profiles.
+ if (profiles) {
+ autofill_profiles = GetAutoFillProfilesFromList(*profiles, &error_mesg);
+ }
+ // Create a CreditCard for each of the dictionary values.
+ if (cards) {
+ credit_cards = GetCreditCardsFromList(*cards, &error_mesg);
+ }
+ if (!error_mesg.empty()) {
+ reply.SendError(error_mesg);
+ return;
+ }
+
+ // Save the AutoFillProfiles.
+ int tab_index = 0;
+ args->GetInteger("tab_index", &tab_index);
+ TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
+
+ if (tab_contents) {
+ PersonalDataManager* pdm = tab_contents->profile()
+ ->GetPersonalDataManager();
+ if (pdm) {
+ pdm->OnAutoFillDialogApply(profiles? &autofill_profiles : NULL,
+ cards? &credit_cards : NULL);
+ } else {
+ reply.SendError("No PersonalDataManager.");
+ return;
+ }
+ } else {
+ reply.SendError("No tab at that index.");
+ return;
+ }
+ reply.SendSuccess(NULL);
+}
+
+/* static */
+ListValue* TestingAutomationProvider::GetListFromAutoFillProfiles(
+ std::vector<AutoFillProfile*> autofill_profiles) {
+ ListValue* profiles = new ListValue;
+
+ std::map<AutoFillFieldType, std::wstring> autofill_type_to_string
+ = GetAutoFillFieldToStringMap();
+
+ // For each AutoFillProfile, transform it to a dictionary object to return.
+ for (std::vector<AutoFillProfile*>::iterator it = autofill_profiles.begin();
+ it != autofill_profiles.end(); ++it) {
+ AutoFillProfile* profile = *it;
+ DictionaryValue* profile_info = new DictionaryValue;
+ profile_info->SetString("label", profile->Label());
+ // For each of the types, if it has a value, add it to the dictionary.
+ for (std::map<AutoFillFieldType, std::wstring>::iterator
+ type_it = autofill_type_to_string.begin();
+ type_it != autofill_type_to_string.end(); ++type_it) {
+ string16 value = profile->GetFieldText(AutoFillType(type_it->first));
+ if (value.length()) { // If there was something stored for that value.
+ profile_info->SetString(WideToUTF8(type_it->second), value);
+ }
+ }
+ profiles->Append(profile_info);
+ }
+ return profiles;
+}
+
+/* static */
+ListValue* TestingAutomationProvider::GetListFromCreditCards(
+ std::vector<CreditCard*> credit_cards) {
+ ListValue* cards = new ListValue;
+
+ std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
+ GetCreditCardFieldToStringMap();
+
+ // For each AutoFillProfile, transform it to a dictionary object to return.
+ for (std::vector<CreditCard*>::iterator it = credit_cards.begin();
+ it != credit_cards.end(); ++it) {
+ CreditCard* card = *it;
+ DictionaryValue* card_info = new DictionaryValue;
+ card_info->SetString("label", card->Label());
+ // For each of the types, if it has a value, add it to the dictionary.
+ for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
+ credit_card_type_to_string.begin();
+ type_it != credit_card_type_to_string.end(); ++type_it) {
+ string16 value = card->GetFieldText(AutoFillType(type_it->first));
+ // If there was something stored for that value.
+ if (value.length()) {
+ card_info->SetString(WideToUTF8(type_it->second), value);
+ }
+ }
+ cards->Append(card_info);
+ }
+ return cards;
+}
+
+/* static */
+std::vector<AutoFillProfile>
+TestingAutomationProvider::GetAutoFillProfilesFromList(
+ const ListValue& profiles, std::string* error_message) {
+ std::vector<AutoFillProfile> autofill_profiles;
+ DictionaryValue* profile_info = NULL;
+ string16 profile_label;
+ string16 current_value;
+
+ std::map<AutoFillFieldType, std::wstring> autofill_type_to_string =
+ GetAutoFillFieldToStringMap();
+
+ int num_profiles = profiles.GetSize();
+ for (int i = 0; i < num_profiles; i++) {
+ profiles.GetDictionary(i, &profile_info);
+ profile_info->GetString("label", &profile_label);
+ // Choose an id of 0 so that a unique id will be created.
+ AutoFillProfile profile(profile_label, 0);
+ // Loop through the possible profile types and add those provided.
+ for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
+ autofill_type_to_string.begin();
+ type_it != autofill_type_to_string.end(); ++type_it) {
+ if (profile_info->HasKey(WideToUTF8(type_it->second))) {
+ if (profile_info->GetString(WideToUTF8(type_it->second),
+ &current_value)) {
+ profile.SetInfo(AutoFillType(type_it->first), current_value);
+ } else {
+ *error_message= "All values must be strings";
+ break;
+ }
+ }
+ }
+ autofill_profiles.push_back(profile);
+ }
+ return autofill_profiles;
+}
+
+/* static */
+std::vector<CreditCard> TestingAutomationProvider::GetCreditCardsFromList(
+ const ListValue& cards, std::string* error_message) {
+ std::vector<CreditCard> credit_cards;
+ DictionaryValue* card_info = NULL;
+ string16 card_label;
+ string16 current_value;
+
+ std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
+ GetCreditCardFieldToStringMap();
+
+ int num_credit_cards = cards.GetSize();
+ for (int i = 0; i < num_credit_cards; i++) {
+ cards.GetDictionary(i, &card_info);
+ card_info->GetString("label", &card_label);
+ CreditCard card(card_label, 0);
+ // Loop through the possible credit card fields and add those provided.
+ for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
+ credit_card_type_to_string.begin();
+ type_it != credit_card_type_to_string.end(); ++type_it) {
+ if (card_info->HasKey(WideToUTF8(type_it->second))) {
+ if (card_info->GetString(WideToUTF8(type_it->second), &current_value)) {
+ card.SetInfo(AutoFillType(type_it->first), current_value);
+ } else {
+ *error_message= "All values must be strings";
+ break;
+ }
+ }
+ }
+ credit_cards.push_back(card);
+ }
+ return credit_cards;
+}
+
+/* static */
+std::map<AutoFillFieldType, std::wstring>
+ TestingAutomationProvider::GetAutoFillFieldToStringMap() {
+ std::map<AutoFillFieldType, std::wstring> autofill_type_to_string;
+ autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
+ autofill_type_to_string[NAME_MIDDLE] = L"NAME_MIDDLE";
+ autofill_type_to_string[NAME_LAST] = L"NAME_LAST";
+ autofill_type_to_string[COMPANY_NAME] = L"COMPANY_NAME";
+ autofill_type_to_string[EMAIL_ADDRESS] = L"EMAIL_ADDRESS";
+ autofill_type_to_string[ADDRESS_HOME_LINE1] = L"ADDRESS_HOME_LINE1";
+ autofill_type_to_string[ADDRESS_HOME_LINE2] = L"ADDRESS_HOME_LINE2";
+ autofill_type_to_string[ADDRESS_HOME_CITY] = L"ADDRESS_HOME_CITY";
+ autofill_type_to_string[ADDRESS_HOME_STATE] = L"ADDRESS_HOME_STATE";
+ autofill_type_to_string[ADDRESS_HOME_ZIP] = L"ADDRESS_HOME_ZIP";
+ autofill_type_to_string[ADDRESS_HOME_COUNTRY] = L"ADDRESS_HOME_COUNTRY";
+ autofill_type_to_string[PHONE_HOME_NUMBER] = L"PHONE_HOME_NUMBER";
+ autofill_type_to_string[PHONE_FAX_NUMBER] = L"PHONE_FAX_NUMBER";
+ autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
+ return autofill_type_to_string;
+}
+
+/* static */
+std::map<AutoFillFieldType, std::wstring>
+ TestingAutomationProvider::GetCreditCardFieldToStringMap() {
+ std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string;
+ credit_card_type_to_string[CREDIT_CARD_NAME] = L"CREDIT_CARD_NAME";
+ credit_card_type_to_string[CREDIT_CARD_NUMBER] = L"CREDIT_CARD_NUMBER";
+ credit_card_type_to_string[CREDIT_CARD_EXP_MONTH] = L"CREDIT_CARD_EXP_MONTH";
+ credit_card_type_to_string[CREDIT_CARD_EXP_4_DIGIT_YEAR] =
+ L"CREDIT_CARD_EXP_4_DIGIT_YEAR";
+ return credit_card_type_to_string;
+}
+
// TODO(brettw) change this to accept GURLs when history supports it
void TestingAutomationProvider::OnRedirectQueryComplete(
HistoryService::Handle request_handle,
diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h
index 11be6c9b..10fe387 100644
--- a/chrome/browser/automation/testing_automation_provider.h
+++ b/chrome/browser/automation/testing_automation_provider.h
@@ -346,6 +346,256 @@ class TestingAutomationProvider : public AutomationProvider,
// Returns the number of blocked popups in the tab |handle|.
void GetBlockedPopupCount(int handle, int* count);
+ // Generic pattern for pyautolib
+ // Uses the JSON interface for input/output.
+ void SendJSONRequest(int handle,
+ std::string json_request,
+ IPC::Message* reply_message);
+
+ // Method ptr for json handlers.
+ // Uses the JSON interface for input/output.
+ typedef void (TestingAutomationProvider::*JsonHandler)(
+ Browser* browser,
+ DictionaryValue*,
+ IPC::Message*);
+
+ // Set window dimensions.
+ // Uses the JSON interface for input/output.
+ void SetWindowDimensions(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about infobars in the given TabContents object.
+ // This includes info about the type of infobars, the message text,
+ // buttons, etc.
+ // Caller owns the returned object.
+ ListValue* GetInfobarsInfo(TabContents* tc);
+
+ // Perform actions on an infobar like dismiss, accept, cancel.
+ // Uses the JSON interface for input/output.
+ void PerformActionOnInfobar(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about the chromium/chrome in use.
+ // This includes things like version, executable name, executable path.
+ // Uses the JSON interface for input/output.
+ void GetBrowserInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about the state of navigation in a given tab.
+ // This includes ssl info.
+ // Uses the JSON interface for input/output.
+ void GetNavigationInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about downloads. This includes only ones that have been
+ // registered by the history system.
+ // Uses the JSON interface for input/output.
+ void GetDownloadsInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Wait for all downloads to complete.
+ // Uses the JSON interface for input/output.
+ void WaitForDownloadsToComplete(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Performs the given action on the specified download.
+ // Uses the JSON interface for input/output.
+ void PerformActionOnDownload(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about history.
+ // Uses the JSON interface for input/output.
+ void GetHistoryInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Add an item to the history service.
+ // Uses the JSON interface for input/output.
+ void AddHistoryItem(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about preferences.
+ // Uses the JSON interface for input/output.
+ void GetPrefsInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Set prefs.
+ // Uses the JSON interface for input/output.
+ void SetPrefs(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Return load times of initial tabs.
+ // Uses the JSON interface for input/output.
+ // Only includes tabs from command line arguments or session restore.
+ // See declaration of InitialLoadObserver in automation_provider_observers.h
+ // for example response.
+ void GetInitialLoadTimes(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about plugins.
+ // Uses the JSON interface for input/output.
+ void GetPluginsInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Enable a plugin.
+ // Uses the JSON interface for input/output.
+ void EnablePlugin(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Disable a plugin.
+ // Uses the JSON interface for input/output.
+ void DisablePlugin(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about omnibox.
+ // Contains data about the matches (url, content, description)
+ // in the omnibox popup, the text in the omnibox.
+ // Uses the JSON interface for input/output.
+ void GetOmniboxInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Set text in the omnibox. This sets focus to the omnibox.
+ // Uses the JSON interface for input/output.
+ void SetOmniboxText(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Move omnibox popup selection up or down.
+ // Uses the JSON interface for input/output.
+ void OmniboxMovePopupSelection(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Accept the current string of text in the omnibox.
+ // This is equivalent to clicking or hiting enter on a popup selection.
+ // Blocks until the page loads.
+ // Uses the JSON interface for input/output.
+ void OmniboxAcceptInput(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Save the contents of a tab into a file.
+ // Uses the JSON interface for input/output.
+ void SaveTabContents(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Import the given settings from the given browser.
+ // Uses the JSON interface for input/output.
+ void ImportSettings(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Add a new entry to the password store based on the password information
+ // provided. This method can also be used to add a blacklisted site (which
+ // will never fill in the password).
+ // Uses the JSON interface for input/output.
+ void AddSavedPassword(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Removes the password matching the information provided. This method can
+ // also be used to remove a blacklisted site.
+ // Uses the JSON interface for input/output.
+ void RemoveSavedPassword(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Return the saved username/password combinations.
+ // Uses the JSON interface for input/output.
+ void GetSavedPasswords(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Clear the specified browsing data. This call provides similar
+ // functionality to RemoveBrowsingData but is synchronous.
+ // Uses the JSON interface for input/output.
+ void ClearBrowsingData(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about theme.
+ // Uses the JSON interface for input/output.
+ void GetThemeInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Get info about all intalled extensions.
+ // Uses the JSON interface for input/output.
+ void GetExtensionsInfo(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Uninstalls the extension with the given id.
+ // Uses the JSON interface for input/output.
+ void UninstallExtensionById(Browser* browser,
+ 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,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Fill in an AutoFillProfile with the given profile information.
+ // Uses the JSON interface for input/output.
+ void FillAutoFillProfile(Browser* browser,
+ DictionaryValue* args,
+ IPC::Message* reply_message);
+
+ // Translate DictionaryValues of autofill profiles and credit cards to the
+ // data structure used in the browser.
+ // Args:
+ // profiles/cards: the ListValue of profiles/credit cards to translate.
+ // error_message: a pointer to the return string in case of error.
+ static std::vector<AutoFillProfile> GetAutoFillProfilesFromList(
+ const ListValue& profiles, std::string* error_message);
+ static std::vector<CreditCard> GetCreditCardsFromList(
+ const ListValue& cards, std::string* error_message);
+
+ // The opposite of the above: translates from the internal data structure
+ // for profiles and credit cards to a ListValue of DictionaryValues. The
+ // caller owns the returned object.
+ static ListValue* GetListFromAutoFillProfiles(
+ std::vector<AutoFillProfile*> autofill_profiles);
+ static ListValue* GetListFromCreditCards(
+ std::vector<CreditCard*> credit_cards);
+
+ // Return the map from the internal data representation to the string value
+ // of auto fill fields and credit card fields.
+ static std::map<AutoFillFieldType, std::wstring>
+ GetAutoFillFieldToStringMap();
+ static std::map<AutoFillFieldType, std::wstring>
+ GetCreditCardFieldToStringMap();
+
// Callback for history redirect queries.
virtual void OnRedirectQueryComplete(
HistoryService::Handle request_handle,