diff options
author | jrg@chromium.org <jrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-24 00:52:49 +0000 |
---|---|---|
committer | jrg@chromium.org <jrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-24 00:52:49 +0000 |
commit | 7060bb292ea9e20cb0f45dadd1a2b06ef61bcc2f (patch) | |
tree | 4919709ddb82f03e87f7627f1a3b03ed1ce21af0 /chrome/browser/automation | |
parent | 26199ae574cad50fa5ac8ab222daa60843d8308f (diff) | |
download | chromium_src-7060bb292ea9e20cb0f45dadd1a2b06ef61bcc2f.zip chromium_src-7060bb292ea9e20cb0f45dadd1a2b06ef61bcc2f.tar.gz chromium_src-7060bb292ea9e20cb0f45dadd1a2b06ef61bcc2f.tar.bz2 |
Enable "get html from page" functionality for PyAuto.
BUG=36184
TEST=Run PyAuto's content.py and make sure it passes.
Review URL: http://codereview.chromium.org/2861019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50678 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/automation')
4 files changed, 127 insertions, 10 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 1630f14a..6692f09 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -9,6 +9,7 @@ #include "app/l10n_util.h" #include "app/message_box_flags.h" #include "base/callback.h" +#include "base/file_path.h" #include "base/file_version_info.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" @@ -1608,6 +1609,19 @@ void AutomationProvider::SetWindowDimensions(Browser* browser, Send(reply_message); } +std::string AutomationProvider::JSONErrorString(std::string err) { + std::string prefix = "{\"error\": \""; + std::string no_quote_err = err; + std::string suffix = "\"}"; + + // Don't allow input string to break JSON by embedding quotes. + // Try and make sure the input string won't break json quoting rules. + if (no_quote_err.find("\"") != std::string::npos) + no_quote_err = "unhappy about embedded quote in error string"; + + return prefix + no_quote_err + suffix; +} + // Sample json input: { "command": "GetBrowserInfo" } // Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for // sample json output. @@ -1796,7 +1810,7 @@ void AutomationProvider::AddHistoryItem(Browser* browser, if (title.length()) hs->SetPageTitle(gurl, title); } else { - json_return = "{\"error\": \"bad args (no URL in dict?).\"}"; + json_return = JSONErrorString("bad args (no URL in dict?)"); reply_return = false; } @@ -1817,7 +1831,7 @@ void AutomationProvider::GetDownloadsInfo(Browser* browser, scoped_ptr<DictionaryValue> return_value(new DictionaryValue); if (!profile_->HasCreatedDownloadManager()) { - json_return = "{\"error\": \"no download manager\"}"; + json_return = JSONErrorString("no download manager"); reply_return = false; } else { // Use DownloadManager's GetDownloads() method and not GetCurrentDownloads() @@ -1883,7 +1897,7 @@ void AutomationProvider::WaitForDownloadsToComplete( // Look for a quick return. if (!profile_->HasCreatedDownloadManager()) { - json_return = "{\"error\": \"no download manager\"}"; + json_return = JSONErrorString("no download manager"); reply_return = false; } else { profile_->GetDownloadManager()->GetCurrentDownloads(&observer, @@ -1948,16 +1962,16 @@ void AutomationProvider::SetPrefs(Browser* browser, const PrefService::Preference* pref = pref_service->FindPreference(path.c_str()); if (!pref) { // Not a registered pref. - json_return = "{\"error\": \"pref not registered.\"}"; + json_return = JSONErrorString("pref not registered."); reply_return = false; } else if (pref->IsManaged()) { // Do not attempt to change a managed pref. - json_return = "{\"error\": \"pref is managed. cannot be changed.\"}"; + json_return = JSONErrorString("pref is managed. cannot be changed."); reply_return = false; } else { // Set the pref. pref_service->Set(path.c_str(), *val); } } else { - json_return = "{\"error\": \"no pref path or value given.\"}"; + json_return = JSONErrorString("no pref path or value given."); reply_return = false; } @@ -2019,7 +2033,7 @@ void AutomationProvider::SetOmniboxText(Browser* browser, std::wstring text; if (!args->GetString(L"text", &text)) { - json_return = "{\"error\": \"text missing\"}"; + json_return = JSONErrorString("text missing"); reply_return = false; } else { browser->FocusLocationBar(); @@ -2047,7 +2061,7 @@ void AutomationProvider::OmniboxMovePopupSelection( int count; if (!args->GetInteger(L"count", &count)) { - json_return = "{\"error\": \"count missing\"}"; + json_return = JSONErrorString("count missing"); reply_return = false; } else { LocationBar* loc_bar = browser->window()->GetLocationBar(); @@ -2153,7 +2167,7 @@ void AutomationProvider::EnablePlugin(Browser* browser, bool reply_return = true; FilePath::StringType path; if (!args->GetString(L"path", &path)) { - json_return = "{\"error\": \"path not specified.\"}"; + json_return = JSONErrorString("path not specified."); reply_return = false; } else if (!NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(path))) { json_return = StringPrintf("{\"error\": \"Could not enable plugin" @@ -2176,7 +2190,7 @@ void AutomationProvider::DisablePlugin(Browser* browser, bool reply_return = true; FilePath::StringType path; if (!args->GetString(L"path", &path)) { - json_return = "{\"error\": \"path not specified.\"}"; + json_return = JSONErrorString("path not specified."); reply_return = false; } else if (!NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(path))) { json_return = StringPrintf("{\"error\": \"Could not enable plugin" @@ -2189,6 +2203,52 @@ void AutomationProvider::DisablePlugin(Browser* browser, Send(reply_message); } +// 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) { + std::string json_return; + int tab_index = 0; + FilePath::StringType filename; + FilePath::StringType parent_directory; + TabContents* tab_contents = NULL; + + if (!args->GetInteger(L"tab_index", &tab_index) || + !args->GetString(L"filename", &filename)) { + json_return = JSONErrorString("tab_index or filename param missing"); + } else { + tab_contents = browser->GetTabContentsAt(tab_index); + if (!tab_contents) { + json_return = JSONErrorString("no tab at tab_index"); + } + } + if (tab_contents) { + // 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)) { + json_return = JSONErrorString("Could not initiate SavePage"); + } else { + // The observer will delete itself when done. + new SavePackageNotificationObserver(tab_contents->save_package(), + this, reply_message); + return; + } + } + + // if we get here, error. + DCHECK(!json_return.empty()); + AutomationMsg_SendJSONRequest::WriteReplyParams( + reply_message, json_return, false); + Send(reply_message); +} + void AutomationProvider::SendJSONRequest(int handle, std::string json_request, IPC::Message* reply_message) { @@ -2254,6 +2314,8 @@ void AutomationProvider::SendJSONRequest(int handle, handler_map["GetInitialLoadTimes"] = &AutomationProvider::GetInitialLoadTimes; + handler_map["SaveTabContents"] = &AutomationProvider::SaveTabContents; + if (error_string.empty()) { if (handler_map.find(std::string(command)) != handler_map.end()) { (this->*handler_map[command])(browser, dict_value, reply_message); diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index b644dd4..da32336 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -327,6 +327,10 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, int64 id, bool* success); + // Util for creating a JSON error return string (dict with key + // 'error' and error string value). No need to quote input. + std::string JSONErrorString(std::string err); + // Set window dimensions. // Uses the JSON interface for input/output. void SetWindowDimensions(Browser* browser, @@ -432,6 +436,12 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, 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); + // Generic pattern for pyautolib // Uses the JSON interface for input/output. void SendJSONRequest(int handle, diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc index a59e8d1..0b7f0af 100644 --- a/chrome/browser/automation/automation_provider_observers.cc +++ b/chrome/browser/automation/automation_provider_observers.cc @@ -11,6 +11,7 @@ #include "chrome/browser/automation/automation_provider.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/dom_operation_notification_details.h" +#include "chrome/browser/download/save_package.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_updater.h" @@ -1043,3 +1044,26 @@ void OmniboxAcceptNotificationObserver::Observe( } } +SavePackageNotificationObserver::SavePackageNotificationObserver( + SavePackage* save_package, + AutomationProvider* automation, + IPC::Message* reply_message) : automation_(automation), + reply_message_(reply_message) { + Source<SavePackage> source(save_package); + registrar_.Add(this, NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED, + source); +} + +void SavePackageNotificationObserver::Observe( + NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED) { + AutomationMsg_SendJSONRequest::WriteReplyParams( + reply_message_, std::string("{}"), true); + automation_->Send(reply_message_); + delete this; + } else { + NOTREACHED(); + } +} diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index 6bf6a26..fbe8c15 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -21,6 +21,7 @@ class Browser; class Extension; class ExtensionProcessManager; class NavigationController; +class SavePackage; class TabContents; namespace IPC { @@ -632,4 +633,24 @@ class OmniboxAcceptNotificationObserver : public NotificationObserver { DISALLOW_COPY_AND_ASSIGN(OmniboxAcceptNotificationObserver); }; +// Allows the automation provider to wait for a save package notification. +class SavePackageNotificationObserver : public NotificationObserver { + public: + SavePackageNotificationObserver(SavePackage* save_package, + AutomationProvider* automation, + IPC::Message* reply_message); + virtual ~SavePackageNotificationObserver() {} + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + NotificationRegistrar registrar_; + AutomationProvider* automation_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(SavePackageNotificationObserver); +}; + #endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_OBSERVERS_H_ |