summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-16 04:22:51 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-16 04:22:51 +0000
commitb679032aef9317482f87ceaf67ee138aaa67a152 (patch)
tree8ccd1bcf22215a8b62464c11ec01075c34f0fcb9 /chrome_frame
parent94b7e8d7a56619b6c98f23c2f6f8d4f2f65b48e7 (diff)
downloadchromium_src-b679032aef9317482f87ceaf67ee138aaa67a152.zip
chromium_src-b679032aef9317482f87ceaf67ee138aaa67a152.tar.gz
chromium_src-b679032aef9317482f87ceaf67ee138aaa67a152.tar.bz2
Resurrecting Tommi's attachment download test in response to a FORM post request. This
test was incorrectly deleted during the test reorganization. Added expectations to this test to look for the File download dialog box and close it when we see this. Added an end to end download attachment test with a lot of help from Stoyan about the intricacies of gmock which saves the file and verifies that the content matches that being sent from the server. Bug=36694 Review URL: http://codereview.chromium.org/3833002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62846 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/test/ie_event_sink.cc7
-rw-r--r--chrome_frame/test/mock_ie_event_sink_actions.h31
-rw-r--r--chrome_frame/test/mock_ie_event_sink_test.cc1
-rw-r--r--chrome_frame/test/navigation_test.cc121
-rw-r--r--chrome_frame/test/test_with_web_server.cc126
5 files changed, 283 insertions, 3 deletions
diff --git a/chrome_frame/test/ie_event_sink.cc b/chrome_frame/test/ie_event_sink.cc
index 9848dcc..85bebb88 100644
--- a/chrome_frame/test/ie_event_sink.cc
+++ b/chrome_frame/test/ie_event_sink.cc
@@ -463,10 +463,11 @@ STDMETHODIMP_(void) IEEventSink::OnFileDownload(
VARIANT_BOOL active_doc, VARIANT_BOOL* cancel) {
DLOG(INFO) << __FUNCTION__ << base::StringPrintf(" 0x%08X ad=%i", this,
active_doc);
- if (listener_)
+ if (listener_) {
listener_->OnFileDownload(active_doc, cancel);
- // Always cancel file downloads in tests.
- *cancel = VARIANT_TRUE;
+ } else {
+ *cancel = VARIANT_TRUE;
+ }
}
STDMETHODIMP_(void) IEEventSink::OnNewWindow3(
diff --git a/chrome_frame/test/mock_ie_event_sink_actions.h b/chrome_frame/test/mock_ie_event_sink_actions.h
index e010bfc..830ded7 100644
--- a/chrome_frame/test/mock_ie_event_sink_actions.h
+++ b/chrome_frame/test/mock_ie_event_sink_actions.h
@@ -92,6 +92,14 @@ ACTION_P(AccDoDefaultAction, matcher) {
}
}
+ACTION_P2(DelayAccDoDefaultAction, matcher, delay) {
+ SleepEx(delay, false);
+ scoped_refptr<AccObject> object;
+ if (FindAccObjectInWindow(arg0, matcher, &object)) {
+ EXPECT_TRUE(object->DoDefaultAction());
+ }
+}
+
ACTION_P(AccLeftClick, matcher) {
scoped_refptr<AccObject> object;
if (FindAccObjectInWindow(arg0, matcher, &object)) {
@@ -99,6 +107,17 @@ ACTION_P(AccLeftClick, matcher) {
}
}
+ACTION_P(AccSendCommand, matcher) {
+ scoped_refptr<AccObject> object;
+ if (FindAccObjectInWindow(arg0, matcher, &object)) {
+ HWND window = NULL;
+ object->GetWindow(&window);
+ long window_id = GetWindowLong(window, GWL_ID);
+ ::SendMessage(arg0, WM_COMMAND, MAKEWPARAM(window_id, BN_CLICKED),
+ reinterpret_cast<LPARAM>(window));
+ }
+}
+
ACTION_P(AccRightClick, matcher) {
scoped_refptr<AccObject> object;
if (FindAccObjectInWindow(arg0, matcher, &object)) {
@@ -170,6 +189,7 @@ ACTION_P2(AccSendCharMessage, matcher, character_code) {
::SendMessage(window, WM_CHAR, character_code, 0);
}
}
+
// Various other actions
ACTION(OpenContextMenuAsync) {
@@ -316,6 +336,17 @@ ACTION_P3(CloseWhenFileSaved, mock, file, timeout_ms) {
mock->event_sink()->CloseWebBrowser();
}
+ACTION_P2(WaitForFileSave, file, timeout_ms) {
+ base::Time start = base::Time::Now();
+ while (!file_util::PathExists(file)) {
+ PlatformThread::Sleep(200);
+ if ((base::Time::Now() - start).InMilliseconds() > timeout_ms) {
+ ADD_FAILURE() << "File was not saved within timeout";
+ break;
+ }
+ }
+}
+
// Flaky actions
ACTION_P(SetFocusToRenderer, mock) {
diff --git a/chrome_frame/test/mock_ie_event_sink_test.cc b/chrome_frame/test/mock_ie_event_sink_test.cc
index 9037358..cb77efa 100644
--- a/chrome_frame/test/mock_ie_event_sink_test.cc
+++ b/chrome_frame/test/mock_ie_event_sink_test.cc
@@ -69,6 +69,7 @@ ExpectationSet MockIEEventSink::ExpectNavigationCardinality(
while (!complete_cardinality.IsSaturatedByCallCount(call_count)) {
navigation += EXPECT_CALL(*this, OnFileDownload(_, _))
.Times(testing::AtMost(1))
+ .WillOnce(testing::SetArgumentPointee<1>(VARIANT_TRUE))
.RetiresOnSaturation();
Cardinality split_complete_cardinality = testing::Exactly(1);
diff --git a/chrome_frame/test/navigation_test.cc b/chrome_frame/test/navigation_test.cc
index 62cb876..6ff83dd 100644
--- a/chrome_frame/test/navigation_test.cc
+++ b/chrome_frame/test/navigation_test.cc
@@ -5,6 +5,7 @@
#include <string>
#include "base/scoped_comptr_win.h"
+#include "base/test/test_file_util.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
#include "chrome_frame/test/chrome_frame_ui_test_utils.h"
#include "chrome_frame/test/mock_ie_event_sink_actions.h"
@@ -714,4 +715,124 @@ TEST_P(FullTabNavigationTest, CF_UnloadEventTest) {
LaunchIEAndNavigate(kUnloadEventTestUrl);
}
+// Fixture for ChromeFrame download tests.
+class FullTabDownloadTest
+ : public MockIEEventSinkTest, public testing::TestWithParam<CFInvocation> {
+ public:
+ FullTabDownloadTest() {}
+};
+
+void SaveOwnerWindow(HWND* owner_window, HWND window) {
+ *owner_window = GetWindow(window, GW_OWNER);
+}
+
+void CloseWindow(HWND* window) {
+ if (window)
+ PostMessage(*window, WM_CLOSE, 0, 0);
+}
+
+// See bug http://crbug.com/36694
+// This test does the following:-
+// Navigates IE to a URL which in ChromeFrame.
+// Performs a top level form post in the document
+// In response to the POST we send over an attachment via the
+// content-disposition header.
+// IE brings up a file open dialog in this context.
+// We bring up the Save dialog via accessibility and save the file
+// and validate that all is well.
+TEST_F(FullTabDownloadTest, CF_DownloadFileFromPost) {
+ chrome_frame_test::MockWindowObserver download_watcher;
+ download_watcher.WatchWindow("File Download");
+
+ chrome_frame_test::MockWindowObserver save_dialog_watcher;
+ save_dialog_watcher.WatchWindow("Save As");
+
+ EXPECT_CALL(server_mock_, Get(_, StrEq(L"/post_source.html"), _)).WillOnce(
+ SendFast(
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/html\r\n",
+ "<html>"
+ "<head><meta http-equiv=\"x-ua-compatible\" content=\"chrome=1\" />"
+ " <script type=\"text/javascript\">"
+ " function onLoad() {"
+ " document.getElementById(\"myform\").submit();}</script></head>"
+ " <body onload=\"setTimeout(onLoad, 2000);\">"
+ " <form id=\"myform\" action=\"post_target.html\" method=\"POST\">"
+ "</form></body></html>"));
+
+ EXPECT_CALL(server_mock_, Post(_, StrEq(L"/post_target.html"), _)).WillOnce(
+ SendFast(
+ "HTTP/1.1 200 OK\r\n"
+ "content-disposition: attachment;filename=\"hello.txt\"\r\n"
+ "Content-Type: application/text\r\n"
+ "Cache-Control: private\r\n",
+ "hello"));
+
+
+ // If you want to debug this action then you may need to
+ // SendMessage(parent_window, WM_NCACTIVATE, TRUE, 0);
+ // SendMessage(parent_window, WM_COMMAND, MAKEWPARAM(0x114B, BN_CLICKED),
+ // control_window);
+ // For the uninitiated, please debug IEFrame!CDialogActivateGuard::*
+ EXPECT_CALL(download_watcher, OnWindowOpen(_))
+ .Times(2)
+ .WillOnce(DelayAccDoDefaultAction(
+ AccObjectMatcher(L"Save", L"push button"),
+ 1000))
+ .WillOnce(testing::Return());
+
+ EXPECT_CALL(download_watcher, OnWindowClose(_))
+ .Times(testing::AnyNumber());
+
+ std::wstring src_url = server_mock_.Resolve(L"/post_source.html");
+ std::wstring tgt_url = server_mock_.Resolve(L"/post_target.html");
+
+ EXPECT_CALL(ie_mock_, OnFileDownload(_, _)).Times(testing::AnyNumber());
+
+ EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_,
+ testing::Field(&VARIANT::bstrVal,
+ StrEq(src_url)), _, _, _, _, _));
+ EXPECT_CALL(ie_mock_, OnNavigateComplete2(_,
+ testing::Field(&VARIANT::bstrVal,
+ StrEq(src_url))));
+ EXPECT_CALL(ie_mock_, OnLoad(true, StrEq(src_url)));
+
+ EXPECT_CALL(ie_mock_, OnLoadError(StrEq(tgt_url)))
+ .Times(testing::AnyNumber());
+ EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_,
+ testing::Field(&VARIANT::bstrVal,
+ StrEq(tgt_url)), _, _, _, _, _));
+ FilePath temp_file_path;
+ ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
+ file_util::DieFileDie(temp_file_path, false);
+
+ temp_file_path = temp_file_path.ReplaceExtension(L"txt");
+ file_util::DieFileDie(temp_file_path, false);
+
+ AccObjectMatcher file_name_box(L"File name:", L"editable text");
+
+ HWND owner_window = NULL;
+
+ EXPECT_CALL(save_dialog_watcher, OnWindowOpen(_))
+ .WillOnce(testing::DoAll(
+ testing::Invoke(testing::CreateFunctor(
+ SaveOwnerWindow, &owner_window)),
+ AccSendCharMessage(file_name_box, L'a'),
+ AccSetValue(file_name_box, temp_file_path.value()),
+ AccDoDefaultAction(AccObjectMatcher(L"Save", L"push button"))));
+
+ EXPECT_CALL(save_dialog_watcher, OnWindowClose(_))
+ .WillOnce(testing::DoAll(
+ WaitForFileSave(temp_file_path, 2000),
+ testing::InvokeWithoutArgs(
+ testing::CreateFunctor(CloseWindow, &owner_window)),
+ CloseBrowserMock(&ie_mock_)));
+ LaunchIENavigateAndLoop(src_url, kChromeFrameLongNavigationTimeoutInSeconds);
+
+ std::string data;
+ EXPECT_TRUE(file_util::ReadFileToString(temp_file_path, &data));
+ EXPECT_EQ("hello", data);
+ file_util::DieFileDie(temp_file_path, false);
+}
+
} // namespace chrome_frame_test
diff --git a/chrome_frame/test/test_with_web_server.cc b/chrome_frame/test/test_with_web_server.cc
index 2ee8e17..29b3831 100644
--- a/chrome_frame/test/test_with_web_server.cc
+++ b/chrome_frame/test/test_with_web_server.cc
@@ -17,6 +17,7 @@
#include "chrome_frame/utils.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
#include "chrome_frame/test/mock_ie_event_sink_actions.h"
+#include "chrome_frame/test/mock_ie_event_sink_test.h"
#include "net/base/mime_util.h"
#include "net/http/http_util.h"
@@ -1116,3 +1117,128 @@ TEST_F(ChromeFrameTestWithWebServer, FAILS_FullTabModeIE_RefreshMshtmlTest) {
EXPECT_GT(requests_for_first_page, 1);
}
+// See bug 36694 for details. http://crbug.com/36694
+TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_TestDownloadFromForm) {
+ chrome_frame_test::MockWindowObserver win_observer_mock;
+ win_observer_mock.WatchWindow("File Download");
+
+ // The content of our HTML test page. This will be returned whenever
+ // we reply to a GET request.
+ static const char kHtml[] =
+ "<html><head>\n"
+ "<title>ChromeFrame Form Download Test</title>\n"
+ // To see how this test runs with only IE (no CF in the picture), comment
+ // out this meta tag. The outcome of the test should be identical.
+ "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />\n"
+ "</head>\n"
+ "<script language=\"javascript\">\n"
+ "function SubmitForm() {\n"
+ " var form = document.forms['myform'];\n"
+ " form.action = document.location;\n"
+ " form.submit();\n"
+ " return true;\n"
+ "}\n"
+ "</script>\n"
+ "<body onload=\"SubmitForm();\">\n"
+ "<form method=\"post\" action=\"foo.html\" id=\"myform\">\n"
+ " <input type=\"hidden\" name=\"Field1\" value=\"myvalue\" />\n"
+ " <input type=\"button\" name=\"btn\" value=\"Test Download\" "
+ "onclick=\"return SubmitForm();\" id=\"Button1\"/>\n"
+ "</form></body></html>\n";
+
+ // The content of our HTML test page. This will be returned whenever
+ // we reply to a POST request.
+ static const char kText[] =
+ "This is a text file (in case you were wondering).";
+
+ // This http response class will return an HTML document that contains
+ // a form whenever it receives a GET request. Whenever it gets a POST
+ // request, it will respond with a text file that needs to be downloaded
+ // (content-disposition is "attachment").
+ class CustomResponse : public test_server::ResponseForPath {
+ public:
+ explicit CustomResponse(const char* path)
+ : test_server::ResponseForPath(path), is_post_(false),
+ post_requests_(0), get_requests_(0) {
+ }
+
+ virtual bool GetContentType(std::string* content_type) const {
+ DCHECK(!is_post_);
+ return false;
+ }
+
+ virtual size_t ContentLength() const {
+ DCHECK(!is_post_);
+ return sizeof(kHtml) - 1;
+ }
+
+ virtual bool GetCustomHeaders(std::string* headers) const {
+ if (!is_post_)
+ return false;
+ *headers = StringPrintf(
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Disposition: attachment;filename=\"test.txt\"\r\n"
+ "Content-Type: application/text\r\n"
+ "Connection: close\r\n"
+ "Content-Length: %i\r\n\r\n", sizeof(kText) - 1);
+ return true;
+ }
+
+ virtual bool Matches(const test_server::Request& r) const {
+ bool match = __super::Matches(r);
+ if (match) {
+ is_post_ = LowerCaseEqualsASCII(r.method().c_str(), "post");
+ }
+ return match;
+ }
+
+ virtual void WriteContents(ListenSocket* socket) const {
+ if (is_post_) {
+ socket->Send(kText, sizeof(kText) - 1, false);
+ } else {
+ socket->Send(kHtml, sizeof(kHtml) - 1, false);
+ }
+ }
+
+ virtual void IncrementAccessCounter() {
+ __super::IncrementAccessCounter();
+ if (is_post_) {
+ post_requests_++;
+ } else {
+ get_requests_++;
+ }
+ }
+
+ size_t get_request_count() const {
+ return get_requests_;
+ }
+
+ size_t post_request_count() const {
+ return get_requests_;
+ }
+
+ protected:
+ mutable bool is_post_;
+ size_t post_requests_;
+ size_t get_requests_;
+ };
+
+ EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
+ .WillOnce(chrome_frame_test::DoCloseWindow());
+
+ EXPECT_CALL(win_observer_mock, OnWindowClose(_))
+ .WillOnce(QUIT_LOOP(loop_));
+
+ SimpleWebServerTest server(46664);
+ CustomResponse* response = new CustomResponse("/form.html");
+ server.web_server()->AddResponse(response);
+
+ std::wstring url(server.FormatHttpPath(L"form.html"));
+
+ ASSERT_TRUE(LaunchBrowser(IE, url.c_str()));
+ loop_.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
+
+ EXPECT_EQ(1, response->get_request_count());
+ EXPECT_EQ(1, response->post_request_count());
+}
+