summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornirnimesh@chromium.org <nirnimesh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-15 18:06:39 +0000
committernirnimesh@chromium.org <nirnimesh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-15 18:06:39 +0000
commitd4adc298c7b9a2883dcefeccd67dbb102afe7b2b (patch)
treed16433931684e1a5c3c90c05423be20fc31e521b
parent31e2c69eb9a9cf4e59f08b483f7cd849631e7da4 (diff)
downloadchromium_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.cc71
-rw-r--r--chrome/browser/automation/automation_provider.h6
-rw-r--r--chrome/test/pyautolib/download_info.py81
-rw-r--r--chrome/test/pyautolib/pyauto.py14
-rw-r--r--chrome/test/pyautolib/pyauto_errors.py11
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