diff options
author | nirnimesh@chromium.org <nirnimesh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-15 18:06:39 +0000 |
---|---|---|
committer | nirnimesh@chromium.org <nirnimesh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-15 18:06:39 +0000 |
commit | d4adc298c7b9a2883dcefeccd67dbb102afe7b2b (patch) | |
tree | d16433931684e1a5c3c90c05423be20fc31e521b | |
parent | 31e2c69eb9a9cf4e59f08b483f7cd849631e7da4 (diff) | |
download | chromium_src-d4adc298c7b9a2883dcefeccd67dbb102afe7b2b.zip chromium_src-d4adc298c7b9a2883dcefeccd67dbb102afe7b2b.tar.gz chromium_src-d4adc298c7b9a2883dcefeccd67dbb102afe7b2b.tar.bz2 |
Add automation hooks to get info about downloads.
Makes info about downloads available to pyauto.
Also add JSONInterfaceError to represent an error in the json ipc interace.
TEST=None
BUG=None
Review URL: http://codereview.chromium.org/1637008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44664 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 71 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider.h | 6 | ||||
-rw-r--r-- | chrome/test/pyautolib/download_info.py | 81 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyauto.py | 14 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyauto_errors.py | 11 |
5 files changed, 181 insertions, 2 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index ad4dc9c..023b337 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -1571,6 +1571,71 @@ void AutomationProvider::RemoveBookmark(int handle, *success = false; } +void AutomationProvider::GetDownloadsInfo( + DictionaryValue* args, + IPC::Message* reply_message) { + std::string json_return; + bool reply_return = true; + AutomationProviderDownloadManagerObserver observer; + std::vector<DownloadItem*> downloads; + scoped_ptr<DictionaryValue> return_value(new DictionaryValue); + + if (!profile_->HasCreatedDownloadManager()) { + json_return = "{'error': 'no download manager'}"; + reply_return = false; + } else { + // Use DownloadManager's GetDownloads() method and not GetCurrentDownloads() + // since that would be transient; a download might enter and empty out + // the current download queue too soon to be noticed. + profile_->GetDownloadManager()->GetDownloads(&observer, L""); + downloads = observer.Downloads(); + } + + 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"); + + ListValue* list_of_downloads = new ListValue; + for (std::vector<DownloadItem*>::iterator it = downloads.begin(); + it != downloads.end(); + it++) { // Fill info about each download item. + DictionaryValue* dl_item_value = new DictionaryValue; + dl_item_value->SetInteger(L"id", static_cast<int>((*it)->id())); + dl_item_value->SetString(L"url", (*it)->url().spec()); + dl_item_value->SetString(L"referrer_url", (*it)->referrer_url().spec()); + dl_item_value->SetString(L"file_name", (*it)->file_name().value()); + dl_item_value->SetString(L"full_path", (*it)->full_path().value()); + dl_item_value->SetBoolean(L"is_paused", (*it)->is_paused()); + dl_item_value->SetBoolean(L"open_when_complete", + (*it)->open_when_complete()); + dl_item_value->SetBoolean(L"is_extension_install", + (*it)->is_extension_install()); + dl_item_value->SetBoolean(L"is_temporary", (*it)->is_temporary()); + dl_item_value->SetBoolean(L"is_otr", (*it)->is_otr()); // off-the-record + dl_item_value->SetString(L"state", state_to_string[(*it)->state()]); + dl_item_value->SetString(L"safety_state", + safety_state_to_string[(*it)->safety_state()]); + dl_item_value->SetInteger(L"PercentComplete", (*it)->PercentComplete()); + list_of_downloads->Append(dl_item_value); + } + return_value->Set(L"downloads", list_of_downloads); + base::JSONWriter::Write(return_value.get(), false, &json_return); + + AutomationMsg_SendJSONRequest::WriteReplyParams( + reply_message, json_return, reply_return); + Send(reply_message); + // All value objects allocated above are owned by |return_value| + // and get freed by it. +} + void AutomationProvider::WaitForDownloadsToComplete( DictionaryValue* args, IPC::Message* reply_message) { @@ -1651,7 +1716,11 @@ void AutomationProvider::SendJSONRequest( // 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") { + // TODO(nirnimesh): Replace if else cases with map. + if (command == "GetDownloadsInfo") { + this->GetDownloadsInfo(dict_value, reply_message); + return; + } else if (command == "WaitForAllDownloadsToComplete") { this->WaitForDownloadsToComplete(dict_value, reply_message); return; } else { diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index f3d03cb6..0c30ced 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -328,7 +328,13 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, int64 id, bool* success); + // 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(DictionaryValue* args, IPC::Message* reply_message); + // Wait for all downloads to complete. + // Uses the JSON interface for input/output. void WaitForDownloadsToComplete( DictionaryValue* args, IPC::Message* reply_message); diff --git a/chrome/test/pyautolib/download_info.py b/chrome/test/pyautolib/download_info.py new file mode 100644 index 0000000..e01fdac --- /dev/null +++ b/chrome/test/pyautolib/download_info.py @@ -0,0 +1,81 @@ +#!/usr/bin/python + +# Copyright (c) 2010 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""DownloadInfo: python representation for downloads visible to Chrome. + +Obtain one of these from PyUITestSuite::GetDownloadsInfo() call. + +class MyDownloadsTest(pyauto.PyUITest): + def testDownload(self): + self.NavigateToURL('http://my.url/package.zip') + self.WaitForDownloadsToComplete() + info = self.GetDownloadsInfo() + print info.Downloads() + self.assertEqual(info.Downloads()[0]['file_name'], 'packge.zip') + +See more tests in chrome/test/functional/downloads.py. +""" + +import os +import simplejson as json +import sys + +from pyauto_errors import JSONInterfaceError + + +class DownloadInfo(object): + """Represent info about Downloads. + + The info is represented as a list of DownloadItems. Each DownloadItem is a + dictionary with various attributes about a download, like id, file_name, + path, state, and so on. + """ + def __init__(self, json_string): + """Initialize a DownloadInfo from a string of json. + + Args: + json_string: a string of JSON, as returned by a json ipc call for the + command 'GetDownloadsInfo' + A typical json string representing one download looks like: + {'downloads': [{'url': 'http://blah/a_file.zip', + 'file_name': 'a_file.zip', + 'state': 'COMPLETED', + ..., + ..., } ] } + + Raises: + pyauto_errors.JSONInterfaceError if the automation call returns an error. + """ + # JSON string prepared in GetDownloadsInfo() in automation_provider.cc + self.downloadsdict = json.loads(json_string) + if self.downloadsdict.has_key('error'): + raise JSONInterfaceError(self.downloadsdict['error']) + + def Downloads(self): + """Info about all downloads. + + This includes downloads in all states (COMPLETE, IN_PROGRESS, ...). + + Returns: + [downloaditem1, downloaditem2, ...] + """ + return self.downloadsdict.get('downloads', []) + + def DownloadsInProgress(self): + """Info about all downloads in progress. + + Returns: + [downloaditem1, downloaditem2, ...] + """ + return [x for x in self.Downloads() if x['state'] == 'IN_PROGRESS'] + + def DownloadsComplete(self): + """Info about all downloads that have completed. + + Returns: + [downloaditem1, downloaditem2, ...] + """ + return [x for x in self.Downloads() if x['state'] == 'COMPLETE'] diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py index fe5f9ab..41e7889 100644 --- a/chrome/test/pyautolib/pyauto.py +++ b/chrome/test/pyautolib/pyauto.py @@ -69,8 +69,9 @@ except ImportError: raise # Should go after sys.path is set appropriately -import simplejson as json # found in third_party import bookmark_model +import download_info +import simplejson as json # found in third_party class PyUITest(pyautolib.PyUITestBase, unittest.TestCase): @@ -144,6 +145,17 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase): """ return bookmark_model.BookmarkModel(self._GetBookmarksAsJSON()) + def GetDownloadsInfo(self): + """Return info about downloads. + + This includes all the downloads recognized by the history system. + + Returns: + an instance of downloads_info.DownloadInfo + """ + return download_info.DownloadInfo( + self._SendJSONRequest(0, json.dumps({'command': 'GetDownloadsInfo'}))) + def WaitForAllDownloadsToComplete(self): """Wait for all downloads to complete.""" # Implementation detail: uses the generic "JSON command" model diff --git a/chrome/test/pyautolib/pyauto_errors.py b/chrome/test/pyautolib/pyauto_errors.py new file mode 100644 index 0000000..901874d --- /dev/null +++ b/chrome/test/pyautolib/pyauto_errors.py @@ -0,0 +1,11 @@ +#!/usr/bin/python + +# Copyright (c) 2010 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""PyAuto Errors.""" + +class JSONInterfaceError(RuntimeError): + """Represent an error in the JSON ipc interface.""" + pass |