diff options
author | jrg@chromium.org <jrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-02 02:24:04 +0000 |
---|---|---|
committer | jrg@chromium.org <jrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-02 02:24:04 +0000 |
commit | 59a6112447827f01c4e40ef3072819f821989570 (patch) | |
tree | be9f7a44a64e899dd2c27fb35d5c17bacd77b088 /chrome/browser/automation | |
parent | 94953a56eb19ddef86c0264ef9cd0ac1f0f18332 (diff) | |
download | chromium_src-59a6112447827f01c4e40ef3072819f821989570.zip chromium_src-59a6112447827f01c4e40ef3072819f821989570.tar.gz chromium_src-59a6112447827f01c4e40ef3072819f821989570.tar.bz2 |
Add generic "json dict" entry point for pyauto commands. Will prevent
the need to modify the automation proxy anymore. New pyauto commands
will only need to edit pyauto.py (to add a new SendJSONCommand() call)
and browser_proxy.cc (to implement the other side). Contrast with the
normal editing of ~8 files.
Also added WaitForAllDownloadsToComplete using new JSON path.
BUG=http://crbug.com/39274
Review URL: http://codereview.chromium.org/1547012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43436 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/automation')
4 files changed, 178 insertions, 0 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index c6ee650..2b88a29 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/file_version_info.h" #include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/keyboard_codes.h" #include "base/message_loop.h" #include "base/path_service.h" @@ -430,6 +431,8 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) { SetBookmarkURL) IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBookmark, RemoveBookmark) + IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest, + SendJSONRequest) IPC_MESSAGE_HANDLER(AutomationMsg_GetInfoBarCount, GetInfoBarCount) IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_ClickInfoBarAccept, ClickInfoBarAccept) @@ -1500,6 +1503,112 @@ void AutomationProvider::RemoveBookmark(int handle, *success = false; } +void AutomationProvider::WaitForDownloadsToComplete( + DictionaryValue* args, + IPC::Message* reply_message) { + std::string json_return; + bool reply_return = true; + AutomationProviderDownloadManagerObserver observer; + std::vector<DownloadItem*> downloads; + + // Look for a quick return. + if (!profile_->HasCreatedDownloadManager()) { + json_return = "{'error': 'no download manager'}"; + reply_return = false; + } else { + profile_->GetDownloadManager()->GetCurrentDownloads(&observer, + FilePath()); + downloads = observer.Downloads(); + if (downloads.size() == 0) { + json_return = "{}"; + } + } + if (!json_return.empty()) { + AutomationMsg_SendJSONRequest::WriteReplyParams( + reply_message, json_return, reply_return); + Send(reply_message); + } + + // 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); + } +} + +void AutomationProvider::SendJSONRequest( + int handle, + std::string json_request, + IPC::Message* reply_message) { + Browser* browser = NULL; + std::string error_string; + scoped_ptr<Value> values; + + // Basic error checking. + if (browser_tracker_->ContainsHandle(handle)) { + browser = browser_tracker_->GetResource(handle); + } + if (!browser) { + error_string = "no browser object"; + } else { + base::JSONReader reader; + std::string error; + values.reset(reader.ReadAndReturnError(json_request, true, &error)); + if (!error.empty()) { + error_string = error; + } + } + + // Make sure input is a dict with a string command. + std::string command; + DictionaryValue* dict_value = NULL; + if (error_string.empty()) { + if (values->GetType() != Value::TYPE_DICTIONARY) { + error_string = "not a dict or no command key in dict"; + } else { + // Ownership remains with "values" variable. + dict_value = static_cast<DictionaryValue*>(values.get()); + if (!dict_value->GetStringASCII(std::string("command"), &command)) { + error_string = "no command key in dict or not a string command"; + } + } + } + + if (error_string.empty()) { + // TODO(jrg): table of calls; async gets passed reply_message, + // sync methods gets passed an output json dict which we package + // up and send. Right now we only have one. + if (command == "WaitForAllDownloadsToComplete") { + this->WaitForDownloadsToComplete(dict_value, reply_message); + return; + } else { + error_string = "unknown command"; + } + } + + // If we hit an error, return info. + // Return a dict of {'error', 'descriptive_string_for_error'}. + // Else return an empty dict. + std::string json_string; + bool success = true; + if (!error_string.empty()) { + scoped_ptr<DictionaryValue> dict(new DictionaryValue); + dict->SetString(L"error", error_string); + base::JSONWriter::Write(dict.get(), false, &json_string); + success = false; + } else { + json_string = "{}"; + } + AutomationMsg_SendJSONRequest::WriteReplyParams( + reply_message, json_string, success); + Send(reply_message); +} + void AutomationProvider::HandleInspectElementRequest( int handle, int x, int y, IPC::Message* reply_message) { TabContents* tab_contents = GetTabContentsForHandle(handle, NULL); diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index 2d680b1..929bc20 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -17,6 +17,7 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" +#include "base/values.h" #include "chrome/browser/automation/automation_autocomplete_edit_tracker.h" #include "chrome/browser/automation/automation_browser_tracker.h" #include "chrome/browser/automation/automation_resource_message_filter.h" @@ -319,6 +320,16 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, int64 id, bool* success); + // Wait for all downloads to complete. + void WaitForDownloadsToComplete( + DictionaryValue* args, + IPC::Message* reply_message); + + // Generic pattern for pyautolib + void SendJSONRequest(int handle, + std::string json_request, + IPC::Message* reply_message); + // Responds to InspectElement request void HandleInspectElementRequest(int handle, int x, diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc index 7e5ac24..da7537d 100644 --- a/chrome/browser/automation/automation_provider_observers.cc +++ b/chrome/browser/automation/automation_provider_observers.cc @@ -767,3 +767,14 @@ void AutomationProviderBookmarkModelObserver::ReplyAndDelete(bool success) { automation_provider_->Send(reply_message_); delete this; } + +void AutomationProviderDownloadItemObserver::OnDownloadFileCompleted( + DownloadItem* download) { + download->RemoveObserver(this); + if (--downloads_ == 0) { + AutomationMsg_SendJSONRequest::WriteReplyParams( + reply_message_, std::string("{}"), true); + provider_->Send(reply_message_); + delete this; + } +} diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index 0d75e70..892be51 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -9,6 +9,7 @@ #include <set> #include "chrome/browser/bookmarks/bookmark_model_observer.h" +#include "chrome/browser/download/download_manager.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_type.h" @@ -452,4 +453,50 @@ class AutomationProviderBookmarkModelObserver : BookmarkModelObserver { DISALLOW_COPY_AND_ASSIGN(AutomationProviderBookmarkModelObserver); }; +// When asked for pending downloads, the DownloadManager places +// results in a DownloadManager::Observer. +class AutomationProviderDownloadManagerObserver : + public DownloadManager::Observer { + public: + AutomationProviderDownloadManagerObserver() : DownloadManager::Observer() {} + virtual ~AutomationProviderDownloadManagerObserver() {} + virtual void ModelChanged() {} + virtual void SetDownloads(std::vector<DownloadItem*>& downloads) { + downloads_ = downloads; + } + std::vector<DownloadItem*> Downloads() { + return downloads_; + } + private: + std::vector<DownloadItem*> downloads_; + + DISALLOW_COPY_AND_ASSIGN(AutomationProviderDownloadManagerObserver); +}; + + +// Allows the automation provider to wait for all downloads to finish. +class AutomationProviderDownloadItemObserver : public DownloadItem::Observer { + public: + AutomationProviderDownloadItemObserver( + AutomationProvider* provider, + IPC::Message* reply_message, + int downloads) { + provider_ = provider; + reply_message_ = reply_message; + downloads_ = downloads; + } + virtual ~AutomationProviderDownloadItemObserver() {} + + virtual void OnDownloadUpdated(DownloadItem* download) { } + virtual void OnDownloadFileCompleted(DownloadItem* download); + virtual void OnDownloadOpened(DownloadItem* download) { } + + private: + AutomationProvider* provider_; + IPC::Message* reply_message_; + int downloads_; + + DISALLOW_COPY_AND_ASSIGN(AutomationProviderDownloadItemObserver); +}; + #endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_OBSERVERS_H_ |