diff options
author | chrisgao@chromium.org <chrisgao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-01 16:28:33 +0000 |
---|---|---|
committer | chrisgao@chromium.org <chrisgao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-01 16:28:33 +0000 |
commit | 0b4468ed16cf93bac23d5abf3ef39e400665d694 (patch) | |
tree | f6b9c65b60fb7c3b5b54c4141bb6554128e52513 | |
parent | a1129f2eb6d0cb85284c427b09a4cb6fd5e4312e (diff) | |
download | chromium_src-0b4468ed16cf93bac23d5abf3ef39e400665d694.zip chromium_src-0b4468ed16cf93bac23d5abf3ef39e400665d694.tar.gz chromium_src-0b4468ed16cf93bac23d5abf3ef39e400665d694.tar.bz2 |
[chromedriver] Implement file upload in SendKeys command.
BUG=chromedriver:276, chromedriver:154
Review URL: https://chromiumcodereview.appspot.com/13127002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191615 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/test/chromedriver/chrome/chrome.h | 2 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/chrome_impl.cc | 4 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/chrome_impl.h | 1 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/stub_chrome.cc | 4 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/stub_chrome.h | 1 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/stub_web_view.cc | 6 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/stub_web_view.h | 3 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/web_view.h | 7 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/web_view_impl.cc | 23 | ||||
-rw-r--r-- | chrome/test/chromedriver/chrome/web_view_impl.h | 3 | ||||
-rw-r--r-- | chrome/test/chromedriver/element_commands.cc | 44 |
11 files changed, 96 insertions, 2 deletions
diff --git a/chrome/test/chromedriver/chrome/chrome.h b/chrome/test/chromedriver/chrome/chrome.h index 1e64cdf..854027a 100644 --- a/chrome/test/chromedriver/chrome/chrome.h +++ b/chrome/test/chromedriver/chrome/chrome.h @@ -17,6 +17,8 @@ class Chrome { virtual std::string GetVersion() = 0; + virtual int GetBuildNo() = 0; + // Return ids of opened WebViews in the same order as they are opened. virtual Status GetWebViewIds(std::list<std::string>* web_view_ids) = 0; diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc index c5d266c..f7b0d7e 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_impl.cc @@ -211,6 +211,10 @@ std::string ChromeImpl::GetVersion() { return version_; } +int ChromeImpl::GetBuildNo() { + return build_no_; +} + Status ChromeImpl::GetWebViewIds(std::list<std::string>* web_view_ids) { WebViewInfoList info_list; Status status = FetchWebViewsInfo( diff --git a/chrome/test/chromedriver/chrome/chrome_impl.h b/chrome/test/chromedriver/chrome/chrome_impl.h index d9f3217..161d477 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_impl.h @@ -30,6 +30,7 @@ class ChromeImpl : public Chrome, public WebViewDelegate { // Overridden from Chrome: virtual std::string GetVersion() OVERRIDE; + virtual int GetBuildNo() OVERRIDE; virtual Status GetWebViewIds(std::list<std::string>* web_view_ids) OVERRIDE; virtual Status GetWebViewById(const std::string& id, WebView** web_view) OVERRIDE; diff --git a/chrome/test/chromedriver/chrome/stub_chrome.cc b/chrome/test/chromedriver/chrome/stub_chrome.cc index 56b565f..642e9cd 100644 --- a/chrome/test/chromedriver/chrome/stub_chrome.cc +++ b/chrome/test/chromedriver/chrome/stub_chrome.cc @@ -14,6 +14,10 @@ std::string StubChrome::GetVersion() { return ""; } +int StubChrome::GetBuildNo() { + return 9999; +} + Status StubChrome::GetWebViewIds(std::list<std::string>* web_view_ids) { return Status(kOk); } diff --git a/chrome/test/chromedriver/chrome/stub_chrome.h b/chrome/test/chromedriver/chrome/stub_chrome.h index a919be6..df51692 100644 --- a/chrome/test/chromedriver/chrome/stub_chrome.h +++ b/chrome/test/chromedriver/chrome/stub_chrome.h @@ -20,6 +20,7 @@ class StubChrome : public Chrome { // Overridden from Chrome: virtual std::string GetVersion() OVERRIDE; + virtual int GetBuildNo() OVERRIDE; virtual Status GetWebViewIds(std::list<std::string>* web_view_ids) OVERRIDE; virtual Status GetWebViewById(const std::string& id, WebView** web_view) OVERRIDE; diff --git a/chrome/test/chromedriver/chrome/stub_web_view.cc b/chrome/test/chromedriver/chrome/stub_web_view.cc index a62a66e..8824b2f 100644 --- a/chrome/test/chromedriver/chrome/stub_web_view.cc +++ b/chrome/test/chromedriver/chrome/stub_web_view.cc @@ -92,3 +92,9 @@ Status StubWebView::OverrideGeolocation(const Geoposition& geoposition) { Status StubWebView::CaptureScreenshot(std::string* screenshot) { return Status(kOk); } + +Status StubWebView::SetFileInputFiles(const std::string& frame, + const base::DictionaryValue& element, + const base::ListValue& files) { + return Status(kOk); +} diff --git a/chrome/test/chromedriver/chrome/stub_web_view.h b/chrome/test/chromedriver/chrome/stub_web_view.h index 0dc612b..27de7e9 100644 --- a/chrome/test/chromedriver/chrome/stub_web_view.h +++ b/chrome/test/chromedriver/chrome/stub_web_view.h @@ -57,6 +57,9 @@ class StubWebView : public WebView { virtual JavaScriptDialogManager* GetJavaScriptDialogManager() OVERRIDE; virtual Status OverrideGeolocation(const Geoposition& geoposition) OVERRIDE; virtual Status CaptureScreenshot(std::string* screenshot) OVERRIDE; + virtual Status SetFileInputFiles(const std::string& frame, + const base::DictionaryValue& element, + const base::ListValue& files) OVERRIDE; private: std::string id_; diff --git a/chrome/test/chromedriver/chrome/web_view.h b/chrome/test/chromedriver/chrome/web_view.h index 5bfe5d1..14759f4 100644 --- a/chrome/test/chromedriver/chrome/web_view.h +++ b/chrome/test/chromedriver/chrome/web_view.h @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" namespace base { +class DictionaryValue; class ListValue; class Value; } @@ -98,6 +99,12 @@ class WebView { // Captures the visible portions of the web view as a base64-encoded PNG. virtual Status CaptureScreenshot(std::string* screenshot) = 0; + + // Set files in a file input element. + // |element| is the WebElement JSON Object of the input element. + virtual Status SetFileInputFiles(const std::string& frame, + const base::DictionaryValue& element, + const base::ListValue& files) = 0; }; #endif // CHROME_TEST_CHROMEDRIVER_CHROME_WEB_VIEW_H_ diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc index 7da699c..9ccbbe6 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl.cc +++ b/chrome/test/chromedriver/chrome/web_view_impl.cc @@ -299,6 +299,29 @@ Status WebViewImpl::CaptureScreenshot(std::string* screenshot) { return Status(kOk); } +Status WebViewImpl::SetFileInputFiles(const std::string& frame, + const base::DictionaryValue& element, + const base::ListValue& files) { + int context_id; + Status status = GetContextIdForFrame(frame_tracker_.get(), frame, + &context_id); + if (status.IsError()) + return status; + base::ListValue args; + args.Append(element.DeepCopy()); + int node_id; + status = internal::GetNodeIdFromFunction( + client_.get(), context_id, "function(element) { return element; }", + args, &node_id); + if (status.IsError()) + return status; + base::DictionaryValue params; + params.SetInteger("nodeId", node_id); + params.Set("files", files.DeepCopy()); + return client_->SendCommand("DOM.setFileInputFiles", params); +} + + namespace internal { Status EvaluateScript(DevToolsClient* client, diff --git a/chrome/test/chromedriver/chrome/web_view_impl.h b/chrome/test/chromedriver/chrome/web_view_impl.h index 57ccb0c..378ad57 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl.h +++ b/chrome/test/chromedriver/chrome/web_view_impl.h @@ -70,6 +70,9 @@ class WebViewImpl : public WebView { virtual JavaScriptDialogManager* GetJavaScriptDialogManager() OVERRIDE; virtual Status OverrideGeolocation(const Geoposition& geoposition) OVERRIDE; virtual Status CaptureScreenshot(std::string* screenshot) OVERRIDE; + virtual Status SetFileInputFiles(const std::string& frame, + const base::DictionaryValue& element, + const base::ListValue& files) OVERRIDE; private: std::string id_; diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc index 594bf59..395da59 100644 --- a/chrome/test/chromedriver/element_commands.cc +++ b/chrome/test/chromedriver/element_commands.cc @@ -5,8 +5,12 @@ #include "chrome/test/chromedriver/element_commands.h" #include <list> +#include <vector> #include "base/callback.h" +#include "base/files/file_path.h" +#include "base/stringprintf.h" +#include "base/strings/string_split.h" #include "base/values.h" #include "chrome/test/chromedriver/basic_types.h" #include "chrome/test/chromedriver/chrome/chrome.h" @@ -188,8 +192,44 @@ Status ExecuteSendKeysToElement( if (status.IsError()) return status; if (is_input && is_file) { - // TODO(chrisgao): Implement file upload. - return Status(kUnknownError, "file upload is not implemented"); + // File upload is only supported for chrome 27+. + if (session->chrome->GetBuildNo() < 1420) { + return Status( + kUnknownError, + base::StringPrintf( + "file upload requires chrome 27+, build 1420+," + "while current one is %s", + session->chrome->GetVersion().c_str())); + } + + // Compress array into a single string. + base::FilePath::StringType paths_string; + for (size_t i = 0; i < key_list->GetSize(); ++i) { + base::FilePath::StringType path_part; + if (!key_list->GetString(i, &path_part)) + return Status(kUnknownError, "'value' is invalid"); + paths_string.append(path_part); + } + + // Separate the string into separate paths, delimited by '\n'. + std::vector<base::FilePath::StringType> paths; + base::SplitString(paths_string, '\n', &paths); + + bool multiple = false; + status = IsElementAttributeEqualToIgnoreCase( + session, web_view, element_id, "multiple", "true", &multiple); + if (status.IsError()) + return status; + if (!multiple && paths.size() > 1) + return Status(kUnknownError, "the element can not hold multiple files"); + + base::ListValue files; + for (size_t i = 0; i < paths.size(); ++i) + files.AppendString(paths[i]); + + scoped_ptr<base::DictionaryValue> element(CreateElement(element_id)); + return web_view->SetFileInputFiles( + session->GetCurrentFrameId(), *element, files); } else { return SendKeysToElement(session, web_view, element_id, key_list); } |