| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "app/app_switches.h" | 7 #include "app/app_switches.h" |
| 8 #include "app/l10n_util.h" | 8 #include "app/l10n_util.h" |
| 9 #include "app/message_box_flags.h" | 9 #include "app/message_box_flags.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "chrome/test/automation/autocomplete_edit_proxy.h" | 22 #include "chrome/test/automation/autocomplete_edit_proxy.h" |
| 23 #include "chrome/test/automation/automation_messages.h" | 23 #include "chrome/test/automation/automation_messages.h" |
| 24 #include "chrome/test/automation/automation_proxy_uitest.h" | 24 #include "chrome/test/automation/automation_proxy_uitest.h" |
| 25 #include "chrome/test/automation/browser_proxy.h" | 25 #include "chrome/test/automation/browser_proxy.h" |
| 26 #include "chrome/test/automation/tab_proxy.h" | 26 #include "chrome/test/automation/tab_proxy.h" |
| 27 #include "chrome/test/automation/window_proxy.h" | 27 #include "chrome/test/automation/window_proxy.h" |
| 28 #include "chrome/test/ui_test_utils.h" | 28 #include "chrome/test/ui_test_utils.h" |
| 29 #include "chrome/test/ui/ui_test.h" | 29 #include "chrome/test/ui/ui_test.h" |
| 30 #include "net/base/net_util.h" | 30 #include "net/base/net_util.h" |
| 31 #include "net/url_request/url_request_unittest.h" | 31 #include "net/url_request/url_request_unittest.h" |
| 32 #include "testing/gmock/include/gmock/gmock.h" | |
| 33 #define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING | 32 #define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING |
| 34 #include "testing/gmock_mutant.h" | 33 #include "testing/gmock_mutant.h" |
| 35 #include "views/event.h" | 34 #include "views/event.h" |
| 36 | 35 |
| 37 using ui_test_utils::TimedMessageLoopRunner; | 36 using ui_test_utils::TimedMessageLoopRunner; |
| 38 using testing::CreateFunctor; | 37 using testing::CreateFunctor; |
| 39 using testing::StrEq; | 38 using testing::StrEq; |
| 40 | 39 |
| 41 #if defined(OS_MACOSX) | 40 #if defined(OS_MACOSX) |
| 42 #define MAYBE_WindowGetViewBounds DISABLED_WindowGetViewBounds | 41 #define MAYBE_WindowGetViewBounds DISABLED_WindowGetViewBounds |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 | 645 |
| 647 ASSERT_TRUE(tab->NavigateToURL(net::FilePathToFileURL(filename))); | 646 ASSERT_TRUE(tab->NavigateToURL(net::FilePathToFileURL(filename))); |
| 648 | 647 |
| 649 ASSERT_TRUE(tab->WaitForBlockedPopupCountToChangeTo(2, 5000)); | 648 ASSERT_TRUE(tab->WaitForBlockedPopupCountToChangeTo(2, 5000)); |
| 650 } | 649 } |
| 651 | 650 |
| 652 #endif // defined(OS_WIN) | 651 #endif // defined(OS_WIN) |
| 653 | 652 |
| 654 // TODO(port): Remove HWND if possible | 653 // TODO(port): Remove HWND if possible |
| 655 #if defined(OS_WIN) | 654 #if defined(OS_WIN) |
| 656 static const wchar_t class_name[] = L"External_Tab_UI_Test_Class"; | |
| 657 static const wchar_t window_title[] = L"External Tab Tester"; | |
| 658 | |
| 659 AutomationProxyForExternalTab::AutomationProxyForExternalTab( | |
| 660 int execution_timeout) | |
| 661 : AutomationProxy(execution_timeout), | |
| 662 messages_received_(0), | |
| 663 navigate_complete_(false), | |
| 664 quit_after_(QUIT_INVALID), | |
| 665 host_window_class_(NULL), | |
| 666 host_window_(NULL) { | |
| 667 } | |
| 668 | |
| 669 AutomationProxyForExternalTab::~AutomationProxyForExternalTab() { | |
| 670 DestroyHostWindow(); | |
| 671 UnregisterClassW(host_window_class_, NULL); | |
| 672 } | |
| 673 | |
| 674 gfx::NativeWindow AutomationProxyForExternalTab::CreateHostWindow() { | |
| 675 DCHECK(!IsWindow(host_window_)); | |
| 676 if (!host_window_class_) { | |
| 677 WNDCLASSEX wnd_class = {0}; | |
| 678 wnd_class.cbSize = sizeof(wnd_class); | |
| 679 wnd_class.style = CS_HREDRAW | CS_VREDRAW; | |
| 680 wnd_class.lpfnWndProc = DefWindowProc; | |
| 681 wnd_class.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); | |
| 682 wnd_class.lpszClassName = class_name; | |
| 683 host_window_class_ = reinterpret_cast<const wchar_t*>( | |
| 684 RegisterClassEx(&wnd_class)); | |
| 685 if (!host_window_class_) { | |
| 686 NOTREACHED() << "RegisterClassEx failed. Error: " << GetLastError(); | |
| 687 return false; | |
| 688 } | |
| 689 } | |
| 690 | |
| 691 unsigned long style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN; | |
| 692 host_window_ = CreateWindow(host_window_class_, window_title, style, | |
| 693 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, | |
| 694 NULL, NULL, NULL); | |
| 695 if (!host_window_) { | |
| 696 NOTREACHED() << "CreateWindow failed. Error: " << GetLastError(); | |
| 697 return false; | |
| 698 } | |
| 699 | |
| 700 ShowWindow(host_window_, SW_SHOW); | |
| 701 return host_window_; | |
| 702 } | |
| 703 | |
| 704 scoped_refptr<TabProxy> AutomationProxyForExternalTab::CreateTabWithHostWindow( | |
| 705 bool is_incognito, const GURL& initial_url, | |
| 706 gfx::NativeWindow* container_wnd, gfx::NativeWindow* tab_wnd) { | |
| 707 DCHECK(container_wnd); | |
| 708 DCHECK(tab_wnd); | |
| 709 | |
| 710 CreateHostWindow(); | |
| 711 EXPECT_NE(FALSE, ::IsWindow(host_window_)); | |
| 712 | |
| 713 RECT client_area = {0}; | |
| 714 GetClientRect(host_window_, &client_area); | |
| 715 | |
| 716 const IPC::ExternalTabSettings settings = { | |
| 717 host_window_, | |
| 718 gfx::Rect(client_area), | |
| 719 WS_CHILD | WS_VISIBLE, | |
| 720 is_incognito, | |
| 721 false, | |
| 722 false, | |
| 723 initial_url | |
| 724 }; | |
| 725 | |
| 726 scoped_refptr<TabProxy> tab(CreateExternalTab(settings, container_wnd, | |
| 727 tab_wnd)); | |
| 728 | |
| 729 EXPECT_TRUE(tab != NULL); | |
| 730 EXPECT_NE(FALSE, ::IsWindow(*container_wnd)); | |
| 731 EXPECT_NE(FALSE, ::IsWindow(*tab_wnd)); | |
| 732 return tab; | |
| 733 } | |
| 734 | |
| 735 void AutomationProxyForExternalTab::DestroyHostWindow() { | |
| 736 if (host_window_) { | |
| 737 DestroyWindow(host_window_); | |
| 738 host_window_ = NULL; | |
| 739 } | |
| 740 } | |
| 741 | |
| 742 bool AutomationProxyForExternalTab::WaitForNavigation(int timeout_ms) { | |
| 743 set_quit_after(AutomationProxyForExternalTab::QUIT_AFTER_NAVIGATION); | |
| 744 return RunMessageLoop(timeout_ms, NULL); | |
| 745 } | |
| 746 | |
| 747 bool AutomationProxyForExternalTab::WaitForMessage(int timeout_ms) { | |
| 748 set_quit_after(AutomationProxyForExternalTab::QUIT_AFTER_MESSAGE); | |
| 749 return RunMessageLoop(timeout_ms, NULL); | |
| 750 } | |
| 751 | |
| 752 bool AutomationProxyForExternalTab::WaitForTabCleanup(TabProxy* tab, | |
| 753 int timeout_ms) { | |
| 754 DCHECK(tab); | |
| 755 base::Time end_time = | |
| 756 base::Time::Now() + TimeDelta::FromMilliseconds(timeout_ms); | |
| 757 while (base::Time::Now() < end_time) { | |
| 758 const int kWaitInterval = 50; | |
| 759 DWORD wait_result = MsgWaitForMultipleObjects(0, NULL, FALSE, kWaitInterval, | |
| 760 QS_ALLINPUT); | |
| 761 if (!tab->is_valid()) | |
| 762 break; | |
| 763 if (WAIT_OBJECT_0 == wait_result) { | |
| 764 MSG msg = {0}; | |
| 765 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { | |
| 766 TranslateMessage(&msg); | |
| 767 DispatchMessage(&msg); | |
| 768 } | |
| 769 } | |
| 770 } | |
| 771 | |
| 772 return !tab->is_valid(); | |
| 773 } | |
| 774 | |
| 775 bool AutomationProxyForExternalTab::RunMessageLoop( | |
| 776 int timeout_ms, | |
| 777 gfx::NativeWindow window_to_monitor) { | |
| 778 // If there's no host window then the abort or this loop will be stuck | |
| 779 // in GetMessage | |
| 780 if (!IsWindow(host_window_)) | |
| 781 return false; | |
| 782 | |
| 783 // Allow the renderers to connect. | |
| 784 const int kTimerIdQuit = 100; | |
| 785 const int kTimerIdProcessPendingMessages = 101; | |
| 786 | |
| 787 if (!window_to_monitor) | |
| 788 window_to_monitor = host_window_; | |
| 789 | |
| 790 UINT_PTR quit_timer = ::SetTimer(host_window_, kTimerIdQuit, | |
| 791 timeout_ms, NULL); | |
| 792 UINT_PTR pump_timer = ::SetTimer(host_window_, | |
| 793 kTimerIdProcessPendingMessages, 50, NULL); | |
| 794 | |
| 795 MSG msg; | |
| 796 bool quit = false; | |
| 797 do { | |
| 798 BOOL ok = ::GetMessage(&msg, NULL, 0, 0); | |
| 799 if (!ok || ok == -1) | |
| 800 break; | |
| 801 | |
| 802 if (msg.message == WM_TIMER && msg.hwnd == host_window_) { | |
| 803 switch (msg.wParam) { | |
| 804 case kTimerIdProcessPendingMessages: | |
| 805 MessageLoop::current()->RunAllPending(); | |
| 806 break; | |
| 807 case kTimerIdQuit: | |
| 808 quit = true; | |
| 809 break; | |
| 810 default: | |
| 811 NOTREACHED() << "invalid timer id"; | |
| 812 break; | |
| 813 } | |
| 814 } else if ((msg.message == WM_QUIT) || (msg.message == kQuitLoopMessage)) { | |
| 815 quit = true; | |
| 816 } else { | |
| 817 ::TranslateMessage(&msg); | |
| 818 ::DispatchMessage(&msg); | |
| 819 } | |
| 820 } while (!quit && ::IsWindow(window_to_monitor)); | |
| 821 | |
| 822 KillTimer(host_window_, quit_timer); | |
| 823 KillTimer(host_window_, pump_timer); | |
| 824 quit_after_ = QUIT_INVALID; | |
| 825 return true; | |
| 826 } | |
| 827 | |
| 828 void AutomationProxyForExternalTab::OnMessageReceived(const IPC::Message& msg) { | |
| 829 IPC_BEGIN_MESSAGE_MAP(AutomationProxyForExternalTab, msg) | |
| 830 IPC_MESSAGE_HANDLER(AutomationMsg_DidNavigate, OnDidNavigate) | |
| 831 IPC_MESSAGE_HANDLER(AutomationMsg_ForwardMessageToExternalHost, | |
| 832 OnForwardMessageToExternalHost) | |
| 833 IPC_END_MESSAGE_MAP() | |
| 834 } | |
| 835 | |
| 836 void AutomationProxyForExternalTab::OnDidNavigate( | |
| 837 int tab_handle, | |
| 838 const IPC::NavigationInfo& nav_info) { | |
| 839 navigate_complete_ = true; | |
| 840 if (QUIT_AFTER_NAVIGATION == quit_after_) | |
| 841 QuitLoop(); | |
| 842 } | |
| 843 | |
| 844 void AutomationProxyForExternalTab::OnForwardMessageToExternalHost( | |
| 845 int handle, | |
| 846 const std::string& message, | |
| 847 const std::string& origin, | |
| 848 const std::string& target) { | |
| 849 messages_received_++; | |
| 850 message_ = message; | |
| 851 origin_ = origin; | |
| 852 target_ = target; | |
| 853 | |
| 854 if (QUIT_AFTER_MESSAGE == quit_after_) | |
| 855 QuitLoop(); | |
| 856 } | |
| 857 | 655 |
| 858 const char simple_data_url[] = | 656 const char simple_data_url[] = |
| 859 "data:text/html,<html><head><title>External tab test</title></head>" | 657 "data:text/html,<html><head><title>External tab test</title></head>" |
| 860 "<body>A simple page for testing a floating/invisible tab<br></div>" | 658 "<body>A simple page for testing a floating/invisible tab<br></div>" |
| 861 "</body></html>"; | 659 "</body></html>"; |
| 862 | 660 |
| 863 // We have to derive from AutomationProxy in order to hook up | 661 ExternalTabUITestMockClient::ExternalTabUITestMockClient(int execution_timeout) |
| 864 // OnMessageReceived callbacks. | 662 : AutomationProxy(execution_timeout), |
| 865 class ExternalTabUITestMockClient : public AutomationProxy { | 663 host_window_(NULL) { |
| 866 public: | 664 } |
| 867 explicit ExternalTabUITestMockClient(int execution_timeout) | |
| 868 : AutomationProxy(execution_timeout), | |
| 869 host_window_(NULL) { | |
| 870 } | |
| 871 | 665 |
| 872 MOCK_METHOD2(OnDidNavigate, void(int tab_handle, | 666 void ExternalTabUITestMockClient::ReplyStarted( |
| 873 const IPC::NavigationInfo& nav_info)); | 667 const IPC::AutomationURLResponse* response, |
| 874 MOCK_METHOD4(OnForwardMessageToExternalHost, void(int handle, | 668 int tab_handle, int request_id) { |
| 875 const std::string& message, const std::string& origin, | 669 AutomationProxy::Send(new AutomationMsg_RequestStarted(0, tab_handle, |
| 876 const std::string& target)); | 670 request_id, *response)); |
| 877 MOCK_METHOD3(OnRequestStart, void(int tab_handle, int request_id, | 671 } |
| 878 const IPC::AutomationURLRequest& request)); | |
| 879 MOCK_METHOD3(OnRequestRead, void(int tab_handle, int request_id, | |
| 880 int bytes_to_read)); | |
| 881 MOCK_METHOD3(OnRequestEnd, void(int tab_handle, int request_id, | |
| 882 const URLRequestStatus& status)); | |
| 883 MOCK_METHOD3(OnSetCookieAsync, void(int tab_handle, const GURL& url, | |
| 884 const std::string& cookie)); | |
| 885 | 672 |
| 673 void ExternalTabUITestMockClient::ReplyData( |
| 674 const std::string* data, int tab_handle, int request_id) { |
| 675 AutomationProxy::Send(new AutomationMsg_RequestData(0, tab_handle, |
| 676 request_id, *data)); |
| 677 } |
| 886 | 678 |
| 887 MOCK_METHOD1(HandleClosed, void(int handle)); | 679 void ExternalTabUITestMockClient::ReplyEOF(int tab_handle, int request_id) { |
| 680 AutomationProxy::Send(new AutomationMsg_RequestEnd(0, tab_handle, |
| 681 request_id, |
| 682 URLRequestStatus())); |
| 683 } |
| 888 | 684 |
| 685 void ExternalTabUITestMockClient::Reply404(int tab_handle, int request_id) { |
| 686 const IPC::AutomationURLResponse notfound = {"", "HTTP/1.1 404\r\n\r\n"}; |
| 687 ReplyStarted(¬found, tab_handle, request_id); |
| 688 ReplyEOF(tab_handle, request_id); |
| 689 } |
| 889 | 690 |
| 890 // Action helpers for OnRequest* incoming messages. Create the message and | 691 void ExternalTabUITestMockClient::InvalidateHandle( |
| 891 // delegate sending to the base class. Apparently we do not have wrappers | 692 const IPC::Message& message) { |
| 892 // in AutomationProxy for these messages. | 693 void* iter = NULL; |
| 893 void ReplyStarted(const IPC::AutomationURLResponse* response, | 694 int handle; |
| 894 int tab_handle, int request_id) { | 695 ASSERT_TRUE(message.ReadInt(&iter, &handle)); |
| 895 AutomationProxy::Send(new AutomationMsg_RequestStarted(0, tab_handle, | |
| 896 request_id, *response)); | |
| 897 } | |
| 898 | 696 |
| 899 void ReplyData(const std::string* data, int tab_handle, int request_id) { | 697 // Call base class |
| 900 AutomationProxy::Send(new AutomationMsg_RequestData(0, tab_handle, | 698 AutomationProxy::InvalidateHandle(message); |
| 901 request_id, *data)); | 699 HandleClosed(handle); |
| 902 } | 700 } |
| 903 | |
| 904 void ReplyEOF(int tab_handle, int request_id) { | |
| 905 AutomationProxy::Send(new AutomationMsg_RequestEnd(0, tab_handle, | |
| 906 request_id, | |
| 907 URLRequestStatus())); | |
| 908 } | |
| 909 | |
| 910 void Reply404(int tab_handle, int request_id) { | |
| 911 const IPC::AutomationURLResponse notfound = {"", "HTTP/1.1 404\r\n\r\n"}; | |
| 912 ReplyStarted(¬found, tab_handle, request_id); | |
| 913 ReplyEOF(tab_handle, request_id); | |
| 914 } | |
| 915 | |
| 916 // Test setup helpers | |
| 917 scoped_refptr<TabProxy> CreateHostWindowAndTab( | |
| 918 const IPC::ExternalTabSettings& settings); | |
| 919 scoped_refptr<TabProxy> CreateTabWithUrl(const GURL& initial_url); | |
| 920 void DestroyHostWindow(); | |
| 921 | |
| 922 static const IPC::ExternalTabSettings default_settings; | |
| 923 protected: | |
| 924 HWND host_window_; | |
| 925 | |
| 926 // Simple dispatcher to above OnXXX methods. | |
| 927 virtual void OnMessageReceived(const IPC::Message& msg); | |
| 928 virtual void InvalidateHandle(const IPC::Message& message) { | |
| 929 void* iter = NULL; | |
| 930 int handle; | |
| 931 ASSERT_TRUE(message.ReadInt(&iter, &handle)); | |
| 932 | |
| 933 // Call base class | |
| 934 AutomationProxy::InvalidateHandle(message); | |
| 935 HandleClosed(handle); | |
| 936 } | |
| 937 }; | |
| 938 | 701 |
| 939 // Most of the time we need external tab with these settings. | 702 // Most of the time we need external tab with these settings. |
| 940 const IPC::ExternalTabSettings ExternalTabUITestMockClient::default_settings = { | 703 const IPC::ExternalTabSettings ExternalTabUITestMockClient::default_settings = { |
| 941 NULL, gfx::Rect(), // will be replaced by CreateHostWindowAndTab | 704 NULL, gfx::Rect(), // will be replaced by CreateHostWindowAndTab |
| 942 WS_CHILD | WS_VISIBLE, | 705 WS_CHILD | WS_VISIBLE, |
| 943 false, // is_off_the_record | 706 false, // is_off_the_record |
| 944 true, // load_requests_via_automation | 707 true, // load_requests_via_automation |
| 945 true, // handle_top_level_requests | 708 true, // handle_top_level_requests |
| 946 GURL() // initial_url | 709 GURL() // initial_url |
| 947 }; | 710 }; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 scoped_refptr<TabProxy> ExternalTabUITestMockClient::CreateTabWithUrl( | 751 scoped_refptr<TabProxy> ExternalTabUITestMockClient::CreateTabWithUrl( |
| 989 const GURL& initial_url) { | 752 const GURL& initial_url) { |
| 990 IPC::ExternalTabSettings settings = | 753 IPC::ExternalTabSettings settings = |
| 991 ExternalTabUITestMockClient::default_settings; | 754 ExternalTabUITestMockClient::default_settings; |
| 992 settings.initial_url = initial_url; | 755 settings.initial_url = initial_url; |
| 993 return CreateHostWindowAndTab(settings); | 756 return CreateHostWindowAndTab(settings); |
| 994 } | 757 } |
| 995 | 758 |
| 996 void ExternalTabUITestMockClient::DestroyHostWindow() { | 759 void ExternalTabUITestMockClient::DestroyHostWindow() { |
| 997 ::DestroyWindow(host_window_); | 760 ::DestroyWindow(host_window_); |
| 761 host_window_ = NULL; |
| 998 } | 762 } |
| 999 | 763 |
| 764 bool ExternalTabUITestMockClient::HostWindowExists() { |
| 765 return (host_window_ != NULL) && ::IsWindow(host_window_); |
| 766 } |
| 767 |
| 768 |
| 1000 // Handy macro | 769 // Handy macro |
| 1001 #define QUIT_LOOP(loop) testing::InvokeWithoutArgs(\ | 770 #define QUIT_LOOP(loop) testing::InvokeWithoutArgs(\ |
| 1002 CreateFunctor(loop, &TimedMessageLoopRunner::Quit)) | 771 CreateFunctor(loop, &TimedMessageLoopRunner::Quit)) |
| 1003 #define QUIT_LOOP_SOON(loop, ms) testing::InvokeWithoutArgs(\ | 772 #define QUIT_LOOP_SOON(loop, ms) testing::InvokeWithoutArgs(\ |
| 1004 CreateFunctor(loop, &TimedMessageLoopRunner::QuitAfter, ms)) | 773 CreateFunctor(loop, &TimedMessageLoopRunner::QuitAfter, ms)) |
| 1005 | 774 |
| 1006 template <typename T> T** ReceivePointer(scoped_ptr<T>& p) { // NOLINT | 775 template <typename T> T** ReceivePointer(scoped_ptr<T>& p) { // NOLINT |
| 1007 return reinterpret_cast<T**>(&p); | 776 return reinterpret_cast<T**>(&p); |
| 1008 } | 777 } |
| 1009 | 778 |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1402 | 1171 |
| 1403 // Allow some time for the popup to show up and close. | 1172 // Allow some time for the popup to show up and close. |
| 1404 PlatformThread::Sleep(2000); | 1173 PlatformThread::Sleep(2000); |
| 1405 | 1174 |
| 1406 std::wstring expected(L"string"); | 1175 std::wstring expected(L"string"); |
| 1407 std::wstring jscript = CreateJSString(L"\"" + expected + L"\""); | 1176 std::wstring jscript = CreateJSString(L"\"" + expected + L"\""); |
| 1408 std::wstring actual; | 1177 std::wstring actual; |
| 1409 ASSERT_TRUE(tab->ExecuteAndExtractString(L"", jscript, &actual)); | 1178 ASSERT_TRUE(tab->ExecuteAndExtractString(L"", jscript, &actual)); |
| 1410 ASSERT_EQ(expected, actual); | 1179 ASSERT_EQ(expected, actual); |
| 1411 } | 1180 } |
| OLD | NEW |