Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Side by Side Diff: chrome_frame/test/chrome_frame_unittests.cc

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 #include <windows.h>
5 #include <stdarg.h>
6
7 // IShellWindows includes. Unfortunately we can't keep these in
8 // alphabetic order since exdisp will bark if some interfaces aren't fully
9 // defined.
10 #include <mshtml.h>
11 #include <exdisp.h>
12
13 #include "base/basictypes.h"
14 #include "base/file_version_info.h"
15 #include "base/file_util.h"
16 #include "base/scoped_bstr_win.h"
17 #include "base/scoped_comptr_win.h"
18 #include "base/scoped_variant_win.h"
19 #include "base/sys_info.h"
20 #include "gmock/gmock.h"
21 #include "net/url_request/url_request_unittest.h"
22 #include "chrome_frame/test/chrome_frame_unittests.h"
23 #include "chrome_frame/chrome_frame_automation.h"
24 #include "chrome_frame/chrome_frame_delegate.h"
25 #include "chrome_frame/test/chrome_frame_test_utils.h"
26 #include "chrome_frame/test/helper_gmock.h"
27 #include "chrome_frame/test_utils.h"
28 #include "chrome_frame/utils.h"
29 #include "chrome_frame/vectored_handler-impl.h"
30 #include "chrome/installer/util/install_util.h"
31 #include "chrome/installer/util/helper.h"
32
33 const wchar_t kDocRoot[] = L"chrome_frame\\test\\data";
34 const int kLongWaitTimeout = 60 * 1000;
35 const int kShortWaitTimeout = 25 * 1000;
36
37 _ATL_FUNC_INFO WebBrowserEventSink::kNavigateErrorInfo = {
38 CC_STDCALL, VT_EMPTY, 5, {
39 VT_DISPATCH,
40 VT_VARIANT | VT_BYREF,
41 VT_VARIANT | VT_BYREF,
42 VT_VARIANT | VT_BYREF,
43 VT_BOOL | VT_BYREF,
44 }
45 };
46
47 _ATL_FUNC_INFO WebBrowserEventSink::kNavigateComplete2Info = {
48 CC_STDCALL, VT_EMPTY, 2, {
49 VT_DISPATCH,
50 VT_VARIANT | VT_BYREF
51 }
52 };
53
54 _ATL_FUNC_INFO WebBrowserEventSink::kBeforeNavigate2Info = {
55 CC_STDCALL, VT_EMPTY, 7, {
56 VT_DISPATCH,
57 VT_VARIANT | VT_BYREF,
58 VT_VARIANT | VT_BYREF,
59 VT_VARIANT | VT_BYREF,
60 VT_VARIANT | VT_BYREF,
61 VT_VARIANT | VT_BYREF,
62 VT_BOOL | VT_BYREF
63 }
64 };
65
66
67
68 void ChromeFrameTestWithWebServer::SetUp() {
69 server_.SetUp();
70 results_dir_ = server_.GetDataDir();
71 file_util::AppendToPath(&results_dir_, L"dump");
72 }
73
74 void ChromeFrameTestWithWebServer::TearDown() {
75 CloseBrowser();
76
77 // Web browsers tend to relaunch themselves in other processes, meaning the
78 // KillProcess stuff above might not have actually cleaned up all our browser
79 // instances, so make really sure browsers are dead.
80 base::KillProcesses(chrome_frame_test::kIEImageName, 0, NULL);
81 base::KillProcesses(chrome_frame_test::kIEBrokerImageName, 0, NULL);
82 base::KillProcesses(chrome_frame_test::kFirefoxImageName, 0, NULL);
83 base::KillProcesses(chrome_frame_test::kSafariImageName, 0, NULL);
84 base::KillProcesses(chrome_frame_test::kChromeImageName, 0, NULL);
85
86 server_.TearDown();
87 }
88
89 bool ChromeFrameTestWithWebServer::LaunchBrowser(BrowserKind browser,
90 const wchar_t* page) {
91 std::wstring url = UTF8ToWide(server_.Resolve(page).spec());
92 browser_ = browser;
93 if (browser == IE) {
94 browser_handle_.Set(chrome_frame_test::LaunchIE(url));
95 } else if (browser == FIREFOX) {
96 browser_handle_.Set(chrome_frame_test::LaunchFirefox(url));
97 } else if (browser == OPERA) {
98 browser_handle_.Set(chrome_frame_test::LaunchOpera(url));
99 } else if (browser == SAFARI) {
100 browser_handle_.Set(chrome_frame_test::LaunchSafari(url));
101 } else if (browser == CHROME) {
102 browser_handle_.Set(chrome_frame_test::LaunchChrome(url));
103 } else {
104 NOTREACHED();
105 }
106
107 return browser_handle_.IsValid();
108 }
109
110 void ChromeFrameTestWithWebServer::CloseBrowser() {
111 if (!browser_handle_.IsValid())
112 return;
113
114 int attempts = 0;
115 if (browser_ == IE) {
116 attempts = chrome_frame_test::CloseAllIEWindows();
117 } else {
118 attempts = chrome_frame_test::CloseVisibleWindowsOnAllThreads(
119 browser_handle_);
120 }
121
122 if (attempts > 0) {
123 DWORD wait = ::WaitForSingleObject(browser_handle_, 20000);
124 if (wait == WAIT_OBJECT_0) {
125 browser_handle_.Close();
126 } else {
127 DLOG(ERROR) << "WaitForSingleObject returned " << wait;
128 }
129 } else {
130 DLOG(ERROR) << "No attempts to close browser windows";
131 }
132
133 if (browser_handle_.IsValid()) {
134 DWORD exit_code = 0;
135 if (!::GetExitCodeProcess(browser_handle_, &exit_code) ||
136 exit_code == STILL_ACTIVE) {
137 DLOG(ERROR) << L"Forcefully killing browser process. Exit:" << exit_code;
138 base::KillProcess(browser_handle_, 0, true);
139 }
140 browser_handle_.Close();
141 }
142 }
143
144 bool ChromeFrameTestWithWebServer::BringBrowserToTop() {
145 return chrome_frame_test::EnsureProcessInForeground(GetProcessId(
146 browser_handle_));
147 }
148
149 bool ChromeFrameTestWithWebServer::WaitForTestToComplete(int milliseconds) {
150 return server_.WaitToFinish(milliseconds);
151 }
152
153 bool ChromeFrameTestWithWebServer::WaitForOnLoad(int milliseconds) {
154 DWORD start = ::GetTickCount();
155 std::string data;
156 while (!ReadResultFile(L"OnLoadEvent", &data) || data.length() == 0) {
157 DWORD now = ::GetTickCount();
158 if (start > now) {
159 // Very simple check for overflow. In that case we just restart the
160 // wait.
161 start = now;
162 } else if (static_cast<int>(now - start) > milliseconds) {
163 break;
164 }
165 Sleep(100);
166 }
167
168 return data.compare("loaded") == 0;
169 }
170
171 bool ChromeFrameTestWithWebServer::ReadResultFile(const std::wstring& file_name,
172 std::string* data) {
173 std::wstring full_path = results_dir_;
174 file_util::AppendToPath(&full_path, file_name);
175 return file_util::ReadFileToString(full_path, data);
176 }
177
178 bool ChromeFrameTestWithWebServer::CheckResultFile(
179 const std::wstring& file_name, const std::string& expected_result) {
180 std::string data;
181 bool ret = ReadResultFile(file_name, &data);
182 if (ret)
183 ret = (data == expected_result);
184
185 if (!ret) {
186 DLOG(ERROR) << "Error text: " << (data.empty() ? "<empty>" : data.c_str());
187 }
188
189 return ret;
190 }
191
192 void ChromeFrameTestWithWebServer::SimpleBrowserTest(BrowserKind browser,
193 const wchar_t* page, const wchar_t* result_file_to_check) {
194 EXPECT_TRUE(LaunchBrowser(browser, page));
195 ASSERT_TRUE(WaitForTestToComplete(kLongWaitTimeout));
196 ASSERT_TRUE(CheckResultFile(result_file_to_check, "OK"));
197 }
198
199 void ChromeFrameTestWithWebServer::OptionalBrowserTest(BrowserKind browser,
200 const wchar_t* page, const wchar_t* result_file_to_check) {
201 if (!LaunchBrowser(browser, page)) {
202 DLOG(ERROR) << "Failed to launch browser " << ToString(browser);
203 } else {
204 ASSERT_TRUE(WaitForTestToComplete(kLongWaitTimeout));
205 ASSERT_TRUE(CheckResultFile(result_file_to_check, "OK"));
206 }
207 }
208
209 void ChromeFrameTestWithWebServer::VersionTest(BrowserKind browser,
210 const wchar_t* page, const wchar_t* result_file_to_check) {
211 std::wstring plugin_path;
212 PathService::Get(base::DIR_MODULE, &plugin_path);
213 file_util::AppendToPath(&plugin_path, L"servers/npchrome_tab.dll");
214
215 static FileVersionInfo* version_info =
216 FileVersionInfo::CreateFileVersionInfo(plugin_path);
217
218 std::wstring version;
219 if (version_info)
220 version = version_info->product_version();
221
222 // If we can't find the npchrome_tab.dll in the src tree, we turn to
223 // the directory where chrome is installed.
224 if (!version_info) {
225 installer::Version* ver_system = InstallUtil::GetChromeVersion(true);
226 installer::Version* ver_user = InstallUtil::GetChromeVersion(false);
227 ASSERT_TRUE(ver_system || ver_user);
228
229 bool system_install = ver_system ? true : false;
230 std::wstring npchrome_path(installer::GetChromeInstallPath(system_install));
231 file_util::AppendToPath(&npchrome_path,
232 ver_system ? ver_system->GetString() : ver_user->GetString());
233 file_util::AppendToPath(&npchrome_path, L"npchrome_tab.dll");
234 version_info = FileVersionInfo::CreateFileVersionInfo(npchrome_path);
235 if (version_info)
236 version = version_info->product_version();
237 }
238
239 EXPECT_TRUE(version_info);
240 EXPECT_FALSE(version.empty());
241 EXPECT_TRUE(LaunchBrowser(browser, page));
242 ASSERT_TRUE(WaitForTestToComplete(kLongWaitTimeout));
243 ASSERT_TRUE(CheckResultFile(result_file_to_check, WideToUTF8(version)));
244 }
245
246 const wchar_t kPostMessageBasicPage[] = L"files/postmessage_basic_host.html";
247
248 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PostMessageBasic) {
249 SimpleBrowserTest(IE, kPostMessageBasicPage, L"PostMessage");
250 }
251
252 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_PostMessageBasic) {
253 SimpleBrowserTest(FIREFOX, kPostMessageBasicPage, L"PostMessage");
254 }
255
256 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_PostMessageBasic) {
257 OptionalBrowserTest(OPERA, kPostMessageBasicPage, L"PostMessage");
258 }
259
260 TEST_F(ChromeFrameTestWithWebServer, FullTabIE_MIMEFilterBasic) {
261 const wchar_t kMIMEFilterBasicPage[] =
262 L"files/chrome_frame_mime_filter_test.html";
263
264 SimpleBrowserTest(IE, kMIMEFilterBasicPage, L"MIMEFilter");
265 }
266
267 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_Resize) {
268 SimpleBrowserTest(IE, L"files/chrome_frame_resize.html", L"Resize");
269 }
270
271 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_Resize) {
272 SimpleBrowserTest(FIREFOX, L"files/chrome_frame_resize.html", L"Resize");
273 }
274
275 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_Resize) {
276 OptionalBrowserTest(OPERA, L"files/chrome_frame_resize.html", L"Resize");
277 }
278
279 const wchar_t kNavigateURLAbsolutePage[] =
280 L"files/navigateurl_absolute_host.html";
281
282 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_NavigateURLAbsolute) {
283 SimpleBrowserTest(IE, kNavigateURLAbsolutePage, L"NavigateURL");
284 }
285
286 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_NavigateURLAbsolute) {
287 SimpleBrowserTest(FIREFOX, kNavigateURLAbsolutePage, L"NavigateURL");
288 }
289
290 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_NavigateURLAbsolute) {
291 OptionalBrowserTest(OPERA, kNavigateURLAbsolutePage, L"NavigateURL");
292 }
293
294 const wchar_t kNavigateURLRelativePage[] =
295 L"files/navigateurl_relative_host.html";
296
297 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_NavigateURLRelative) {
298 SimpleBrowserTest(IE, kNavigateURLRelativePage, L"NavigateURL");
299 }
300
301 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_NavigateURLRelative) {
302 SimpleBrowserTest(FIREFOX, kNavigateURLRelativePage, L"NavigateURL");
303 }
304
305 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_NavigateURLRelative) {
306 OptionalBrowserTest(OPERA, kNavigateURLRelativePage, L"NavigateURL");
307 }
308
309 const wchar_t kNavigateSimpleObjectFocus[] = L"files/simple_object_focus.html";
310
311 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_ObjectFocus) {
312 SimpleBrowserTest(FIREFOX, kNavigateSimpleObjectFocus, L"ObjectFocus");
313 }
314
315 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_ObjectFocus) {
316 SimpleBrowserTest(IE, kNavigateSimpleObjectFocus, L"ObjectFocus");
317 }
318
319 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_ObjectFocus) {
320 if (!LaunchBrowser(OPERA, kNavigateSimpleObjectFocus)) {
321 DLOG(ERROR) << "Failed to launch browser " << ToString(OPERA);
322 } else {
323 ASSERT_TRUE(WaitForOnLoad(kLongWaitTimeout));
324 BringBrowserToTop();
325 // Tab through a couple of times. Once should be enough in theory
326 // but in practice activating the browser can take a few milliseconds more.
327 bool ok;
328 for (int i = 0;
329 i < 5 && (ok = CheckResultFile(L"ObjectFocus", "OK")) == false;
330 ++i) {
331 Sleep(300);
332 chrome_frame_test::SendMnemonic(VK_TAB, false, false, false);
333 }
334 ASSERT_TRUE(ok);
335 }
336 }
337
338 const wchar_t kiframeBasicPage[] = L"files/iframe_basic_host.html";
339
340 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_iframeBasic) {
341 SimpleBrowserTest(IE, kiframeBasicPage, L"PostMessage");
342 }
343
344 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_iframeBasic) {
345 SimpleBrowserTest(FIREFOX, kiframeBasicPage, L"PostMessage");
346 }
347
348 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_iframeBasic) {
349 OptionalBrowserTest(OPERA, kiframeBasicPage, L"PostMessage");
350 }
351
352 const wchar_t kSrcPropertyTestPage[] = L"files/src_property_host.html";
353
354 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_SrcProperty) {
355 SimpleBrowserTest(IE, kSrcPropertyTestPage, L"SrcProperty");
356 }
357
358 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_SrcProperty) {
359 SimpleBrowserTest(FIREFOX, kSrcPropertyTestPage, L"SrcProperty");
360 }
361
362 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_SrcProperty) {
363 OptionalBrowserTest(OPERA, kSrcPropertyTestPage, L"SrcProperty");
364 }
365
366 const wchar_t kCFInstanceBasicTestPage[] = L"files/CFInstance_basic_host.html";
367
368 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceBasic) {
369 SimpleBrowserTest(IE, kCFInstanceBasicTestPage, L"CFInstanceBasic");
370 }
371
372 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceBasic) {
373 SimpleBrowserTest(FIREFOX, kCFInstanceBasicTestPage, L"CFInstanceBasic");
374 }
375
376 const wchar_t kCFISingletonPage[] = L"files/CFInstance_singleton_host.html";
377
378 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceSingleton) {
379 SimpleBrowserTest(IE, kCFISingletonPage, L"CFInstanceSingleton");
380 }
381
382 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceSingleton) {
383 SimpleBrowserTest(FIREFOX, kCFISingletonPage, L"CFInstanceSingleton");
384 }
385
386 const wchar_t kCFIDelayPage[] = L"files/CFInstance_delay_host.html";
387
388 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceDelay) {
389 SimpleBrowserTest(IE, kCFIDelayPage, L"CFInstanceDelay");
390 }
391
392 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeFF_CFInstanceDelay) {
393 SimpleBrowserTest(FIREFOX, kCFIDelayPage, L"CFInstanceDelay");
394 }
395
396 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeOpera_CFInstanceDelay) {
397 OptionalBrowserTest(OPERA, kCFIDelayPage, L"CFInstanceDelay");
398 }
399
400 const wchar_t kCFIFallbackPage[] = L"files/CFInstance_fallback_host.html";
401
402 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceFallback) {
403 SimpleBrowserTest(IE, kCFIFallbackPage, L"CFInstanceFallback");
404 }
405
406 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceFallback) {
407 SimpleBrowserTest(FIREFOX, kCFIFallbackPage, L"CFInstanceFallback");
408 }
409
410 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceFallback) {
411 OptionalBrowserTest(OPERA, kCFIFallbackPage, L"CFInstanceFallback");
412 }
413
414 const wchar_t kCFINoSrcPage[] = L"files/CFInstance_no_src_host.html";
415
416 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceNoSrc) {
417 SimpleBrowserTest(IE, kCFINoSrcPage, L"CFInstanceNoSrc");
418 }
419
420 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceNoSrc) {
421 SimpleBrowserTest(FIREFOX, kCFINoSrcPage, L"CFInstanceNoSrc");
422 }
423
424 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceNoSrc) {
425 OptionalBrowserTest(OPERA, kCFINoSrcPage, L"CFInstanceNoSrc");
426 }
427
428 const wchar_t kCFIIfrOnLoadPage[] = L"files/CFInstance_iframe_onload_host.html";
429
430 // disabled since it's unlikely that we care about this case
431 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeIE_CFInstanceIfrOnLoad) {
432 SimpleBrowserTest(IE, kCFIIfrOnLoadPage, L"CFInstanceIfrOnLoad");
433 }
434
435 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceIfrOnLoad) {
436 SimpleBrowserTest(FIREFOX, kCFIIfrOnLoadPage, L"CFInstanceIfrOnLoad");
437 }
438
439 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceIfrOnLoad) {
440 OptionalBrowserTest(OPERA, kCFIIfrOnLoadPage, L"CFInstanceIfrOnLoad");
441 }
442
443 const wchar_t kCFIZeroSizePage[] = L"files/CFInstance_zero_size_host.html";
444
445 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceZeroSize) {
446 SimpleBrowserTest(IE, kCFIZeroSizePage, L"CFInstanceZeroSize");
447 }
448
449 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceZeroSize) {
450 SimpleBrowserTest(FIREFOX, kCFIZeroSizePage, L"CFInstanceZeroSize");
451 }
452
453 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceZeroSize) {
454 OptionalBrowserTest(OPERA, kCFIZeroSizePage, L"CFInstanceZeroSize");
455 }
456
457 const wchar_t kCFIIfrPostPage[] = L"files/CFInstance_iframe_post_host.html";
458
459 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceIfrPost) {
460 SimpleBrowserTest(IE, kCFIIfrPostPage, L"CFInstanceIfrPost");
461 }
462
463 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceIfrPost) {
464 SimpleBrowserTest(FIREFOX, kCFIIfrPostPage, L"CFInstanceIfrPost");
465 }
466
467 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceIfrPost) {
468 OptionalBrowserTest(CHROME, kCFIIfrPostPage, L"CFInstanceIfrPost");
469 }
470
471 TEST_F(ChromeFrameTestWithWebServer, WidgetModeSafari_CFInstanceIfrPost) {
472 OptionalBrowserTest(SAFARI, kCFIIfrPostPage, L"CFInstanceIfrPost");
473 }
474
475 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_CFInstanceIfrPost) {
476 OptionalBrowserTest(OPERA, kCFIIfrPostPage, L"CFInstanceIfrPost");
477 }
478
479 const wchar_t kCFIPostPage[] = L"files/CFInstance_post_host.html";
480
481 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstancePost) {
482 SimpleBrowserTest(IE, kCFIPostPage, L"CFInstancePost");
483 }
484
485 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstancePost) {
486 SimpleBrowserTest(FIREFOX, kCFIPostPage, L"CFInstancePost");
487 }
488
489 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstancePost) {
490 OptionalBrowserTest(CHROME, kCFIPostPage, L"CFInstancePost");
491 }
492
493 TEST_F(ChromeFrameTestWithWebServer, WidgetModeSafari_CFInstancePost) {
494 OptionalBrowserTest(SAFARI, kCFIPostPage, L"CFInstancePost");
495 }
496
497 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeOpera_CFInstancePost) {
498 OptionalBrowserTest(OPERA, kCFIPostPage, L"CFInstancePost");
499 }
500
501 const wchar_t kCFIRPCPage[] = L"files/CFInstance_rpc_host.html";
502
503 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPC) {
504 SimpleBrowserTest(IE, kCFIRPCPage, L"CFInstanceRPC");
505 }
506
507 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceRPC) {
508 SimpleBrowserTest(FIREFOX, kCFIRPCPage, L"CFInstanceRPC");
509 }
510
511 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPC) {
512 OptionalBrowserTest(CHROME, kCFIRPCPage, L"CFInstanceRPC");
513 }
514
515 TEST_F(ChromeFrameTestWithWebServer, WidgetModeSafari_CFInstanceRPC) {
516 OptionalBrowserTest(SAFARI, kCFIRPCPage, L"CFInstanceRPC");
517 }
518
519 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeOpera_CFInstanceRPC) {
520 OptionalBrowserTest(OPERA, kCFIRPCPage, L"CFInstanceRPC");
521 }
522
523 const wchar_t kCFIRPCInternalPage[] =
524 L"files/CFInstance_rpc_internal_host.html";
525
526 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceRPCInternal) {
527 SimpleBrowserTest(IE, kCFIRPCInternalPage, L"CFInstanceRPCInternal");
528 }
529
530 // Disabled: http://b/issue?id=2050201
531 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeFF_CFInstanceRPCInternal ) {
532 SimpleBrowserTest(FIREFOX, kCFIRPCInternalPage, L"CFInstanceRPCInternal");
533 }
534
535 TEST_F(ChromeFrameTestWithWebServer, WidgetModeChrome_CFInstanceRPCInternal) {
536 OptionalBrowserTest(CHROME, kCFIRPCInternalPage, L"CFInstanceRPCInternal");
537 }
538
539 TEST_F(ChromeFrameTestWithWebServer, WidgetModeSafari_CFInstanceRPCInternal) {
540 OptionalBrowserTest(SAFARI, kCFIRPCInternalPage, L"CFInstanceRPCInternal");
541 }
542
543 const wchar_t kCFIDefaultCtorPage[] =
544 L"files/CFInstance_default_ctor_host.html";
545
546 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_CFInstanceDefaultCtor) {
547 SimpleBrowserTest(IE, kCFIDefaultCtorPage, L"CFInstanceDefaultCtor");
548 }
549
550 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_CFInstanceDefaultCtor) {
551 SimpleBrowserTest(FIREFOX, kCFIDefaultCtorPage, L"CFInstanceDefaultCtor");
552 }
553
554 // Class that mocks external call from VectoredHandlerT for testing purposes.
555 class EMock : public VEHTraitsBase {
556 public:
557 static inline bool WriteDump(EXCEPTION_POINTERS* p) {
558 g_dump_made = true;
559 return true;
560 }
561
562 static inline void* Register(PVECTORED_EXCEPTION_HANDLER func,
563 const void* module_start,
564 const void* module_end) {
565 VEHTraitsBase::SetModule(module_start, module_end);
566 // Return some arbitrary number, expecting to get the same on Unregister()
567 return reinterpret_cast<void*>(4);
568 }
569
570 static inline ULONG Unregister(void* handle) {
571 EXPECT_EQ(handle, reinterpret_cast<void*>(4));
572 return 1;
573 }
574
575 static inline WORD RtlCaptureStackBackTrace(DWORD FramesToSkip,
576 DWORD FramesToCapture, void** BackTrace, DWORD* BackTraceHash) {
577 EXPECT_EQ(2, FramesToSkip);
578 EXPECT_LE(FramesToSkip + FramesToCapture,
579 VectoredHandlerBase::max_back_trace);
580 memcpy(BackTrace, g_stack, g_stack_entries * sizeof(BackTrace[0]));
581 return g_stack_entries;
582 }
583
584 static inline EXCEPTION_REGISTRATION_RECORD* RtlpGetExceptionList() {
585 return g_seh_chain;
586 }
587
588 // Test helpers
589
590 // Create fake SEH chain of random filters - with and without our module.
591 static void SetHaveSEHFilter() {
592 SetSEHChain(reinterpret_cast<const char*>(g_module_start) - 0x1000,
593 reinterpret_cast<const char*>(g_module_start) + 0x1000,
594 reinterpret_cast<const char*>(g_module_end) + 0x7127,
595 NULL);
596 }
597
598 static void SetNoSEHFilter() {
599 SetSEHChain(reinterpret_cast<const char*>(g_module_start) - 0x1000,
600 reinterpret_cast<const char*>(g_module_end) + 0x7127,
601 NULL);
602 }
603
604 // Create fake stack - with and without our module.
605 static void SetOnStack() {
606 SetStack(reinterpret_cast<const char*>(g_module_start) - 0x11283,
607 reinterpret_cast<const char*>(g_module_start) - 0x278361,
608 reinterpret_cast<const char*>(g_module_start) + 0x9171,
609 reinterpret_cast<const char*>(g_module_end) + 1231,
610 NULL);
611 }
612
613 static void SetNotOnStack() {
614 SetStack(reinterpret_cast<const char*>(g_module_start) - 0x11283,
615 reinterpret_cast<const char*>(g_module_start) - 0x278361,
616 reinterpret_cast<const char*>(g_module_end) + 1231,
617 NULL);
618 }
619
620 // Populate stack array
621 static void SetStack(const void* p, ...) {
622 va_list vl;
623 va_start(vl, p);
624 g_stack_entries = 0;
625 for (; p; ++g_stack_entries) {
626 CHECK(g_stack_entries < arraysize(g_stack));
627 g_stack[g_stack_entries] = p;
628 p = va_arg(vl, const void*);
629 }
630 }
631
632 static void SetSEHChain(const void* p, ...) {
633 va_list vl;
634 va_start(vl, p);
635 int i = 0;
636 for (; p; ++i) {
637 CHECK(i + 1 < arraysize(g_seh_chain));
638 g_seh_chain[i].Handler = const_cast<void*>(p);
639 g_seh_chain[i].Next = &g_seh_chain[i + 1];
640 p = va_arg(vl, const void*);
641 }
642
643 g_seh_chain[i].Next = EXCEPTION_CHAIN_END;
644 }
645
646 static EXCEPTION_REGISTRATION_RECORD g_seh_chain[25];
647 static const void* g_stack[VectoredHandlerBase::max_back_trace];
648 static WORD g_stack_entries;
649 static bool g_dump_made;
650 };
651
652 EXCEPTION_REGISTRATION_RECORD EMock::g_seh_chain[25];
653 const void* EMock::g_stack[VectoredHandlerBase::max_back_trace];
654 WORD EMock::g_stack_entries;
655 bool EMock::g_dump_made;
656
657 typedef VectoredHandlerT<EMock> VectoredHandlerMock;
658
659 class ExPtrsHelper : public _EXCEPTION_POINTERS {
660 public:
661 ExPtrsHelper() {
662 ExceptionRecord = &er_;
663 ContextRecord = &ctx_;
664 ZeroMemory(&er_, sizeof(er_));
665 ZeroMemory(&ctx_, sizeof(ctx_));
666 }
667
668 void Set(DWORD code, void* address, DWORD flags) {
669 er_.ExceptionCode = code;
670 er_.ExceptionAddress = address;
671 er_.ExceptionFlags = flags;
672 }
673
674 EXCEPTION_RECORD er_;
675 CONTEXT ctx_;
676 };
677
678
679 TEST(ChromeFrame, ExceptionReport) {
680 char* s = reinterpret_cast<char*>(0x30000000);
681 char* e = s + 0x10000;
682 void* handler = VectoredHandlerMock::Register(s, e);
683 char* our_code = s + 0x1111;
684 char* not_our_code = s - 0x5555;
685 char* not_our_code2 = e + 0x5555;
686
687 ExPtrsHelper ex;
688 // Exception in our code, but we have SEH filter
689 ex.Set(STATUS_ACCESS_VIOLATION, our_code, 0);
690 EMock::SetHaveSEHFilter();
691 EMock::SetOnStack();
692 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex));
693 EXPECT_EQ(1, VectoredHandlerMock::g_exceptions_seen);
694 EXPECT_FALSE(EMock::g_dump_made);
695
696 // RPC_E_DISCONNECTED (0x80010108) is "The object invoked has disconnected
697 // from its clients", shall not be caught since it's a warning only.
698 ex.Set(RPC_E_DISCONNECTED, our_code, 0);
699 EMock::SetHaveSEHFilter();
700 EMock::SetOnStack();
701 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex));
702 EXPECT_EQ(1, VectoredHandlerMock::g_exceptions_seen);
703 EXPECT_FALSE(EMock::g_dump_made);
704
705
706 // Exception, not in our code, we do not have SEH and we are not in stack.
707 ex.Set(STATUS_INTEGER_DIVIDE_BY_ZERO, not_our_code, 0);
708 EMock::SetNoSEHFilter();
709 EMock::SetNotOnStack();
710 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex));
711 EXPECT_EQ(2, VectoredHandlerMock::g_exceptions_seen);
712 EXPECT_FALSE(EMock::g_dump_made);
713
714 // Exception, not in our code, no SEH, but we are on the stack.
715 ex.Set(STATUS_INTEGER_DIVIDE_BY_ZERO, not_our_code2, 0);
716 EMock::SetNoSEHFilter();
717 EMock::SetOnStack();
718 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex));
719 EXPECT_EQ(3, VectoredHandlerMock::g_exceptions_seen);
720 EXPECT_TRUE(EMock::g_dump_made);
721 EMock::g_dump_made = false;
722
723
724 // Exception, in our code, no SEH, not on stack (assume FPO screwed us)
725 ex.Set(STATUS_INTEGER_DIVIDE_BY_ZERO, our_code, 0);
726 EMock::SetNoSEHFilter();
727 EMock::SetNotOnStack();
728 EXPECT_EQ(ExceptionContinueSearch, VectoredHandlerMock::VectoredHandler(&ex));
729 EXPECT_EQ(4, VectoredHandlerMock::g_exceptions_seen);
730 EXPECT_TRUE(EMock::g_dump_made);
731 EMock::g_dump_made = false;
732
733 VectoredHandlerMock::Unregister();
734 }
735
736 const wchar_t kInitializeHiddenPage[] = L"files/initialize_hidden.html";
737
738 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_InitializeHidden) {
739 SimpleBrowserTest(IE, kInitializeHiddenPage, L"InitializeHidden");
740 }
741
742 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_InitializeHidden) {
743 SimpleBrowserTest(FIREFOX, kInitializeHiddenPage, L"InitializeHidden");
744 }
745
746 // Disabled due to a problem with Opera.
747 // http://b/issue?id=1708275
748 TEST_F(ChromeFrameTestWithWebServer, DISABLED_WidgetModeOpera_InitializeHidden) {
749 OptionalBrowserTest(OPERA, kInitializeHiddenPage, L"InitializeHidden");
750 }
751
752 const wchar_t kInHeadPage[] = L"files/in_head.html";
753
754 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_InHead) {
755 SimpleBrowserTest(FIREFOX, kInHeadPage, L"InHead");
756 }
757
758 const wchar_t kVersionPage[] = L"files/version.html";
759
760 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_Version) {
761 VersionTest(IE, kVersionPage, L"version");
762 }
763
764 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_Version) {
765 VersionTest(FIREFOX, kVersionPage, L"version");
766 }
767
768 const wchar_t kEventListenerPage[] = L"files/event_listener.html";
769
770 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_EventListener) {
771 SimpleBrowserTest(IE, kEventListenerPage, L"EventListener");
772 }
773
774 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_EventListener) {
775 SimpleBrowserTest(FIREFOX, kEventListenerPage, L"EventListener");
776 }
777
778 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_EventListener) {
779 OptionalBrowserTest(OPERA, kEventListenerPage, L"EventListener");
780 }
781
782 const wchar_t kPrivilegedApisPage[] = L"files/privileged_apis_host.html";
783
784 TEST_F(ChromeFrameTestWithWebServer, WidgetModeIE_PrivilegedApis) {
785 SimpleBrowserTest(IE, kPrivilegedApisPage, L"PrivilegedApis");
786 }
787
788 TEST_F(ChromeFrameTestWithWebServer, WidgetModeFF_PrivilegedApis) {
789 SimpleBrowserTest(FIREFOX, kPrivilegedApisPage, L"PrivilegedApis");
790 }
791
792 TEST_F(ChromeFrameTestWithWebServer, WidgetModeOpera_PrivilegedApis) {
793 OptionalBrowserTest(OPERA, kPrivilegedApisPage, L"PrivilegedApis");
794 }
795
796 class ChromeFrameTestEnvironment: public testing::Environment {
797 public:
798 ~ChromeFrameTestEnvironment() {
799 }
800
801 void SetUp() {
802 ScopedChromeFrameRegistrar::RegisterDefaults();
803 }
804
805 void TearDown() {
806 }
807 };
808
809 ::testing::Environment* const chrome_frame_env =
810 ::testing::AddGlobalTestEnvironment(new ChromeFrameTestEnvironment);
811
812 // TODO(stoyan): - Move everything below in separate file(s).
813 struct LaunchDelegateMock : public ProxyFactory::LaunchDelegate {
814 MOCK_METHOD2(LaunchComplete, void(ChromeFrameAutomationProxy*,
815 AutomationLaunchResult));
816 };
817
818 TEST(ProxyFactoryTest, CreateDestroy) {
819 ProxyFactory f;
820 LaunchDelegateMock d;
821 EXPECT_CALL(d, LaunchComplete(testing::NotNull(), testing::_)).Times(1);
822 void* id = f.GetAutomationServer(0, L"Adam.N.Epilinter", L"", false, &d);
823 f.ReleaseAutomationServer(id);
824 }
825
826 TEST(ProxyFactoryTest, CreateSameProfile) {
827 ProxyFactory f;
828 LaunchDelegateMock d;
829 EXPECT_CALL(d, LaunchComplete(testing::NotNull(), testing::_)).Times(2);
830 void* i1 = f.GetAutomationServer(0, L"Dr. Gratiano Forbeson", L"", false, &d);
831 void* i2 = f.GetAutomationServer(0, L"Dr. Gratiano Forbeson", L"", false, &d);
832 EXPECT_EQ(i1, i2);
833 f.ReleaseAutomationServer(i2);
834 f.ReleaseAutomationServer(i1);
835 }
836
837 TEST(ProxyFactoryTest, CreateDifferentProfiles) {
838 ProxyFactory f;
839 LaunchDelegateMock d;
840 EXPECT_CALL(d, LaunchComplete(testing::NotNull(), testing::_)).Times(2);
841 void* i1 = f.GetAutomationServer(0, L"Adam.N.Epilinter", L"", false, &d);
842 void* i2 = f.GetAutomationServer(0, L"Dr. Gratiano Forbeson", L"", false, &d);
843 EXPECT_NE(i1, i2);
844 f.ReleaseAutomationServer(i2);
845 f.ReleaseAutomationServer(i1);
846 }
847
848 // ChromeFrameAutomationClient [CFAC] tests.
849 struct MockCFDelegate : public ChromeFrameDelegateImpl {
850 MOCK_CONST_METHOD0(GetWindow, WindowType());
851 MOCK_METHOD1(GetBounds, void(RECT* bounds));
852 MOCK_METHOD0(GetDocumentUrl, std::string());
853 MOCK_METHOD2(ExecuteScript, bool(const std::string& script,
854 std::string* result));
855 MOCK_METHOD0(OnAutomationServerReady, void());
856 MOCK_METHOD2(OnAutomationServerLaunchFailed, void(
857 AutomationLaunchResult reason, const std::string& server_version));
858 // This remains in interface since we call it if Navigate()
859 // returns immediate error.
860 MOCK_METHOD2(OnLoadFailed, void(int error_code, const std::string& url));
861
862 // Do not mock this method. :) Use it as message demuxer and dispatcher
863 // to the following methods (which we mock)
864 // MOCK_METHOD1(OnMessageReceived, void(const IPC::Message&));
865
866
867 MOCK_METHOD2(OnNavigationStateChanged, void(int tab_handle, int flags));
868 MOCK_METHOD2(OnUpdateTargetUrl, void(int tab_handle,
869 const std::wstring& new_target_url));
870 MOCK_METHOD2(OnAcceleratorPressed, void(int tab_handle,
871 const MSG& accel_message));
872 MOCK_METHOD2(OnTabbedOut, void(int tab_handle, bool reverse));
873 MOCK_METHOD3(OnOpenURL, void(int tab_handle, const GURL& url,
874 int open_disposition));
875 MOCK_METHOD2(OnDidNavigate, void(int tab_handle,
876 const IPC::NavigationInfo& navigation_info));
877 MOCK_METHOD3(OnNavigationFailed, void(int tab_handle, int error_code,
878 const GURL& gurl));
879 MOCK_METHOD2(OnLoad, void(int tab_handle, const GURL& url));
880 MOCK_METHOD4(OnMessageFromChromeFrame, void(int tab_handle,
881 const std::string& message,
882 const std::string& origin,
883 const std::string& target));
884 MOCK_METHOD5(OnHandleContextMenu, void(int tab_handle, HANDLE menu_handle,
885 int x_pos, int y_pos, int align_flags));
886 MOCK_METHOD3(OnRequestStart, void(int tab_handle, int request_id,
887 const IPC::AutomationURLRequest& request));
888 MOCK_METHOD3(OnRequestRead, void(int tab_handle, int request_id,
889 int bytes_to_read));
890 MOCK_METHOD3(OnRequestEnd, void(int tab_handle, int request_id,
891 const URLRequestStatus& status));
892 MOCK_METHOD3(OnSetCookieAsync, void(int tab_handle, const GURL& url,
893 const std::string& cookie));
894
895 // Use for sending network responses
896 void SetAutomationSender(IPC::Message::Sender* automation) {
897 automation_ = automation;
898 }
899
900 // Set-expectation helpers
901 void SetOnNavigationStateChanged(int tab_handle) {
902 EXPECT_CALL(*this,
903 OnNavigationStateChanged(testing::Eq(tab_handle), testing::_))
904 .Times(testing::AnyNumber());
905 }
906
907 // Response sender helpers
908 void ReplyStarted(const IPC::AutomationURLResponse* response,
909 int tab_handle, int request_id,
910 const IPC::AutomationURLRequest& request) {
911 automation_->Send(new AutomationMsg_RequestStarted(0, tab_handle,
912 request_id, *response));
913 }
914
915 void ReplyData(const std::string* data, int tab_handle, int request_id,
916 int bytes_to_read) {
917 automation_->Send(new AutomationMsg_RequestData(0, tab_handle,
918 request_id, *data));
919 }
920
921 void ReplyEOF(int tab_handle, int request_id) {
922 automation_->Send(new AutomationMsg_RequestEnd(0, tab_handle,
923 request_id, URLRequestStatus()));
924 }
925
926 void Reply404(int tab_handle, int request_id,
927 const IPC::AutomationURLRequest& request) {
928 const IPC::AutomationURLResponse notfound = {"", "HTTP/1.1 404\r\n\r\n"};
929 automation_->Send(new AutomationMsg_RequestStarted(0, tab_handle,
930 request_id, notfound));
931 automation_->Send(new AutomationMsg_RequestEnd(0, tab_handle,
932 request_id, URLRequestStatus()));
933 }
934
935 IPC::Message::Sender* automation_;
936 };
937
938 class MockProxyFactory : public ProxyFactory {
939 public:
940 MOCK_METHOD5(GetAutomationServer, void*(int, const std::wstring&,
941 const std::wstring& extra_argument, bool, ProxyFactory::LaunchDelegate*));
942 MOCK_METHOD1(ReleaseAutomationServer, bool(void* id));
943
944 MockProxyFactory() : thread_("mock factory worker") {
945 thread_.Start();
946 loop_ = thread_.message_loop();
947 }
948
949 // Fake implementation
950 void GetServerImpl(ChromeFrameAutomationProxy* pxy,
951 AutomationLaunchResult result,
952 int timeout,
953 ProxyFactory::LaunchDelegate* d) {
954 Task* task = NewRunnableMethod(d,
955 &ProxyFactory::LaunchDelegate::LaunchComplete, pxy, result);
956 loop_->PostDelayedTask(FROM_HERE, task, timeout/2);
957 }
958
959 base::Thread thread_;
960 MessageLoop* loop_;
961 };
962
963 class MockAutomationProxy : public ChromeFrameAutomationProxy {
964 public:
965 MOCK_METHOD1(Send, bool(IPC::Message*));
966 MOCK_METHOD3(SendAsAsync, void(IPC::SyncMessage* msg, void* callback,
967 void* key));
968 MOCK_METHOD1(CancelAsync, void(void* key));
969 MOCK_METHOD1(CreateTabProxy, scoped_refptr<TabProxy>(int handle));
970 MOCK_METHOD0(server_version, std::string(void));
971 MOCK_METHOD1(SendProxyConfig, void(const std::string&));
972 MOCK_METHOD1(SetEnableExtensionAutomation, void(bool enable));
973
974 ~MockAutomationProxy() {}
975 };
976
977 struct MockAutomationMessageSender : public AutomationMessageSender {
978 MOCK_METHOD1(Send, bool(IPC::Message*));
979 MOCK_METHOD3(SendWithTimeout, bool(IPC::Message* , int , bool*));
980
981 void ForwardTo(MockAutomationProxy *p) {
982 proxy_ = p;
983 ON_CALL(*this, Send(testing::_))
984 .WillByDefault(testing::Invoke(proxy_, &MockAutomationProxy::Send));
985 }
986
987 MockAutomationProxy* proxy_;
988 };
989
990 template <> struct RunnableMethodTraits<ProxyFactory::LaunchDelegate> {
991 static void RetainCallee(ProxyFactory::LaunchDelegate* obj) {}
992 static void ReleaseCallee(ProxyFactory::LaunchDelegate* obj) {}
993 };
994
995 template <> struct RunnableMethodTraits<MockProxyFactory> {
996 static void RetainCallee(MockProxyFactory* obj) {}
997 static void ReleaseCallee(MockProxyFactory* obj) {}
998 };
999
1000 template <> struct RunnableMethodTraits<ChromeFrameAutomationClient> {
1001 static void RetainCallee(ChromeFrameAutomationClient* obj) {}
1002 static void ReleaseCallee(ChromeFrameAutomationClient* obj) {}
1003 };
1004
1005 // MessageLoopForUI wrapper that runs only for a limited time.
1006 // We need a UI message loop in the main thread.
1007 struct TimedMsgLoop {
1008 public:
1009 void RunFor(int seconds) {
1010 loop_.PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask, 1000 * seconds);
1011 loop_.MessageLoop::Run();
1012 }
1013
1014 void Quit() {
1015 loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask);
1016 }
1017
1018 MessageLoopForUI loop_;
1019 };
1020
1021 template <> struct RunnableMethodTraits<TimedMsgLoop> {
1022 static void RetainCallee(TimedMsgLoop* obj) {}
1023 static void ReleaseCallee(TimedMsgLoop* obj) {}
1024 };
1025
1026 // Saves typing. It's somewhat hard to create a wrapper around
1027 // testing::InvokeWithoutArgs since it returns a
1028 // non-public (testing::internal) type.
1029 #define QUIT_LOOP(loop) testing::InvokeWithoutArgs(TaskHolder(\
1030 NewRunnableMethod(&loop, &TimedMsgLoop::Quit)))
1031
1032 // We mock ChromeFrameDelegate only. The rest is with real AutomationProxy
1033 TEST(CFACWithChrome, CreateTooFast) {
1034 MockCFDelegate cfd;
1035 TimedMsgLoop loop;
1036 int timeout = 0; // Chrome cannot send Hello message so fast.
1037 const std::wstring profile = L"Adam.N.Epilinter";
1038
1039 scoped_ptr<ChromeFrameAutomationClient> client;
1040 client.reset(new ChromeFrameAutomationClient());
1041
1042 EXPECT_CALL(cfd, OnAutomationServerLaunchFailed(AUTOMATION_TIMEOUT,
1043 testing::_))
1044 .Times(1)
1045 .WillOnce(QUIT_LOOP(loop));
1046
1047 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", false));
1048 loop.RunFor(10);
1049 client->Uninitialize();
1050 }
1051
1052 // This test may fail if Chrome take more that 10 seconds (timeout var) to
1053 // launch. In this case GMock shall print something like "unexpected call to
1054 // OnAutomationServerLaunchFailed". I'm yet to find out how to specify
1055 // that this is an unexpected call, and still to execute and action.
1056 TEST(CFACWithChrome, CreateNotSoFast) {
1057 MockCFDelegate cfd;
1058 TimedMsgLoop loop;
1059 const std::wstring profile = L"Adam.N.Epilinter";
1060 int timeout = 10000;
1061
1062 scoped_ptr<ChromeFrameAutomationClient> client;
1063 client.reset(new ChromeFrameAutomationClient);
1064
1065 EXPECT_CALL(cfd, OnAutomationServerReady())
1066 .Times(1)
1067 .WillOnce(QUIT_LOOP(loop));
1068
1069 EXPECT_CALL(cfd, OnAutomationServerLaunchFailed(testing::_, testing::_))
1070 .Times(0);
1071
1072 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", false));
1073
1074 loop.RunFor(11);
1075 client->Uninitialize();
1076 client.reset(NULL);
1077 }
1078
1079 MATCHER_P(MsgType, msg_type, "IPC::Message::type()") {
1080 const IPC::Message& m = arg;
1081 return (m.type() == msg_type);
1082 }
1083
1084 MATCHER_P(EqNavigationInfoUrl, url, "IPC::NavigationInfo matcher") {
1085 if (url.is_valid() && url != arg.url)
1086 return false;
1087 // TODO: other members
1088 return true;
1089 }
1090
1091 TEST(CFACWithChrome, NavigateOk) {
1092 MockCFDelegate cfd;
1093 TimedMsgLoop loop;
1094 const std::wstring profile = L"Adam.N.Epilinter";
1095 const std::string url = "about:version";
1096 int timeout = 10000;
1097
1098 scoped_ptr<ChromeFrameAutomationClient> client;
1099 client.reset(new ChromeFrameAutomationClient);
1100
1101 EXPECT_CALL(cfd, OnAutomationServerReady())
1102 .WillOnce(testing::InvokeWithoutArgs(TaskHolder(NewRunnableMethod(
1103 client.get(), &ChromeFrameAutomationClient::InitiateNavigation,
1104 url))));
1105
1106 // cfd.SetOnNavigationStateChanged();
1107 EXPECT_CALL(cfd,
1108 OnNavigationStateChanged(testing::_, testing::_))
1109 .Times(testing::AnyNumber());
1110
1111 {
1112 testing::InSequence s;
1113
1114 EXPECT_CALL(cfd, OnDidNavigate(testing::_, EqNavigationInfoUrl(GURL())))
1115 .Times(1);
1116
1117 EXPECT_CALL(cfd, OnUpdateTargetUrl(testing::_, testing::_)).Times(1);
1118
1119 EXPECT_CALL(cfd, OnLoad(testing::_, testing::_))
1120 .Times(1)
1121 .WillOnce(QUIT_LOOP(loop));
1122 }
1123
1124 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", false));
1125 loop.RunFor(10);
1126 client->Uninitialize();
1127 client.reset(NULL);
1128 }
1129
1130 // Bug: http://b/issue?id=2033644
1131 TEST(CFACWithChrome, DISABLED_NavigateFailed) {
1132 MockCFDelegate cfd;
1133 TimedMsgLoop loop;
1134 const std::wstring profile = L"Adam.N.Epilinter";
1135 const std::string url = "http://127.0.0.3:65412/";
1136 int timeout = 10000;
1137
1138 scoped_ptr<ChromeFrameAutomationClient> client;
1139 client.reset(new ChromeFrameAutomationClient);
1140
1141 EXPECT_CALL(cfd, OnAutomationServerReady())
1142 .WillOnce(testing::InvokeWithoutArgs(TaskHolder(NewRunnableMethod(
1143 client.get(), &ChromeFrameAutomationClient::InitiateNavigation,
1144 url))));
1145
1146 EXPECT_CALL(cfd,
1147 OnNavigationStateChanged(testing::_, testing::_))
1148 .Times(testing::AnyNumber());
1149
1150 EXPECT_CALL(cfd, OnNavigationFailed(testing::_, testing::_, testing::_))
1151 .Times(1);
1152
1153 EXPECT_CALL(cfd, OnUpdateTargetUrl(testing::_, testing::_))
1154 .Times(testing::AnyNumber());
1155
1156 EXPECT_CALL(cfd, OnLoad(testing::_, testing::_))
1157 .Times(0);
1158
1159 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"", false));
1160
1161 loop.RunFor(10);
1162 client->Uninitialize();
1163 client.reset(NULL);
1164 }
1165
1166 MATCHER_P(EqURLRequest, x, "IPC::AutomationURLRequest matcher") {
1167 if (arg.url != x.url)
1168 return false;
1169 if (arg.method != x.method)
1170 return false;
1171 if (arg.referrer != x.referrer)
1172 return false;
1173 if (arg.extra_request_headers != x.extra_request_headers)
1174 return false;
1175 // TODO: uploaddata member
1176 return true;
1177 }
1178
1179 MATCHER_P(EqUrlGet, url, "Quick URL matcher for 'HTTP GET' request") {
1180 if (arg.url != url)
1181 return false;
1182 if (arg.method != "GET")
1183 return false;
1184 return true;
1185 }
1186
1187 TEST(CFACWithChrome, UseHostNetworkStack) {
1188 MockCFDelegate cfd;
1189 TimedMsgLoop loop;
1190 const std::wstring profile = L"Adam.N.Epilinter";
1191 const std::string url = "http://bongo.com";
1192 int timeout = 10000;
1193
1194 scoped_ptr<ChromeFrameAutomationClient> client;
1195 client.reset(new ChromeFrameAutomationClient);
1196 client->set_use_chrome_network(false);
1197 cfd.SetAutomationSender(client.get());
1198
1199 EXPECT_CALL(cfd, OnAutomationServerReady())
1200 .WillOnce(testing::InvokeWithoutArgs(TaskHolder(NewRunnableMethod(
1201 client.get(), &ChromeFrameAutomationClient::InitiateNavigation,
1202 url))));
1203
1204 EXPECT_CALL(cfd, OnNavigationStateChanged(testing::_, testing::_))
1205 .Times(testing::AnyNumber());
1206
1207 EXPECT_CALL(cfd, GetBounds(testing::_))
1208 .Times(testing::AtMost(1));
1209
1210 EXPECT_CALL(cfd, OnUpdateTargetUrl(testing::_, testing::_))
1211 .Times(testing::AnyNumber());
1212
1213 // Note slash appending to the url string, because of GURL inside chrome
1214 const IPC::AutomationURLResponse found = {"", "HTTP/0.9 200\r\n\r\n\r\n", };
1215
1216 // Hard coded tab and request ids
1217 static const int tab_id = 1;
1218 int request_id = 2;
1219
1220 EXPECT_CALL(cfd, OnRequestStart(tab_id, request_id, EqUrlGet(url + '/')))
1221 .Times(1)
1222 .WillOnce(testing::Invoke(CBF(&cfd, &MockCFDelegate::ReplyStarted,
1223 &found)));
1224
1225 // Return some trivial page, that have a link to a "logo.gif" image
1226 const std::string data = "<!DOCTYPE html><title>Hello</title>"
1227 "<img src=\"logo.gif\">";
1228 EXPECT_CALL(cfd, OnRequestRead(tab_id, request_id, testing::Ge(0)))
1229 .Times(2)
1230 .WillOnce(testing::Invoke(CBF(&cfd, &MockCFDelegate::ReplyData, &data)))
1231 .WillOnce(testing::WithArgs<0, 1>(testing::Invoke(CBF(&cfd,
1232 &MockCFDelegate::ReplyEOF))));
1233
1234 EXPECT_CALL(cfd, OnDidNavigate(tab_id, EqNavigationInfoUrl(GURL(url))))
1235 .Times(1);
1236 EXPECT_CALL(cfd, OnLoad(tab_id, GURL(url)))
1237 .Times(1);
1238
1239 // Expect request for logo.gif
1240 request_id++;
1241 EXPECT_CALL(cfd,
1242 OnRequestStart(tab_id, request_id, EqUrlGet(url + "/logo.gif")))
1243 .Times(1)
1244 .WillOnce(testing::Invoke(CBF(&cfd, &MockCFDelegate::Reply404)));
1245
1246 EXPECT_CALL(cfd, OnRequestRead(tab_id, request_id, testing::_))
1247 .Times(testing::AtMost(1));
1248
1249 // Chrome makes a brave request for favicon.ico
1250 request_id++;
1251 EXPECT_CALL(cfd,
1252 OnRequestStart(tab_id, request_id, EqUrlGet(url + "/favicon.ico")))
1253 .Times(1)
1254 .WillOnce(testing::Invoke(CBF(&cfd, &MockCFDelegate::Reply404)));
1255
1256 EXPECT_CALL(cfd, OnRequestRead(tab_id, request_id, testing::_))
1257 .Times(testing::AtMost(1));
1258
1259 bool incognito = true;
1260 EXPECT_TRUE(client->Initialize(&cfd, timeout, false, profile, L"",
1261 incognito));
1262
1263 loop.RunFor(10);
1264 client->Uninitialize();
1265 client.reset(NULL);
1266 }
1267
1268
1269 // [CFAC] -- uses a ProxyFactory for creation of ChromeFrameAutomationProxy
1270 // -- uses ChromeFrameAutomationProxy
1271 // -- uses TabProxy obtained from ChromeFrameAutomationProxy
1272 // -- uses ChromeFrameDelegate as outgoing interface
1273 //
1274 // We mock ProxyFactory to return mock object (MockAutomationProxy) implementing
1275 // ChromeFrameAutomationProxy interface.
1276 // Since CFAC uses TabProxy for few calls and TabProxy is not easy mockable,
1277 // we create 'real' TabProxy but with fake AutomationSender (the one responsible
1278 // for sending messages over channel).
1279 // Additionally we have mock implementation ChromeFrameDelagate interface -
1280 // MockCFDelegate.
1281
1282 // Test fixture, saves typing all of it's members.
1283 class CFACMockTest : public testing::Test {
1284 public:
1285 MockProxyFactory factory_;
1286 MockCFDelegate cfd_;
1287 TimedMsgLoop loop_;
1288 MockAutomationProxy proxy_;
1289 scoped_ptr<AutomationHandleTracker> tracker_;
1290 MockAutomationMessageSender dummy_sender_;
1291 scoped_refptr<TabProxy> tab_;
1292 scoped_ptr<ChromeFrameAutomationClient> client_; // the victim of all tests
1293
1294 std::wstring profile_;
1295 int timeout_;
1296 void* id_; // Automation server id we are going to return
1297 int tab_handle_; // Tab handle. Any non-zero value is Ok.
1298
1299 inline ChromeFrameAutomationProxy* get_proxy() {
1300 return static_cast<ChromeFrameAutomationProxy*>(&proxy_);
1301 }
1302
1303 inline void CreateTab() {
1304 ASSERT_EQ(NULL, tab_.get());
1305 tab_ = new TabProxy(&dummy_sender_, tracker_.get(), tab_handle_);
1306 }
1307
1308 // Easy methods to set expectations.
1309 void SetAutomationServerOk() {
1310 EXPECT_CALL(factory_, GetAutomationServer(testing::Eq(timeout_),
1311 testing::StrEq(profile_),
1312 testing::_,
1313 testing::_,
1314 testing::NotNull()))
1315 .Times(1)
1316 .WillOnce(testing::DoAll(
1317 testing::WithArgs<0, 4>(
1318 testing::Invoke(CBF(&factory_, &MockProxyFactory::GetServerImpl,
1319 get_proxy(), AUTOMATION_SUCCESS))),
1320 testing::Return(id_)));
1321
1322 EXPECT_CALL(factory_, ReleaseAutomationServer(testing::Eq(id_))).Times(1);
1323 }
1324
1325 void Set_CFD_LaunchFailed(AutomationLaunchResult result) {
1326 EXPECT_CALL(cfd_, OnAutomationServerLaunchFailed(
1327 testing::Eq(result), testing::_))
1328 .Times(1)
1329 .WillOnce(QUIT_LOOP(loop_));
1330 }
1331
1332 protected:
1333 CFACMockTest() : tracker_(NULL), timeout_(500),
1334 profile_(L"Adam.N.Epilinter") {
1335 id_ = reinterpret_cast<void*>(5);
1336 tab_handle_ = 3;
1337 }
1338
1339 virtual void SetUp() {
1340 dummy_sender_.ForwardTo(&proxy_);
1341 tracker_.reset(new AutomationHandleTracker(&dummy_sender_));
1342
1343 client_.reset(new ChromeFrameAutomationClient);
1344 client_->set_proxy_factory(&factory_);
1345 }
1346 };
1347
1348 // Could be implemented as MockAutomationProxy member (we have WithArgs<>!)
1349 ACTION_P3(HandleCreateTab, tab_handle, external_tab_container, tab_wnd) {
1350 // arg0 - message
1351 // arg1 - callback
1352 // arg2 - key
1353 CallbackRunner<Tuple3<HWND, HWND, int> >* c =
1354 reinterpret_cast<CallbackRunner<Tuple3<HWND, HWND, int> >*>(arg1);
1355 c->Run(external_tab_container, tab_wnd, tab_handle);
1356 delete c;
1357 delete arg0;
1358 }
1359
1360 TEST_F(CFACMockTest, MockedCreateTabOk) {
1361 int timeout = 500;
1362 CreateTab();
1363 SetAutomationServerOk();
1364
1365 EXPECT_CALL(proxy_, server_version()).Times(testing::AnyNumber())
1366 .WillRepeatedly(testing::Return(""));
1367
1368 // We need some valid HWNDs, when responding to CreateExternalTab
1369 HWND h1 = ::GetDesktopWindow();
1370 HWND h2 = ::GetDesktopWindow();
1371 EXPECT_CALL(proxy_, SendAsAsync(testing::Property(&IPC::SyncMessage::type,
1372 AutomationMsg_CreateExternalTab__ID),
1373 testing::NotNull(), testing::_))
1374 .Times(1)
1375 .WillOnce(HandleCreateTab(tab_handle_, h1, h2));
1376
1377 EXPECT_CALL(proxy_, CreateTabProxy(testing::Eq(tab_handle_)))
1378 .WillOnce(testing::Return(tab_));
1379
1380 EXPECT_CALL(cfd_, OnAutomationServerReady())
1381 .WillOnce(QUIT_LOOP(loop_));
1382
1383 // Here we go!
1384 EXPECT_TRUE(client_->Initialize(&cfd_, timeout, false, profile_, L"", false));
1385 loop_.RunFor(10);
1386 client_->Uninitialize();
1387 }
1388
1389 TEST_F(CFACMockTest, MockedCreateTabFailed) {
1390 HWND null_wnd = NULL;
1391 SetAutomationServerOk();
1392
1393 EXPECT_CALL(proxy_, server_version()).Times(testing::AnyNumber())
1394 .WillRepeatedly(testing::Return(""));
1395
1396 EXPECT_CALL(proxy_, SendAsAsync(testing::Property(&IPC::SyncMessage::type,
1397 AutomationMsg_CreateExternalTab__ID),
1398 testing::NotNull(), testing::_))
1399 .Times(1)
1400 .WillOnce(HandleCreateTab(tab_handle_, null_wnd, null_wnd));
1401
1402 EXPECT_CALL(proxy_, CreateTabProxy(testing::_)).Times(0);
1403
1404 Set_CFD_LaunchFailed(AUTOMATION_CREATE_TAB_FAILED);
1405
1406 // Here we go!
1407 EXPECT_TRUE(client_->Initialize(&cfd_, timeout_, false, profile_, L"",
1408 false));
1409 loop_.RunFor(4);
1410 client_->Uninitialize();
1411 }
1412
1413 const wchar_t kMetaTagPage[] = L"files/meta_tag.html";
1414 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_MetaTag) {
1415 SimpleBrowserTest(IE, kMetaTagPage, L"meta_tag");
1416 }
1417
1418 const wchar_t kCFProtocolPage[] = L"files/chrome_frame_protocol.html";
1419 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_CFProtocol) {
1420 SimpleBrowserTest(IE, kCFProtocolPage, L"chrome_frame_protocol");
1421 }
1422
1423 const wchar_t kPersistentCookieTest[] =
1424 L"files/persistent_cookie_test_page.html";
1425 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_PersistentCookieTest) {
1426 SimpleBrowserTest(IE, kPersistentCookieTest, L"PersistentCookieTest");
1427 }
1428
1429 const wchar_t kNavigateOutPage[] = L"files/navigate_out.html";
1430 TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_NavigateOut) {
1431 SimpleBrowserTest(IE, kNavigateOutPage, L"navigate_out");
1432 }
1433
1434 HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser) {
1435 if (!web_browser)
1436 return E_INVALIDARG;
1437
1438 ScopedComPtr<IWebBrowser2> web_browser2;
1439 HRESULT hr = CoCreateInstance(
1440 CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2,
1441 reinterpret_cast<void**>(web_browser2.Receive()));
1442
1443 if (SUCCEEDED(hr)) {
1444 *web_browser = web_browser2.Detach();
1445 }
1446
1447 return hr;
1448 }
1449
1450 TEST(ChromeFrameTest, FullTabModeIE_DisallowedUrls) {
1451 int major_version = 0;
1452 int minor_version = 0;
1453 int bugfix_version = 0;
1454
1455 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
1456 &bugfix_version);
1457 if (major_version > 5) {
1458 DLOG(INFO) << __FUNCTION__ << " Not running test on Windows version: "
1459 << major_version;
1460 return;
1461 }
1462
1463 IEVersion ie_version = GetIEVersion();
1464 if (ie_version == IE_8) {
1465 DLOG(INFO) << __FUNCTION__ << " Not running test on IE8";
1466 return;
1467 }
1468
1469 HRESULT hr = CoInitialize(NULL);
1470 bool should_uninit = SUCCEEDED(hr);
1471
1472 ScopedComPtr<IWebBrowser2> web_browser2;
1473 EXPECT_TRUE(S_OK == LaunchIEAsComServer(web_browser2.Receive()));
1474 web_browser2->put_Visible(VARIANT_TRUE);
1475
1476 CComObject<WebBrowserEventSink>* web_browser_sink = NULL;
1477 CComObject<WebBrowserEventSink>::CreateInstance(&web_browser_sink);
1478
1479 // Pass the main thread id to the browser sink so that it can notify
1480 // us about test completion.
1481 web_browser_sink->set_main_thread_id(GetCurrentThreadId());
1482
1483 hr = web_browser_sink->DispEventAdvise(web_browser2,
1484 &DIID_DWebBrowserEvents2);
1485 EXPECT_TRUE(hr == S_OK);
1486
1487 VARIANT empty = ScopedVariant::kEmptyVariant;
1488 ScopedVariant url;
1489 url.Set(L"cf:file:///C:/");
1490
1491 TimedMsgLoop loop;
1492
1493 hr = web_browser2->Navigate2(url.AsInput(), &empty, &empty, &empty, &empty);
1494 EXPECT_TRUE(hr == S_OK);
1495
1496 loop.RunFor(10);
1497
1498 EXPECT_TRUE(web_browser_sink->navigation_failed());
1499
1500 hr = web_browser_sink->DispEventUnadvise(web_browser2);
1501 EXPECT_TRUE(hr == S_OK);
1502
1503 web_browser2.Release();
1504 chrome_frame_test::CloseAllIEWindows();
1505
1506 if (should_uninit) {
1507 CoUninitialize();
1508 }
1509 }
1510
OLDNEW
« no previous file with comments | « chrome_frame/test/chrome_frame_unittests.h ('k') | chrome_frame/test/chrometab_unittests.vsprops » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698