- add sources.
[platform/framework/web/crosswalk.git] / src / chrome_frame / test / test_with_web_server.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome_frame/test/test_with_web_server.h"
6
7 #include "base/base_paths.h"
8 #include "base/file_util.h"
9 #include "base/file_version_info.h"
10 #include "base/files/memory_mapped_file.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/path_service.h"
13 #include "base/process/kill.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/win/windows_version.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/installer/util/helper.h"
20 #include "chrome/installer/util/install_util.h"
21 #include "chrome/installer/util/product.h"
22 #include "chrome_frame/html_utils.h"
23 #include "chrome_frame/test/chrome_frame_test_utils.h"
24 #include "chrome_frame/test/mock_ie_event_sink_actions.h"
25 #include "chrome_frame/test/mock_ie_event_sink_test.h"
26 #include "chrome_frame/test/test_scrubber.h"
27 #include "chrome_frame/utils.h"
28 #include "net/base/mime_util.h"
29 #include "net/http/http_util.h"
30 #include "net/socket/stream_listen_socket.h"
31
32 using chrome_frame_test::kChromeFrameLongNavigationTimeout;
33 using chrome_frame_test::kChromeFrameVeryLongNavigationTimeout;
34
35 using testing::_;
36 using testing::StrCaseEq;
37
38 const wchar_t kDocRoot[] = L"chrome_frame\\test\\data";
39
40 namespace {
41
42 // Helper method for creating the appropriate HTTP response headers.
43 std::string CreateHttpHeaders(CFInvocation invocation,
44                               bool add_no_cache_header,
45                               const std::string& content_type) {
46   std::ostringstream ss;
47   ss << "HTTP/1.1 200 OK\r\n"
48      << "Connection: close\r\n"
49      << "Content-Type: " << content_type << "\r\n";
50   if (invocation.type() == CFInvocation::HTTP_HEADER)
51     ss << "X-UA-Compatible: chrome=1\r\n";
52   if (add_no_cache_header) {
53     ss << "Cache-Control: no-cache\r\n";
54     ss << "Expires: Tue, 15 Nov 1994 08:12:31 GMT\r\n";
55   }
56   return ss.str();
57 }
58
59 std::string GetMockHttpHeaders(const base::FilePath& mock_http_headers_path) {
60   std::string headers;
61   base::ReadFileToString(mock_http_headers_path, &headers);
62   return headers;
63 }
64
65 class ChromeFrameTestEnvironment: public testing::Environment {
66  public:
67   virtual ~ChromeFrameTestEnvironment() {}
68   virtual void SetUp() OVERRIDE {
69     ScopedChromeFrameRegistrar::RegisterDefaults();
70   }
71 };
72
73 ::testing::Environment* const chrome_frame_env =
74     ::testing::AddGlobalTestEnvironment(new ChromeFrameTestEnvironment);
75
76 }  // namespace
77
78 base::FilePath ChromeFrameTestWithWebServer::test_file_path_;
79 base::FilePath ChromeFrameTestWithWebServer::results_dir_;
80 base::FilePath ChromeFrameTestWithWebServer::CFInstall_path_;
81 base::FilePath ChromeFrameTestWithWebServer::CFInstance_path_;
82 base::ScopedTempDir ChromeFrameTestWithWebServer::temp_dir_;
83 base::FilePath ChromeFrameTestWithWebServer::chrome_user_data_dir_;
84 chrome_frame_test::TimedMsgLoop* ChromeFrameTestWithWebServer::loop_;
85 std::string ChromeFrameTestWithWebServer::local_address_;
86 testing::StrictMock<MockWebServerListener>*
87     ChromeFrameTestWithWebServer::listener_mock_;
88 testing::StrictMock<MockWebServer>* ChromeFrameTestWithWebServer::server_mock_;
89
90 ChromeFrameTestWithWebServer::ChromeFrameTestWithWebServer() {
91 }
92
93 // static
94 void ChromeFrameTestWithWebServer::SetUpTestCase() {
95   base::FilePath chrome_frame_source_path;
96   PathService::Get(base::DIR_SOURCE_ROOT, &chrome_frame_source_path);
97   chrome_frame_source_path = chrome_frame_source_path.Append(
98       FILE_PATH_LITERAL("chrome_frame"));
99
100   test_file_path_ = chrome_frame_source_path
101       .Append(FILE_PATH_LITERAL("test"))
102       .Append(FILE_PATH_LITERAL("data"));
103
104   results_dir_ = chrome_frame_test::GetTestDataFolder().AppendASCII("dump");
105
106   // Copy the CFInstance.js and CFInstall.js files from src\chrome_frame to
107   // src\chrome_frame\test\data.
108   base::FilePath CFInstance_src_path;
109   base::FilePath CFInstall_src_path;
110
111   CFInstance_src_path = chrome_frame_source_path.AppendASCII("CFInstance.js");
112   CFInstance_path_ = test_file_path_.AppendASCII("CFInstance.js");
113
114   ASSERT_TRUE(base::CopyFile(CFInstance_src_path, CFInstance_path_));
115
116   CFInstall_src_path = chrome_frame_source_path.AppendASCII("CFInstall.js");
117   CFInstall_path_ = test_file_path_.AppendASCII("CFInstall.js");
118
119   ASSERT_TRUE(base::CopyFile(CFInstall_src_path, CFInstall_path_));
120
121   loop_ = new chrome_frame_test::TimedMsgLoop();
122   loop_->set_snapshot_on_timeout(true);
123   local_address_ = chrome_frame_test::GetLocalIPv4Address();
124   listener_mock_ = new testing::StrictMock<MockWebServerListener>();
125   server_mock_ = new testing::StrictMock<MockWebServer>(
126       1337, ASCIIToWide(local_address_),
127       chrome_frame_test::GetTestDataFolder());
128   server_mock_->set_listener(listener_mock_);
129 }
130
131 // static
132 void ChromeFrameTestWithWebServer::TearDownTestCase() {
133   delete server_mock_;
134   server_mock_ = NULL;
135   delete listener_mock_;
136   listener_mock_ = NULL;
137   local_address_.clear();
138   delete loop_;
139   loop_ = NULL;
140   base::DeleteFile(CFInstall_path_, false);
141   base::DeleteFile(CFInstance_path_, false);
142   if (temp_dir_.IsValid())
143     EXPECT_TRUE(temp_dir_.Delete());
144 }
145
146 // static
147 const base::FilePath&
148 ChromeFrameTestWithWebServer::GetChromeUserDataDirectory() {
149   if (!temp_dir_.IsValid()) {
150     EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
151     chrome_user_data_dir_ = temp_dir_.path().AppendASCII("User Data");
152   }
153   return chrome_user_data_dir_;
154 }
155
156 void ChromeFrameTestWithWebServer::SetUp() {
157   // Make sure that we are not accidentally enabling gcf protocol.
158   SetConfigBool(kAllowUnsafeURLs, false);
159
160   server_mock().ClearResults();
161   server_mock().ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
162   server_mock().set_expected_result("OK");
163 }
164
165 void ChromeFrameTestWithWebServer::TearDown() {
166   CloseBrowser();
167   loop().RunUntilIdle();
168   testing::Mock::VerifyAndClear(listener_mock_);
169   testing::Mock::VerifyAndClear(server_mock_);
170 }
171
172 bool ChromeFrameTestWithWebServer::LaunchBrowser(BrowserKind browser,
173                                                  const wchar_t* page) {
174   std::wstring url = page;
175
176   // We should resolve the URL only if it is a relative url.
177   GURL parsed_url(WideToUTF8(page));
178   if (!parsed_url.has_scheme()) {
179     url = server_mock().Resolve(page);
180   }
181
182   browser_ = browser;
183   if (browser == IE) {
184     browser_handle_.Set(chrome_frame_test::LaunchIE(url));
185   } else if (browser == CHROME) {
186     const base::FilePath& user_data_dir = GetChromeUserDataDirectory();
187     chrome_frame_test::OverrideDataDirectoryForThisTest(user_data_dir.value());
188     browser_handle_.Set(chrome_frame_test::LaunchChrome(url, user_data_dir));
189   } else {
190     NOTREACHED();
191   }
192
193   return browser_handle_.IsValid();
194 }
195
196 void ChromeFrameTestWithWebServer::CloseBrowser() {
197   if (!browser_handle_.IsValid())
198     return;
199
200   int attempts = 0;
201   if (browser_ == IE) {
202     attempts = chrome_frame_test::CloseAllIEWindows();
203   } else {
204     attempts = chrome_frame_test::CloseVisibleWindowsOnAllThreads(
205                                                                browser_handle_);
206   }
207
208   if (attempts > 0) {
209     DWORD wait = ::WaitForSingleObject(browser_handle_, 20000);
210     if (wait == WAIT_OBJECT_0) {
211       browser_handle_.Close();
212     } else {
213       LOG(ERROR) << "WaitForSingleObject returned " << wait;
214     }
215   } else {
216     LOG(ERROR) << "No attempts to close browser windows";
217   }
218
219   if (browser_handle_.IsValid()) {
220     DWORD exit_code = 0;
221     if (!::GetExitCodeProcess(browser_handle_, &exit_code) ||
222         exit_code == STILL_ACTIVE) {
223       LOG(ERROR) << L"Forcefully killing browser process. Exit:" << exit_code;
224       base::KillProcess(browser_handle_, 0, true);
225     }
226     browser_handle_.Close();
227   }
228 }
229
230 bool ChromeFrameTestWithWebServer::BringBrowserToTop() {
231   return simulate_input::EnsureProcessInForeground(
232       GetProcessId(browser_handle_));
233 }
234
235 bool ChromeFrameTestWithWebServer::WaitForTestToComplete(
236     base::TimeDelta duration) {
237   loop().RunFor(duration);
238   return !loop().WasTimedOut();
239 }
240
241 bool ChromeFrameTestWithWebServer::WaitForOnLoad(int milliseconds) {
242   return false;
243 }
244
245 const wchar_t kPostedResultSubstring[] = L"/writefile/";
246
247 void ChromeFrameTestWithWebServer::SimpleBrowserTestExpectedResult(
248     BrowserKind browser, const wchar_t* page, const char* result) {
249   if (browser == IE && chrome_frame_test::GetInstalledIEVersion() >= IE_9) {
250     LOG(INFO) << "Temporarily disabling IE9 web server tests. "
251                  "See http://crbug.com/143699";
252     return;
253   }
254
255   int tries = 0;
256   ExpectAndHandlePostedResult();
257   // Retry tests that timeout once; see http://crbug.com/96449.
258   do {
259     // NOTE: Failed ASSERTs cause this function to exit immediately.
260     // Don't take a snapshot on the first try.
261     loop().set_snapshot_on_timeout(tries != 0);
262     ASSERT_TRUE(LaunchBrowser(browser, page));
263     if (WaitForTestToComplete(TestTimeouts::action_max_timeout())) {
264       // The test exited without timing out.  Confirm that the expected response
265       // was posted and return.
266       ASSERT_EQ(result, server_mock().posted_result());
267       break;
268     }
269     ASSERT_EQ(std::string(), server_mock().posted_result())
270         << "Test timed out yet provided a result.";
271     ASSERT_EQ(0, tries++) << "Failing test due to two timeouts.";
272     // Close the browser and try a second time.
273     CloseBrowser();
274     LOG(ERROR) << "Retrying test once since it timed out.";
275   } while (true);
276   loop().set_snapshot_on_timeout(true);
277 }
278
279 void ChromeFrameTestWithWebServer::SimpleBrowserTest(BrowserKind browser,
280     const wchar_t* page) {
281   SimpleBrowserTestExpectedResult(browser, page, "OK");
282 }
283
284 void ChromeFrameTestWithWebServer::ExpectAndHandlePostedResult() {
285   EXPECT_CALL(listener_mock(), OnExpectedResponse())
286       .WillRepeatedly(QUIT_LOOP_SOON(loop(),
287                                      base::TimeDelta::FromMilliseconds(100)));
288   server_mock().ExpectAndHandlePostedResult(CFInvocation(CFInvocation::NONE),
289                                             kPostedResultSubstring);
290 }
291
292 void ChromeFrameTestWithWebServer::VersionTest(BrowserKind browser,
293     const wchar_t* page) {
294   base::FilePath plugin_path;
295   PathService::Get(base::DIR_MODULE, &plugin_path);
296   plugin_path = plugin_path.Append(kChromeFrameDllName);
297
298   static FileVersionInfo* version_info =
299       FileVersionInfo::CreateFileVersionInfo(plugin_path);
300
301   std::wstring version;
302   if (version_info)
303     version = version_info->product_version();
304
305   // If we can't find the Chrome Frame DLL in the src tree, we turn to
306   // the directory where chrome is installed.
307   if (!version_info) {
308     BrowserDistribution* dist = BrowserDistribution::GetDistribution();
309     Version ver_system;
310     InstallUtil::GetChromeVersion(dist, true, &ver_system);
311     Version ver_user;
312     InstallUtil::GetChromeVersion(dist, false, &ver_system);
313     ASSERT_TRUE(ver_system.IsValid() || ver_user.IsValid());
314
315     bool system_install = ver_system.IsValid();
316     base::FilePath cf_dll_path(installer::GetChromeInstallPath(system_install, dist));
317     cf_dll_path = cf_dll_path.Append(UTF8ToWide(
318         ver_system.IsValid() ? ver_system.GetString() : ver_user.GetString()));
319     cf_dll_path = cf_dll_path.Append(kChromeFrameDllName);
320     version_info = FileVersionInfo::CreateFileVersionInfo(cf_dll_path);
321     if (version_info)
322       version = version_info->product_version();
323   }
324
325   server_mock().set_expected_result(WideToUTF8(version));
326
327   EXPECT_TRUE(version_info);
328   EXPECT_FALSE(version.empty());
329
330   SimpleBrowserTestExpectedResult(browser, page, WideToASCII(version).c_str());
331 }
332
333 // MockWebServer methods
334 void MockWebServer::ExpectAndServeRequest(CFInvocation invocation,
335                                           const std::wstring& url) {
336   ExpectAndServeRequestWithCardinality(invocation, url, testing::Exactly(1));
337 }
338
339 void MockWebServer::ExpectAndServeRequestWithCardinality(
340     CFInvocation invocation, const std::wstring& url,
341     testing::Cardinality cardinality) {
342   EXPECT_CALL(*this, Get(_, chrome_frame_test::UrlPathEq(url), _))
343       .Times(cardinality)
344       .WillRepeatedly(SendResponse(this, invocation));
345 }
346
347 void MockWebServer::ExpectAndServeRequestAllowCache(CFInvocation invocation,
348                                                     const std::wstring &url) {
349   EXPECT_CALL(*this, Get(_, chrome_frame_test::UrlPathEq(url), _))
350       .WillOnce(SendResponse(this, invocation));
351 }
352
353 void MockWebServer::ExpectAndServeRequestAnyNumberTimes(
354     CFInvocation invocation, const std::wstring& path_prefix) {
355   EXPECT_CALL(*this, Get(_, testing::StartsWith(path_prefix), _))
356       .WillRepeatedly(SendResponse(this, invocation));
357 }
358
359 void MockWebServer::ExpectAndHandlePostedResult(
360     CFInvocation invocation, const std::wstring& post_suffix) {
361   EXPECT_CALL(*this, Post(_, testing::HasSubstr(post_suffix), _))
362       .WillRepeatedly(HandlePostedResponseHelper(this, invocation));
363 }
364
365 void MockWebServer::HandlePostedResponse(
366     test_server::ConfigurableConnection* connection,
367     const test_server::Request& request) {
368   posted_result_ = request.content();
369   if (listener_ && posted_result_ == expected_result_)
370     listener_->OnExpectedResponse();
371   connection->Send("HTTP/1.1 200 OK\r\n", "");
372 }
373
374 void MockWebServer::SendResponseHelper(
375     test_server::ConfigurableConnection* connection,
376     const std::wstring& request_uri,
377     const test_server::Request& request,
378     CFInvocation invocation,
379     bool add_no_cache_header) {
380   static const wchar_t kEchoHeader[] = L"/echoheader?";
381   if (request_uri.find(kEchoHeader) != std::wstring::npos) {
382     std::wstring header = request_uri.substr(
383         wcslen(kEchoHeader),
384         request_uri.length() - wcslen(kEchoHeader));
385
386     std::string header_value = http_utils::GetHttpHeaderFromHeaderList(
387         WideToUTF8(header), request.headers());
388     connection->Send(header_value, "");
389     return;
390   }
391   // Convert |request_uri| to a path.
392   std::wstring path = request_uri;
393   size_t query_index = request_uri.find(L"?");
394   if (query_index != std::string::npos) {
395     path = path.erase(query_index);
396   }
397   base::FilePath file_path = root_dir_;
398   if (path.size())
399     file_path = file_path.Append(path.substr(1));  // remove first '/'
400
401   std::string headers, body;
402   std::string content_type;
403   if (base::PathExists(file_path) &&
404       !base::DirectoryExists(file_path)) {
405     base::FilePath mock_http_headers(file_path.value() + L".mock-http-headers");
406     if (base::PathExists(mock_http_headers)) {
407       headers = GetMockHttpHeaders(mock_http_headers);
408       content_type = http_utils::GetHttpHeaderFromHeaderList("Content-type",
409                                                              headers);
410     } else {
411       EXPECT_TRUE(net::GetMimeTypeFromFile(file_path, &content_type));
412       VLOG(1) << "Going to send file (" << WideToUTF8(file_path.value())
413               << ") with content type (" << content_type << ")";
414       headers = CreateHttpHeaders(invocation, add_no_cache_header,
415                                   content_type);
416     }
417
418     EXPECT_FALSE(headers.empty());
419
420     EXPECT_TRUE(base::ReadFileToString(file_path, &body))
421         << "Could not read file (" << WideToUTF8(file_path.value()) << ")";
422     if (invocation.type() == CFInvocation::META_TAG &&
423         StartsWithASCII(content_type, "text/html", false)) {
424       EXPECT_TRUE(chrome_frame_test::AddCFMetaTag(&body)) << "Could not add "
425           << "meta tag to HTML file.";
426     }
427   } else {
428     VLOG(1) << "Going to send 404 for non-existent file ("
429             << WideToUTF8(file_path.value()) << ")";
430     headers = "HTTP/1.1 404 Not Found";
431     body = "";
432   }
433   connection->Send(headers, body);
434 }
435
436 const wchar_t kPostMessageBasicPage[] = L"postmessage_basic_host.html";
437
438 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PostMessageBasic) {
439   SimpleBrowserTest(IE, kPostMessageBasicPage);
440 }
441
442 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_MIMEFilterBasic) {
443   const wchar_t kMIMEFilterBasicPage[] =
444       L"chrome_frame_mime_filter_test.html";
445
446   // If this test fails for IE8 then it is possible that prebinding is enabled.
447   // A known workaround is to disable it until CF properly handles it.
448   //
449   // HKCU\Software\Microsoft\Internet Explorer\Main
450   // Value name: EnablePreBinding (REG_DWORD)
451   // Value: 0
452   SimpleBrowserTest(IE, kMIMEFilterBasicPage);
453 }
454
455 // Times out: http://crbug.com/163728
456 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_Resize) {
457   SimpleBrowserTest(IE, L"chrome_frame_resize.html");
458 }
459
460 const wchar_t kNavigateURLAbsolutePage[] =
461     L"navigateurl_absolute_host.html";
462
463 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_NavigateURLAbsolute) {
464   SimpleBrowserTest(IE, kNavigateURLAbsolutePage);
465 }
466
467 const wchar_t kNavigateURLRelativePage[] =
468     L"navigateurl_relative_host.html";
469
470 // Flaky, crbug.com/160497.
471 TEST_F(ChromeFrameTestWithWebServer,
472        DISABLED_WidgetModeIE_NavigateURLRelative) {
473   SimpleBrowserTest(IE, kNavigateURLRelativePage);
474 }
475
476 const wchar_t kNavigateSimpleObjectFocus[] = L"simple_object_focus.html";
477
478 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_ObjectFocus) {
479   SimpleBrowserTest(IE, kNavigateSimpleObjectFocus);
480 }
481
482 const wchar_t kiframeBasicPage[] = L"iframe_basic_host.html";
483
484
485 // Flaky, crbug.com/160497.
486 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_iframeBasic) {
487   SimpleBrowserTest(IE, kiframeBasicPage);
488 }
489
490 const wchar_t kSrcPropertyTestPage[] = L"src_property_host.html";
491
492 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_SrcProperty) {
493   SimpleBrowserTest(IE, kSrcPropertyTestPage);
494 }
495
496 const wchar_t kCFInstanceBasicTestPage[] = L"CFInstance_basic_host.html";
497
498 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceBasic) {
499   SimpleBrowserTest(IE, kCFInstanceBasicTestPage);
500 }
501
502 const wchar_t kCFISingletonPage[] = L"CFInstance_singleton_host.html";
503
504 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceSingleton) {
505   SimpleBrowserTest(IE, kCFISingletonPage);
506 }
507
508 const wchar_t kCFIDelayPage[] = L"CFInstance_delay_host.html";
509
510 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDelay) {
511   SimpleBrowserTest(IE, kCFIDelayPage);
512 }
513
514 const wchar_t kCFIFallbackPage[] = L"CFInstance_fallback_host.html";
515
516 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceFallback) {
517   SimpleBrowserTest(IE, kCFIFallbackPage);
518 }
519
520 const wchar_t kCFINoSrcPage[] = L"CFInstance_no_src_host.html";
521
522 // Flaky, crbug.com/160497.
523 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceNoSrc) {
524   SimpleBrowserTest(IE, kCFINoSrcPage);
525 }
526
527 const wchar_t kCFIIfrOnLoadPage[] = L"CFInstance_iframe_onload_host.html";
528
529 // disabled since it's unlikely that we care about this case
530 TEST_F(ChromeFrameTestWithWebServer,
531        DISABLED_WidgetModeIE_CFInstanceIfrOnLoad) {
532   SimpleBrowserTest(IE, kCFIIfrOnLoadPage);
533 }
534
535 const wchar_t kCFIZeroSizePage[] = L"CFInstance_zero_size_host.html";
536
537 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceZeroSize) {
538   SimpleBrowserTest(IE, kCFIZeroSizePage);
539 }
540
541 const wchar_t kCFIIfrPostPage[] = L"CFInstance_iframe_post_host.html";
542
543 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceIfrPost) {
544   SimpleBrowserTest(IE, kCFIIfrPostPage);
545 }
546
547 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceIfrPost) {
548   SimpleBrowserTest(CHROME, kCFIIfrPostPage);
549 }
550
551 const wchar_t kCFIPostPage[] = L"CFInstance_post_host.html";
552
553 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstancePost) {
554   if (chrome_frame_test::GetInstalledIEVersion() == IE_9) {
555     LOG(INFO) << "Not running test on Vista/Windows 7 with IE9";
556     return;
557   }
558   SimpleBrowserTest(IE, kCFIPostPage);
559 }
560
561 // This test randomly fails on the ChromeFrame builder.
562 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstancePost) {
563   SimpleBrowserTest(CHROME, kCFIPostPage);
564 }
565
566 const wchar_t kCFIRPCPage[] = L"CFInstance_rpc_host.html";
567
568 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPC) {
569   if (chrome_frame_test::GetInstalledIEVersion() == IE_9) {
570     LOG(INFO) << "Not running test on Vista/Windows 7 with IE9";
571     return;
572   }
573   SimpleBrowserTest(IE, kCFIRPCPage);
574 }
575
576 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPC) {
577   SimpleBrowserTest(CHROME, kCFIRPCPage);
578 }
579
580 const wchar_t kCFIRPCInternalPage[] =
581     L"CFInstance_rpc_internal_host.html";
582
583 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPCInternal) {
584   if (chrome_frame_test::GetInstalledIEVersion() == IE_9) {
585     LOG(INFO) << "Not running test on Vista/Windows 7 with IE9";
586     return;
587   }
588   SimpleBrowserTest(IE, kCFIRPCInternalPage);
589 }
590
591 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPCInternal) {
592   SimpleBrowserTest(CHROME, kCFIRPCInternalPage);
593 }
594
595 const wchar_t kCFIDefaultCtorPage[] =
596     L"CFInstance_default_ctor_host.html";
597
598 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDefaultCtor) {
599   SimpleBrowserTest(IE, kCFIDefaultCtorPage);
600 }
601
602 const wchar_t kCFInstallBasicTestPage[] = L"CFInstall_basic.html";
603
604 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallBasic) {
605   SimpleBrowserTest(IE, kCFInstallBasicTestPage);
606 }
607
608 const wchar_t kCFInstallPlaceTestPage[] = L"CFInstall_place.html";
609
610 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallPlace) {
611   SimpleBrowserTest(IE, kCFInstallPlaceTestPage);
612 }
613
614 const wchar_t kCFInstallOverlayTestPage[] = L"CFInstall_overlay.html";
615
616 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallOverlay) {
617   SimpleBrowserTest(IE, kCFInstallOverlayTestPage);
618 }
619
620 const wchar_t kCFInstallDismissTestPage[] = L"CFInstall_dismiss.html";
621
622 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_CFInstallDismiss) {
623   SimpleBrowserTest(IE, kCFInstallDismissTestPage);
624 }
625
626 const wchar_t kInitializeHiddenPage[] = L"initialize_hidden.html";
627 // Times out: http://crbug.com/163728
628 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_InitializeHidden) {
629   SimpleBrowserTest(IE, kInitializeHiddenPage);
630 }
631
632 const wchar_t kFullTabHttpHeaderPage[] = L"chrome_frame_http_header.html";
633
634 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderBasic) {
635   SimpleBrowserTest(IE, kFullTabHttpHeaderPage);
636 }
637
638 const wchar_t kFullTabHttpHeaderPageIFrame[] =
639     L"chrome_frame_http_header_host.html";
640
641 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderIFrame) {
642   SimpleBrowserTest(IE, kFullTabHttpHeaderPageIFrame);
643 }
644
645 const wchar_t kFullTabHttpHeaderPageFrameset[] =
646     L"chrome_frame_http_header_frameset.html";
647
648 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFHttpHeaderFrameSet) {
649   SimpleBrowserTest(IE, kFullTabHttpHeaderPageFrameset);
650 }
651
652 const wchar_t kVersionPage[] = L"version.html";
653
654 // Flaky, crbug.com/160497.
655 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_Version) {
656   VersionTest(IE, kVersionPage);
657 }
658
659 const wchar_t kEventListenerPage[] = L"event_listener.html";
660
661 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_EventListener) {
662   SimpleBrowserTest(IE, kEventListenerPage);
663 }
664
665 const wchar_t kPrivilegedApisPage[] = L"privileged_apis_host.html";
666
667 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PrivilegedApis) {
668   SimpleBrowserTest(IE, kPrivilegedApisPage);
669 }
670
671 const wchar_t kMetaTagPage[] = L"meta_tag.html";
672 // Flaky, crbug.com/160497.
673 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_MetaTag) {
674   SimpleBrowserTest(IE, kMetaTagPage);
675 }
676
677 // Times out: http://crbug.com/163728
678 const wchar_t kCFProtocolPage[] = L"cf_protocol.html";
679 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_CFProtocol) {
680   // Temporarily enable  gcf: protocol for this test.
681   SetConfigBool(kAllowUnsafeURLs, true);
682   SimpleBrowserTest(IE, kCFProtocolPage);
683   SetConfigBool(kAllowUnsafeURLs, false);
684 }
685
686 const wchar_t kPersistentCookieTest[] =
687     L"persistent_cookie_test_page.html";
688 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_PersistentCookieTest) {
689   SimpleBrowserTest(IE, kPersistentCookieTest);
690 }
691
692 const wchar_t kNavigateOutPage[] = L"navigate_out.html";
693 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_NavigateOut) {
694   SimpleBrowserTest(IE, kNavigateOutPage);
695 }
696
697 const wchar_t kReferrerMainTest[] = L"referrer_main.html";
698
699 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_ReferrerTest) {
700   SimpleBrowserTest(IE, kReferrerMainTest);
701 }
702
703 // Times out: http://crbug.com/163728
704 const wchar_t kSubFrameTestPage[] = L"full_tab_sub_frame_main.html";
705 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_SubFrame) {
706   SimpleBrowserTest(IE, kSubFrameTestPage);
707 }
708
709 const wchar_t kSubIFrameTestPage[] = L"full_tab_sub_iframe_main.html";
710 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_SubIFrame) {
711   SimpleBrowserTest(IE, kSubIFrameTestPage);
712 }
713
714 const wchar_t kXMLHttpRequestTestUrl[] =
715     L"xmlhttprequest_test.html";
716
717 // Flaky, crbug.com/160497.
718 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_XHRTest) {
719   SimpleBrowserTest(IE, kXMLHttpRequestTestUrl);
720 }
721
722 const wchar_t kInstallFlowTestUrl[] =
723     L"install_flow_test.html";
724
725 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_InstallFlowTest) {
726   if (base::win::GetVersion() < base::win::VERSION_VISTA) {
727     ScopedChromeFrameRegistrar::UnregisterAtPath(
728         GetChromeFrameBuildPath().value(),
729         chrome_frame_test::GetTestBedType());
730
731     ASSERT_TRUE(LaunchBrowser(IE, kInstallFlowTestUrl));
732
733     loop().RunFor(kChromeFrameLongNavigationTimeout);
734
735     ScopedChromeFrameRegistrar::RegisterAtPath(
736         GetChromeFrameBuildPath().value(),
737         chrome_frame_test::GetTestBedType());
738
739     ExpectAndHandlePostedResult();
740     loop().RunFor(kChromeFrameLongNavigationTimeout);
741
742     chrome_frame_test::CloseAllIEWindows();
743     ASSERT_EQ("OK", server_mock().posted_result());
744   }
745 }
746
747 const wchar_t kMultipleCFInstancesTestUrl[] =
748     L"multiple_cf_instances_main.html";
749
750 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_MultipleCFInstances) {
751   SimpleBrowserTest(IE, kMultipleCFInstancesTestUrl);
752 }
753
754 const wchar_t kXHRHeaderTestUrl[] =
755     L"xmlhttprequest_header_test.html";
756
757 // Marking as flaky since it occasionally times out. crbug.com/127395.
758 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_XHRHeaderTest) {
759   SimpleBrowserTest(IE, kXHRHeaderTestUrl);
760 }
761
762 const wchar_t kDeleteCookieTest[] =
763     L"fulltab_delete_cookie_test.html";
764
765 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_DeleteCookieTest) {
766   SimpleBrowserTest(IE, kDeleteCookieTest);
767 }
768
769 const wchar_t kAnchorUrlNavigate[] =
770     L"fulltab_anchor_url_navigate.html#chrome_frame";
771
772 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_AnchorUrlNavigateTest) {
773   SimpleBrowserTest(IE, kAnchorUrlNavigate);
774 }
775
776 // Test whether POST-ing a form from an mshtml page to a CF page will cause
777 // the request to get reissued.  It should not.
778 // https://code.google.com/p/chromium/issues/detail?id=143699
779 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_TestPostReissue) {
780   // The order of pages in this array is assumed to be mshtml, cf, script.
781   const wchar_t* kPages[] = {
782     L"full_tab_post_mshtml.html",
783     L"full_tab_post_target_cf.html",
784     L"chrome_frame_tester_helpers.js",
785   };
786
787   SimpleWebServerTest server(local_address_, 46664);
788   server.PopulateStaticFileListT<test_server::FileResponse>(kPages,
789       arraysize(kPages), GetCFTestFilePath());
790
791   ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str()));
792
793   loop().RunFor(kChromeFrameLongNavigationTimeout);
794
795   const test_server::Request* request = NULL;
796   server.FindRequest("/quit?OK", &request);
797   ASSERT_TRUE(request != NULL);
798   EXPECT_EQ("OK", request->arguments());
799
800   if (request->arguments().compare("OK") == 0) {
801     // Check how many requests we got for the cf page.  Also expect it to be
802     // a POST.
803     int requests = server.GetRequestCountForPage(kPages[1], "POST");
804     EXPECT_EQ(1, requests);
805   }
806 }
807
808 // Test whether following a link from an mshtml page to a CF page will cause
809 // multiple network requests.  It should not.
810 // Flaky, crbug.com/160497.
811 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_TestMultipleGet) {
812   // The order of pages in this array is assumed to be mshtml, cf, script.
813   const wchar_t* kPages[] = {
814     L"full_tab_get_mshtml.html",
815     L"full_tab_get_target_cf.html",
816     L"chrome_frame_tester_helpers.js",
817   };
818
819   SimpleWebServerTest server(local_address_, 46664);
820
821   server.PopulateStaticFileListT<test_server::FileResponse>(kPages,
822       arraysize(kPages), GetCFTestFilePath());
823
824   ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str()));
825
826   loop().RunFor(kChromeFrameVeryLongNavigationTimeout);
827
828   const test_server::Request* request = NULL;
829   server.FindRequest("/quit?OK", &request);
830   ASSERT_TRUE(request != NULL);
831   EXPECT_EQ("OK", request->arguments());
832
833   if (request->arguments().compare("OK") == 0) {
834     // Check how many requests we got for the cf page and check that it was
835     // a GET.
836     int requests = server.GetRequestCountForPage(kPages[1], "GET");
837     EXPECT_EQ(1, requests);
838   }
839 }
840
841 const wchar_t kSetCookieTest[] =
842     L"fulltab_set_cookie_test.html";
843
844 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_SetCookieTest) {
845   SimpleBrowserTest(IE, kSetCookieTest);
846 }
847
848 const wchar_t kXHRConditionalHeaderTestUrl[] =
849     L"xmlhttprequest_conditional_header_test.html";
850
851 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_XHRConditionalHeaderTest) {
852   SimpleBrowserTest(IE, kXHRConditionalHeaderTestUrl);
853 }
854
855 const wchar_t kWindowCloseTestUrl[] =
856     L"window_close.html";
857
858 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_WindowClose) {
859   SimpleBrowserTest(IE, kWindowCloseTestUrl);
860 }
861
862 std::string GetHeaderValue(const std::string& headers,
863                            const char* header_name) {
864   net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(),
865                                     "\r\n");
866   while (it.GetNext()) {
867     if (lstrcmpiA(it.name().c_str(), header_name) == 0) {
868       return it.values();
869     }
870   }
871   return "";
872 }
873
874 // Specialized implementation of test_server::FileResponse that supports
875 // adding the request's User-Agent header to the returned document.
876 // The class also supports $request_id$ which will be replaced with an
877 // id that's incremented each time the response is sent over a socket.
878 class UaTemplateFileResponse : public test_server::FileResponse {
879  public:
880   typedef test_server::FileResponse SuperClass;
881
882   UaTemplateFileResponse(const char* request_path,
883                          const base::FilePath& file_path)
884       : test_server::FileResponse(request_path, file_path), request_id_(0) {
885   }
886
887   virtual bool Matches(const test_server::Request& r) const {
888     bool ret = SuperClass::Matches(r);
889     if (ret)
890       ua_ = GetHeaderValue(r.headers(), "User-Agent");
891     return ret;
892   }
893
894   virtual size_t ContentLength() const {
895     const char kRequestIdTemplate[] = "$request_id$";
896     const char kUserAgentTemplate[] = "$UA$";
897
898     size_t length = SuperClass::ContentLength();
899     DCHECK(length);
900     content_.assign(reinterpret_cast<const char*>(file_->data()),
901                     file_->length());
902     size_t i = content_.find(kUserAgentTemplate);
903     if (i != std::string::npos)
904       content_.replace(i, arraysize(kUserAgentTemplate) - 1, ua_);
905     i = content_.find(kRequestIdTemplate);
906     if (i != std::string::npos) {
907       content_.replace(i, arraysize(kRequestIdTemplate) - 1,
908                        base::StringPrintf("%i", request_id_));
909     }
910     return content_.length();
911   }
912
913   virtual void WriteContents(net::StreamListenSocket* socket) const {
914     DCHECK(content_.length());
915     socket->Send(content_.c_str(), content_.length(), false);
916     request_id_++;
917   }
918
919  protected:
920   mutable std::string ua_;
921   mutable std::string content_;
922   mutable int request_id_;
923 };
924
925 // This test simulates a URL that on first request returns a document
926 // that should be rendered in mshtml, then pops up a sign-in page that
927 // after signing in, refreshes the original page that should then return
928 // a page that needs to be rendered in GCF.
929 //
930 // This test currently fails because GCF does not add the chromeframe header
931 // to requests that mshtml initiates via IInternetSession::CreateBinding.
932 TEST_F(ChromeFrameTestWithWebServer, DISABLED_FullTabModeIE_RefreshMshtmlTest) {
933   const wchar_t* kPages[] = {
934     L"mshtml_refresh_test.html",
935     L"mshtml_refresh_test_popup.html",
936   };
937
938   SimpleWebServerTest server(local_address_, 46664);
939   server.PopulateStaticFileListT<UaTemplateFileResponse>(kPages,
940       arraysize(kPages), GetCFTestFilePath());
941
942   ASSERT_TRUE(LaunchBrowser(IE, server.FormatHttpPath(kPages[0]).c_str()));
943
944   loop().RunFor(kChromeFrameLongNavigationTimeout);
945
946   test_server::SimpleWebServer* ws = server.web_server();
947   const test_server::ConnectionList& connections = ws->connections();
948   test_server::ConnectionList::const_iterator it = connections.begin();
949   int requests_for_first_page = 0;
950   for (; it != connections.end(); ++it) {
951     test_server::Connection* c = (*it);
952     const test_server::Request& r = c->request();
953     if (!r.path().empty() &&
954         ASCIIToWide(r.path().substr(1)).compare(kPages[0]) == 0) {
955       requests_for_first_page++;
956       std::string ua(GetHeaderValue(r.headers(), "User-Agent"));
957       EXPECT_NE(std::string::npos, ua.find("chromeframe"));
958     }
959   }
960   EXPECT_GT(requests_for_first_page, 1);
961 }
962
963 // See bug 36694 for details.  http://crbug.com/36694
964 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_TestDownloadFromForm) {
965   chrome_frame_test::MockWindowObserver win_observer_mock;
966   win_observer_mock.WatchWindow("File Download", "");
967   win_observer_mock.WatchWindow("View Downloads*", "");
968
969   // The content of our HTML test page.  This will be returned whenever
970   // we reply to a GET request.
971   static const char kHtml[] =
972       "<html><head>\n"
973       "<title>ChromeFrame Form Download Test</title>\n"
974       // To see how this test runs with only IE (no CF in the picture), comment
975       // out this meta tag.  The outcome of the test should be identical.
976       "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />\n"
977       "</head>\n"
978       "<script language=\"javascript\">\n"
979       "function SubmitForm() {\n"
980       "  var form = document.forms['myform'];\n"
981       "  form.action = document.location;\n"
982       "  form.submit();\n"
983       "  return true;\n"
984       "}\n"
985       "</script>\n"
986       "<body onload=\"SubmitForm();\">\n"
987       "<form method=\"post\" action=\"foo.html\" id=\"myform\">\n"
988       "  <input type=\"hidden\" name=\"Field1\" value=\"myvalue\" />\n"
989       "  <input type=\"button\" name=\"btn\" value=\"Test Download\" "
990           "onclick=\"return SubmitForm();\" id=\"Button1\"/>\n"
991       "</form></body></html>\n";
992
993   // The content of our HTML test page.  This will be returned whenever
994   // we reply to a POST request.
995   static const char kText[] =
996       "This is a text file (in case you were wondering).";
997
998   // This http response class will return an HTML document that contains
999   // a form whenever it receives a GET request.  Whenever it gets a POST
1000   // request, it will respond with a text file that needs to be downloaded
1001   // (content-disposition is "attachment").
1002   class CustomResponse : public test_server::ResponseForPath {
1003    public:
1004     explicit CustomResponse(const char* path)
1005       : test_server::ResponseForPath(path), is_post_(false),
1006         post_requests_(0), get_requests_(0) {
1007     }
1008
1009     virtual bool GetContentType(std::string* content_type) const {
1010       DCHECK(!is_post_);
1011       return false;
1012     }
1013
1014     virtual size_t ContentLength() const {
1015       DCHECK(!is_post_);
1016       return sizeof(kHtml) - 1;
1017     }
1018
1019     virtual bool GetCustomHeaders(std::string* headers) const {
1020       if (!is_post_)
1021         return false;
1022       *headers = base::StringPrintf(
1023           "HTTP/1.1 200 OK\r\n"
1024           "Content-Disposition: attachment;filename=\"test.txt\"\r\n"
1025           "Content-Type: application/text\r\n"
1026           "Connection: close\r\n"
1027           "Content-Length: %i\r\n\r\n", sizeof(kText) - 1);
1028       return true;
1029     }
1030
1031     virtual bool Matches(const test_server::Request& r) const {
1032       bool match = __super::Matches(r);
1033       if (match) {
1034         is_post_ = LowerCaseEqualsASCII(r.method().c_str(), "post");
1035       }
1036       return match;
1037     }
1038
1039     virtual void WriteContents(net::StreamListenSocket* socket) const {
1040       if (is_post_) {
1041         socket->Send(kText, sizeof(kText) - 1, false);
1042       } else {
1043         socket->Send(kHtml, sizeof(kHtml) - 1, false);
1044       }
1045     }
1046
1047     virtual void IncrementAccessCounter() {
1048       __super::IncrementAccessCounter();
1049       if (is_post_) {
1050         post_requests_++;
1051       } else {
1052         get_requests_++;
1053       }
1054     }
1055
1056     size_t get_request_count() const {
1057       return get_requests_;
1058     }
1059
1060     size_t post_request_count() const {
1061       return get_requests_;
1062     }
1063
1064    protected:
1065     mutable bool is_post_;
1066     size_t post_requests_;
1067     size_t get_requests_;
1068   };
1069
1070   EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
1071       .Times(testing::AtMost(1))
1072       .WillOnce(chrome_frame_test::DoCloseWindow());
1073
1074   EXPECT_CALL(win_observer_mock, OnWindowClose(_))
1075       .Times(testing::AtMost(1))
1076       .WillOnce(QUIT_LOOP(loop()));
1077
1078   SimpleWebServerTest server(local_address_, 46664);
1079   CustomResponse* response = new CustomResponse("/form.html");
1080   server.web_server()->AddResponse(response);
1081
1082   std::wstring url(server.FormatHttpPath(L"form.html"));
1083
1084   ASSERT_TRUE(LaunchBrowser(IE, url.c_str()));
1085   loop().RunFor(kChromeFrameLongNavigationTimeout);
1086
1087   EXPECT_EQ(1, response->get_request_count());
1088   EXPECT_EQ(1, response->post_request_count());
1089 }
1090
1091 // This test loads a large page and ensures that the full page contents are
1092 // actually loaded via a self-validating HTML page. This is done due to a bug
1093 // whereby the middle of the response stream would sometimes be truncated when
1094 // loading a CF document. See http://crbug.com/178421 for details.
1095 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_LargePageLoad) {
1096   const wchar_t kLargePageLoadPage[] =
1097       L"chrome_frame_large_page.html";
1098
1099   SimpleBrowserTest(IE, kLargePageLoadPage);
1100 }