diff options
Diffstat (limited to 'chrome/test')
439 files changed, 25399 insertions, 0 deletions
diff --git a/chrome/test/accessibility/accessibility_tests.cc b/chrome/test/accessibility/accessibility_tests.cc new file mode 100644 index 0000000..84dee3b --- /dev/null +++ b/chrome/test/accessibility/accessibility_tests.cc @@ -0,0 +1,503 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <Objbase.h> +#include <Oleacc.h> +#include "chrome/test/accessibility/accessibility_util.h" +#include "chrome/test/ui/ui_test.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/app/chrome_dll_resource.h" +#include "base/win_util.h" +#include "base/file_util.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_util.h" + + +namespace { + +#define CHK_RELEASE(obj) { if (obj) { (obj)->Release(); (obj) = NULL; } } + +class AccessibilityTest : public UITest { + protected: + AccessibilityTest() { + show_window_ = true; + CoInitialize(NULL); + } + ~AccessibilityTest() { + CoUninitialize(); + } +}; +} // Namespace. + +// Check browser handle and accessibility object browser client. +// TODO(sridharg): Alter, when accessibility objects for Chrome Window, Application and +// Client are corrected. +TEST_F(AccessibilityTest, TestChromeBrowserAccObject) { + IAccessible* p_accobj = NULL; + HWND hwnd = GetChromeBrowserWnd(&p_accobj); + ASSERT_TRUE(NULL != hwnd); + ASSERT_TRUE(NULL != p_accobj); + CHK_RELEASE(p_accobj); +} + +// Check accessibility object for toolbar and it's properties Name, Role, State. +// (Add other properties, if their values are fixed all the time.) +TEST_F(AccessibilityTest, TestChromeToolbarAccObject) { + IAccessible* p_accobj = NULL; + GetToolbarWnd(&p_accobj); + ASSERT_TRUE(NULL != p_accobj); + + // Check Name - "Google Chrome Toolbar". + EXPECT_EQ(L"Google Chrome Toolbar", GetName(p_accobj)); + // Check Role - "tool bar". + EXPECT_EQ(L"tool bar", GetRole(p_accobj)); + // Check State - "focusable" + EXPECT_EQ(L"focusable", GetState(p_accobj)); + + CHK_RELEASE(p_accobj); +} + +// Check accessibility object for tabstrip and it's properties Name, Role, +// State. (Add other properties, if their values are fixed all the time.) +TEST_F(AccessibilityTest, TestChromeTabstripAccObject) { + IAccessible* p_accobj = NULL; + GetTabStripWnd(&p_accobj); + ASSERT_TRUE(NULL != p_accobj); + + // Check Name - "Tabstrip". + EXPECT_EQ(L"Tabstrip", GetName(p_accobj)); + // Check Role - "grouping". + EXPECT_EQ(L"grouping", GetRole(p_accobj)); + // Check State - "focusable" + EXPECT_EQ(L"focusable", GetState(p_accobj)); + + CHK_RELEASE(p_accobj); +} + +// Check Browser buttons and their Name, Role, State. +TEST_F(AccessibilityTest, TestChromeButtons) { + HRESULT hr = S_OK; + IAccessible* p_accobj = NULL; + VARIANT button; + + // Get browser accessibility object. + IAccessible* p_browser = NULL; + GetChromeBrowserWnd(&p_browser); + ASSERT_TRUE(NULL != p_browser); + + // Check Minimize button and it's Name, Role, State. + hr = GetBrowserMinimizeButton(&p_accobj, &button); + // It is not complete accessible object, as it is element. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + // Read it's properties. + EXPECT_EQ(L"Minimize", GetName(p_browser, button)); + EXPECT_EQ(L"push button", GetRole(p_browser, button)); + EXPECT_EQ(L"focusable", GetState(p_browser, button)); + CHK_RELEASE(p_accobj); + + // Check Maximize button and it's Name, Role, State. + GetBrowserMaximizeButton(&p_accobj, &button); + // It is an element and not complete accessible object. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + // Read it's properties. + EXPECT_EQ(L"Maximize", GetName(p_browser, button)); + EXPECT_EQ(L"push button", GetRole(p_browser, button)); + EXPECT_EQ(L"focusable", GetState(p_browser, button)); + CHK_RELEASE(p_accobj); + + // Check Restore button and it's Name, Role, State. + GetBrowserRestoreButton(&p_accobj, &button); + // It is an element and not complete accessible object. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + // Read it's properties. + EXPECT_EQ(L"Restore", GetName(p_browser, button)); + EXPECT_EQ(L"push button", GetRole(p_browser, button)); + EXPECT_EQ(L"focusable, invisible", GetState(p_browser, button)); + CHK_RELEASE(p_accobj); + + // Check Close button and it's Name, Role, State. + GetBrowserCloseButton(&p_accobj, &button); + // It is an element and not complete accessible object. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + // Read it's properties. + EXPECT_EQ(L"Close", GetName(p_browser, button)); + EXPECT_EQ(L"push button", GetRole(p_browser, button)); + EXPECT_EQ(L"focusable", GetState(p_browser, button)); + CHK_RELEASE(p_accobj); + + CHK_RELEASE(p_browser); +} + +// Check Star button and their Name, Role, State. +TEST_F(AccessibilityTest, TestStarButton) { + HRESULT hr = S_OK; + IAccessible* p_accobj = NULL; + VARIANT button; + + // Get toolbar accessibility object. + IAccessible* p_toolbar = NULL; + GetToolbarWnd(&p_toolbar); + ASSERT_TRUE(NULL != p_toolbar); + + // Check button and it's Name, Role, State. + hr = GetStarButton(&p_accobj, &button); + // It is not complete accessible object, as it is element. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + // Read it's properties. + EXPECT_EQ(L"Bookmark", GetName(p_toolbar, button)); + EXPECT_EQ(L"push button", GetRole(p_toolbar, button)); + EXPECT_EQ(L"focusable", GetState(p_toolbar, button)); + CHK_RELEASE(p_accobj); + + CHK_RELEASE(p_toolbar); +} + +// Check Star button and their Name, Role, State. +TEST_F(AccessibilityTest, TestStarBtnStatusOnNewTab) { + HRESULT hr = S_OK; + IAccessible* p_accobj = NULL; + VARIANT button; + + // Get toolbar accessibility object. + IAccessible* p_toolbar = NULL; + GetToolbarWnd(&p_toolbar); + ASSERT_TRUE(NULL != p_toolbar); + + // Check button and it's Name, Role, State. + hr = GetStarButton(&p_accobj, &button); + // It is not a complete accessible object, as it is element. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + EXPECT_EQ(L"focusable", GetState(p_toolbar, button)); + + // Now, check Star status in different situations. + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + // Set URL and check button status. + scoped_ptr<TabProxy> tab1(window->GetTab(0)); + ASSERT_TRUE(tab1.get()); + std::wstring test_file1 = test_data_directory_; + file_util::AppendToPath(&test_file1, L"title1.html"); + tab1->NavigateToURL(net_util::FilePathToFileURL(test_file1)); + Sleep(kWaitForActionMsec); + EXPECT_EQ(L"focusable", GetState(p_toolbar, button)); + + // Add empty new tab and check status. + int old_tab_count = -1; + ASSERT_TRUE(window->GetTabCount(&old_tab_count)); + ASSERT_TRUE(window->ApplyAccelerator(IDC_NEWTAB)); + int new_tab_count; + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + // Check tab count. + ASSERT_GE(new_tab_count, old_tab_count); + // Also, check accessibility object's children. + Sleep(1000); + EXPECT_EQ(L"focusable", GetState(p_toolbar, button)); // ??? + + // Add new tab with URL and check status. + old_tab_count = new_tab_count; + std::wstring test_file2 = test_data_directory_; + file_util::AppendToPath(&test_file2, L"title1.html"); + ASSERT_TRUE(window->AppendTab(net_util::FilePathToFileURL(test_file2))); + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + // Check tab count. Also, check accessibility object's children. + ASSERT_GE(new_tab_count, old_tab_count); + Sleep(kWaitForActionMsec); + EXPECT_EQ(L"focusable", GetState(p_toolbar, button)); + + CHK_RELEASE(p_toolbar); +} + +// Check Back button and their Name, Role, State. +TEST_F(AccessibilityTest, TestBackButton) { + HRESULT hr = S_OK; + IAccessible* p_accobj = NULL; + VARIANT button; + + // Get toolbar accessibility object. + IAccessible* p_toolbar = NULL; + GetToolbarWnd(&p_toolbar); + ASSERT_TRUE(NULL != p_toolbar); + + // Check button and it's Name, Role, State. + hr = GetBackButton(&p_accobj, &button); + // It is not a complete accessible object, as it is element. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + + // Read it's properties. + EXPECT_EQ(L"Back", GetName(p_toolbar, button)); + EXPECT_EQ(L"drop down button", GetRole(p_toolbar, button)); + // State "has popup" only supported in XP and higher. + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + CHK_RELEASE(p_accobj); + + CHK_RELEASE(p_toolbar); +} + +// Check Back button and their Name, Role, State. +// This test is disabled. See bug 1119183. +TEST_F(AccessibilityTest, DISABLED_TestBackBtnStatusOnNewTab) { + HRESULT hr = S_OK; + IAccessible* p_accobj = NULL; + VARIANT button; + + // Get toolbar accessibility object. + IAccessible* p_toolbar = NULL; + GetToolbarWnd(&p_toolbar); + ASSERT_TRUE(NULL != p_toolbar); + + // Check button and it's Name, Role, State. + hr = GetBackButton(&p_accobj, &button); + // It is not complete accessible object, as it is element. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + // State "has popup" only supported in XP and higher. + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + + // Now check Back status in different situations. + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + int old_tab_count = -1; + int new_tab_count = -1; + + // Set URL and check button status. + scoped_ptr<TabProxy> tab1(window->GetTab(0)); + ASSERT_TRUE(tab1.get()); + std::wstring test_file1 = test_data_directory_; + file_util::AppendToPath(&test_file1, L"title1.html"); + tab1->NavigateToURL(net_util::FilePathToFileURL(test_file1)); + Sleep(kWaitForActionMsec); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable", GetState(p_toolbar, button)); + } + // Go Back and check status. + window->ApplyAccelerator(IDC_BACK); + Sleep(kWaitForActionMsec); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + + // Add empty new tab and check status. + ASSERT_TRUE(window->GetTabCount(&old_tab_count)); + ASSERT_TRUE(window->ApplyAccelerator(IDC_NEWTAB)); + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + // Check tab count. Also, check accessibility object's children. + ASSERT_GE(new_tab_count, old_tab_count); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + + // Add new tab with URL and check status. + old_tab_count = new_tab_count; + std::wstring test_file2 = test_data_directory_; + file_util::AppendToPath(&test_file2, L"title1.html"); + ASSERT_TRUE(window->AppendTab(net_util::FilePathToFileURL(test_file2))); + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + // Check tab count. Also, check accessibility object's children. + ASSERT_GE(new_tab_count, old_tab_count); + Sleep(kWaitForActionMsec); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + + CHK_RELEASE(p_toolbar); +} + +// Check Forward button and their Name, Role, State. +TEST_F(AccessibilityTest, TestForwardButton) { + HRESULT hr = S_OK; + IAccessible* p_accobj = NULL; + VARIANT button; + + // Get toolbar accessibility object. + IAccessible* p_toolbar = NULL; + GetToolbarWnd(&p_toolbar); + ASSERT_TRUE(NULL != p_toolbar); + + // Check button and it's Name, Role, State. + hr = GetForwardButton(&p_accobj, &button); + // It is not complete accessible object, as it is element. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + // Read it's properties. + EXPECT_EQ(L"Forward", GetName(p_toolbar, button)); + EXPECT_EQ(L"drop down button", GetRole(p_toolbar, button)); + // State "has popup" only supported in XP and higher. + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + CHK_RELEASE(p_accobj); + + CHK_RELEASE(p_toolbar); +} + +// Check Back button and their Name, Role, State. +// This test is disabled. See bug 1119183. +TEST_F(AccessibilityTest, DISABLED_TestForwardBtnStatusOnNewTab) { + HRESULT hr = S_OK; + IAccessible* p_accobj = NULL; + VARIANT button; + + // Get toolbar accessibility object. + IAccessible* p_toolbar = NULL; + GetToolbarWnd(&p_toolbar); + ASSERT_TRUE(NULL != p_toolbar); + + // Check button and it's Name, Role, State. + hr = GetForwardButton(&p_accobj, &button); + // It is not complete accessible object, as it is element. + ASSERT_TRUE(S_FALSE == hr); + ASSERT_TRUE(NULL == p_accobj); + ASSERT_TRUE(VT_I4 == button.vt); + // State "has popup" only supported in XP and higher. + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + + // Now check Back status in different situations. + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + int old_tab_count = -1; + int new_tab_count = -1; + + // Set URL and check button status. + scoped_ptr<TabProxy> tab1(window->GetTab(0)); + ASSERT_TRUE(tab1.get()); + std::wstring test_file1 = test_data_directory_; + file_util::AppendToPath(&test_file1, L"title1.html"); + tab1->NavigateToURL(net_util::FilePathToFileURL(test_file1)); + Sleep(kWaitForActionMsec); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + // Go Back and check status. + window->ApplyAccelerator(IDC_BACK); + Sleep(kWaitForActionMsec); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable", GetState(p_toolbar, button)); + } + // Go Forward and check status. + window->ApplyAccelerator(IDC_FORWARD); + Sleep(kWaitForActionMsec); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + + // Add empty new tab and check status. + ASSERT_TRUE(window->GetTabCount(&old_tab_count)); + ASSERT_TRUE(window->ApplyAccelerator(IDC_NEWTAB)); + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + // Check tab count. + ASSERT_GE(new_tab_count, old_tab_count); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + + // Add new tab with URL and check status. + old_tab_count = new_tab_count; + std::wstring test_file2 = test_data_directory_; + file_util::AppendToPath(&test_file2, L"title1.html"); + ASSERT_TRUE(window->AppendTab(net_util::FilePathToFileURL(test_file2))); + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + // Check tab count. + ASSERT_GE(new_tab_count, old_tab_count); + Sleep(kWaitForActionMsec); + if (win_util::GetWinVersion() > win_util::WINVERSION_2000) { + EXPECT_EQ(L"has popup, focusable, unavailable", + GetState(p_toolbar, button)); + } else { + EXPECT_EQ(L"focusable, unavailable", GetState(p_toolbar, button)); + } + + CHK_RELEASE(p_toolbar); +}
\ No newline at end of file diff --git a/chrome/test/accessibility/accessibility_util.cc b/chrome/test/accessibility/accessibility_util.cc new file mode 100644 index 0000000..43a79a8 --- /dev/null +++ b/chrome/test/accessibility/accessibility_util.cc @@ -0,0 +1,620 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "accessibility_util.h" +#include "constants.h" +#include "chrome/common/win_util.h" +#include "chrome/common/l10n_util.h" +#include "chrome/browser/xp_frame.h" +#include "chrome/browser/vista_frame.h" +#include "generated_resources.h" + +VARIANT g_var_self = {VT_I4, CHILDID_SELF}; + +HWND GetChromeBrowserWnd(IAccessible** ppi_access) { + HRESULT hr = S_OK; + HWND hwnd = NULL; + BSTR str_name; + std::wstring str_role; + + const std::wstring product_name = l10n_util::GetString(IDS_PRODUCT_NAME); + + // Get Chrome window handle. + if (win_util::ShouldUseVistaFrame()) { + hwnd = FindWindow(VISTA_FRAME_CLASSNAME, NULL); + } else { + hwnd = FindWindow(XP_FRAME_CLASSNAME, NULL); + } + + if (NULL == hwnd) { + if (ppi_access) + *ppi_access = NULL; + return hwnd; + } + + // Get accessibility object for Chrome, only if requested. + if (!ppi_access) { + return hwnd; + } + *ppi_access = NULL; + + // Get accessibility object for Chrome Main Window. If failed to get it, + // return only window handle. + IAccessible *pi_acc_root_win = NULL; + hr = AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, + reinterpret_cast<void**> + (&pi_acc_root_win)); + if ((S_OK != hr) || !pi_acc_root_win) { + return hwnd; + } + + + // Confirm if it is Chrome window using it's accessibility object's + // Name and Role property. If it's not the desired object, return only + // window handle. + hr = pi_acc_root_win->get_accName(g_var_self, &str_name); + if ((S_OK != hr) || (!str_name) || + (0 != _wcsicmp(str_name, product_name.c_str())) ) { + CHK_RELEASE(pi_acc_root_win); + return hwnd; + } + str_role = GetRole(pi_acc_root_win); + if (0 != str_role.compare(BROWSER_WIN_ROLE)) { + CHK_RELEASE(pi_acc_root_win); + return hwnd; + } + + // Get accessibility object for Chrome Window. If failed to get it, + // return only window handle. + INT64 child_cnt = GetChildCount(pi_acc_root_win); + VARIANT *var_array_child = + reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt), + sizeof(VARIANT))); + + if (!var_array_child) { + CHK_RELEASE(pi_acc_root_win); + return hwnd; + } + + hr = GetChildrenArray(pi_acc_root_win, var_array_child); + if (S_OK != hr) { + CHK_RELEASE(pi_acc_root_win); + return hwnd; + } + + // Fetch desired child (Chrome window) of Chrome Main Window. + IAccessible *pi_acc_app = NULL; + GetChildObject(pi_acc_root_win, var_array_child[CHROME_APP_ACC_INDEX], + &pi_acc_app); + if (!pi_acc_app) { + CHK_RELEASE(pi_acc_app); + return hwnd; + } + + // Confirm if it is Chrome application using it's accessibility object's + // Name and Role property. If it's not the desired object, return only + // window handle. + hr = pi_acc_app->get_accName(g_var_self, &str_name); + if ((S_OK != hr) || (!str_name) || + (0 != _wcsicmp(str_name, product_name.c_str())) ) { + CHK_RELEASE(pi_acc_app); + CHK_RELEASE(pi_acc_root_win); + return hwnd; + } + str_role = GetRole(pi_acc_app); + if (0 != str_role.compare(BROWSER_APP_ROLE)) { + CHK_RELEASE(pi_acc_app); + CHK_RELEASE(pi_acc_root_win); + return hwnd; + } + + // Get accessibility object for Chrome Client. If failed, return only + // window handle. + hr = GetChildrenArray(pi_acc_app, var_array_child); + if (S_OK != hr) { + CHK_RELEASE(pi_acc_app); + CHK_RELEASE(pi_acc_root_win); + return hwnd; + } + + // Chrome Window has only one child which is Chrome Client. + GetChildObject(pi_acc_app, var_array_child[CHROME_CLIENT_ACC_INDEX], + ppi_access); + + // Confirm if it is Chrome client using it's accessibility object's Name + // and Role property. If it's not the desired object, return only window + // handle. + hr = (*ppi_access)->get_accName(g_var_self, &str_name); + if ((S_OK != hr) || (!str_name) || + (0 != _wcsicmp(str_name, product_name.c_str())) ) { + CHK_RELEASE(*ppi_access); + } + str_role = GetRole(*ppi_access); + if (0 != str_role.compare(BROWSER_CLIENT_ROLE)) { + CHK_RELEASE(*ppi_access); + } + + CHK_RELEASE(pi_acc_app); + CHK_RELEASE(pi_acc_root_win); + return hwnd; +} + +HRESULT GetChildWndOf(std::wstring parent_name, unsigned int child_index, + IAccessible** ppi_access, VARIANT* child_var_id) { + HRESULT hr = S_OK; + + // Validate input and initialize. + if (!ppi_access && !child_var_id) + return E_INVALIDARG; + if (ppi_access) + *ppi_access = NULL; + if (child_var_id) + VariantInit(child_var_id); + + // Get accessibility object and window handle for Chrome parent. + IAccessible *pi_parent = NULL; + if (0 == parent_name.compare(BROWSER_STR)) + GetChromeBrowserWnd(&pi_parent); + if (0 == parent_name.compare(TOOLBAR_STR)) + GetToolbarWnd(&pi_parent); + if (0 == parent_name.compare(TABSTRIP_STR)) + GetTabStripWnd(&pi_parent); + + if (!pi_parent) + return E_FAIL; + + // Validate child index. + INT64 child_cnt = GetChildCount(pi_parent); + if (child_index >= child_cnt) { + CHK_RELEASE(pi_parent); + VariantClear(child_var_id); + return E_INVALIDARG; + } + + // Get array of child items of parent object. + VARIANT *var_array_child = + reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt), sizeof(VARIANT))); + if (var_array_child) { + hr = GetChildrenArray(pi_parent, var_array_child); + if (S_OK == hr) { + // Fetch Tabstrip which is child_index'th child of parent object. + if (ppi_access) { + hr = GetChildObject(pi_parent, var_array_child[child_index], + ppi_access); + } + if (child_var_id) { + VariantCopy(child_var_id, var_array_child+child_index); + } + } + free(var_array_child); + } + + CHK_RELEASE(pi_parent); + return hr; +} + +HRESULT GetTabStripWnd(IAccessible** ppi_access) { + return GetChildWndOf(BROWSER_STR, TABSTRIP_ACC_INDEX, ppi_access, NULL); +} + +HRESULT GetToolbarWnd(IAccessible** ppi_access) { + return GetChildWndOf(BROWSER_STR, TOOLBAR_ACC_INDEX, ppi_access, NULL); +} + +HRESULT GetBrowserMinimizeButton(IAccessible** ppi_access, + VARIANT* child_var_id) { + return GetChildWndOf(BROWSER_STR, CHROME_MIN_ACC_INDEX, ppi_access, + child_var_id); +} + +HRESULT GetBrowserMaximizeButton(IAccessible** ppi_access, + VARIANT* child_var_id) { + return GetChildWndOf(BROWSER_STR, CHROME_MAX_ACC_INDEX, ppi_access, + child_var_id); +} + +HRESULT GetBrowserRestoreButton(IAccessible** ppi_access, + VARIANT* child_var_id) { + return GetChildWndOf(BROWSER_STR, CHROME_RESTORE_ACC_INDEX, ppi_access, + child_var_id); +} + +HRESULT GetBrowserCloseButton(IAccessible** ppi_access, + VARIANT* child_var_id) { + return GetChildWndOf(BROWSER_STR, CHROME_CLOSE_ACC_INDEX, ppi_access, + child_var_id); +} + +HRESULT GetStarButton(IAccessible** ppi_access, VARIANT* child_var_id) { + return GetChildWndOf(TOOLBAR_STR, STAR_BTN_INDEX, ppi_access, child_var_id); +} + +HRESULT GetBackButton(IAccessible** ppi_access, VARIANT* child_var_id) { + return GetChildWndOf(TOOLBAR_STR, BACK_BTN_INDEX, ppi_access, child_var_id); +} + +HRESULT GetForwardButton(IAccessible** ppi_access, VARIANT* child_var_id) { + return GetChildWndOf(TOOLBAR_STR, FORWARD_BTN_INDEX, ppi_access, + child_var_id); +} + +HWND GetAddressBarWnd(IAccessible** ppi_access) { + HWND hwnd = NULL; + HWND hwnd_addr_bar = NULL; + + // // Initialize, if requested. + if (ppi_access) { + *ppi_access = NULL; + } + + // Get window handle for Chrome Browser. + hwnd = GetChromeBrowserWnd(NULL); + if (NULL != hwnd) { + // Get AddressBar/OmniBox (edit box) window handle. + hwnd_addr_bar = FindWindowEx(hwnd, 0, CHROME_AUTOCOMPLETE_EDIT, NULL); + + // Get accessibility object for address bar, if requested. + if (ppi_access && hwnd_addr_bar) { + AccessibleObjectFromWindow(hwnd_addr_bar, OBJID_WINDOW, IID_IAccessible, + reinterpret_cast<void**>(ppi_access)); + } + } + + return hwnd_addr_bar; +} + +HWND GetFindTextWnd(IAccessible** ppi_access) { + HWND hwnd = NULL; + HWND hwnd_find = NULL; + + // Initialize, if requested. + if (ppi_access) { + *ppi_access = NULL; + } + + // Get window handle for Chrome Browser. + hwnd = GetChromeBrowserWnd(NULL); + if (NULL != hwnd) { + // Get handle of a window, which is contains edit box for Find string. + hwnd_find = FindWindowEx(hwnd, 0, CHROME_HWND_VIEW_CONTAINER, NULL); + + // Get accessibility object, if requested. + if (ppi_access && hwnd_find) { + AccessibleObjectFromWindow(hwnd_find, OBJID_WINDOW, IID_IAccessible, + reinterpret_cast<void**>(ppi_access)); + } + } + + return hwnd_find; +} + +HWND GetAuthWnd(IAccessible** ppi_access) { + HWND hwnd = NULL; + HWND hwnd_tab = NULL; + HWND hwnd_auth = NULL; + + // Initialize, if requested. + if (ppi_access) { + *ppi_access = NULL; + } + + // Get window handle for Chrome Browser. + hwnd = GetChromeBrowserWnd(NULL); + if (NULL != hwnd) { + // Get window handle for tab. + hwnd_tab = FindWindowEx(hwnd, 0, CHROME_TAB_CONTENTS, NULL); + if (!hwnd_tab) + return hwnd_auth; + + // Get handle for Authentication window. + hwnd_auth = FindWindowEx(hwnd_tab, 0, CHROME_HWND_VIEW_CONTAINER, + AUTH_TITLE); + + // Get accessibility object, if requested. + if (ppi_access && hwnd_auth) { + AccessibleObjectFromWindow(hwnd_auth, OBJID_WINDOW, IID_IAccessible, + reinterpret_cast<void**>(ppi_access)); + } + } + + return hwnd_auth; +} + +HRESULT GetChildObject(IAccessible* pi_access, VARIANT var_child, + IAccessible** ppi_child_access) { + HRESULT hr = S_OK; + IDispatch *p_dispatch = NULL; + + // Validate input. + if ( (pi_access == NULL) || + (ppi_child_access == NULL) ) { + return E_INVALIDARG; + } + + // Check the child type and fetch object accordingly. + if (var_child.vt == VT_DISPATCH) { + var_child.pdispVal-> + QueryInterface(IID_IAccessible, + reinterpret_cast<void**>(ppi_child_access)); + } else if (var_child.vt == VT_I4) { + hr = pi_access->get_accChild(var_child, &p_dispatch); + if ( (hr == S_OK) && + (p_dispatch != NULL) ) { + p_dispatch->QueryInterface(IID_IAccessible, + reinterpret_cast<void**>(ppi_child_access)); + CHK_RELEASE(p_dispatch); + } + } + + return hr; +} + +HRESULT GetParentObject(IAccessible* pi_access, + IAccessible** ppi_parent_access) { + HRESULT hr = S_OK; + IDispatch *p_dispatch = NULL; + + // Validate input. + if ( (pi_access == NULL) || + (ppi_parent_access == NULL) ) { + return E_INVALIDARG; + } + + // Fetch parent object. + hr = pi_access->get_accParent(&p_dispatch); + if ( (hr == S_OK) && + (p_dispatch != NULL) ) { + p_dispatch->QueryInterface(IID_IAccessible, + reinterpret_cast<void**>(ppi_parent_access)); + CHK_RELEASE(p_dispatch); + } + + return hr; +} + +INT64 GetChildCount(IAccessible* pi_access) { + HRESULT hr = S_OK; + long child_cnt = 0; + + // Validate input. Object can have 0 children. So return -1 on invalid input. + if (pi_access == NULL) { + return -1; + } + + // Get child count. + pi_access->get_accChildCount(&child_cnt); + return child_cnt; +} + +HRESULT GetChildrenArray(IAccessible* pi_access, VARIANT* var_array_child) { + HRESULT hr = S_OK; + INT64 child_start = 0; + long child_obtained = 0; + INT64 child_cnt = GetChildCount(pi_access); + + // Validate input. + if ((pi_access == NULL) || (var_array_child == NULL)) { + return E_INVALIDARG; + } + + // Validate every item and initialize it. + int i = 0; + for (; (i < child_cnt) && (var_array_child+i); i++) { + VariantInit(var_array_child+i); + } + + // If all items in array are not initialized, return error. + if (i != child_cnt) { + return E_INVALIDARG; + } + + // Get IDs of child items. + AccessibleChildren(pi_access, + LONG(child_start), + LONG(child_cnt), + var_array_child, + &child_obtained); + return hr; +} + +HRESULT ActivateWnd(IAccessible *pi_access, HWND hwnd) { + HRESULT hr = S_OK; + + // Select and focus the object, if accessibility object is specified. + if (pi_access) { + hr = pi_access->accSelect(SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION, + g_var_self); + } + + // Send message to window, if window handle is specified. + if (hwnd) { + SetActiveWindow(hwnd); + } + + return hr; +} + +BSTR GetTabName(INT64 tab_index) { + HRESULT hr = S_OK; + BSTR str_name; + + // Validate tab index specified. + if (tab_index < 1) + return NULL; + + // Get accessibility object for Tabstrip. + IAccessible *pi_acc_strip = NULL; + GetTabStripWnd(&pi_acc_strip); + + // Get Tab from Tabstrip and return it's Name. + if (pi_acc_strip) { + INT64 child_cnt = GetChildCount(pi_acc_strip); + VARIANT *var_array_child = + reinterpret_cast<VARIANT*>(calloc(size_t(child_cnt), sizeof(VARIANT))); + if (var_array_child) { + // Get tab object. tab_index = index in child array, because first child + // in tabstrip is '+' button. + hr = GetChildrenArray(pi_acc_strip, var_array_child); + if (S_OK == hr) { + IAccessible *pi_access_temp = NULL; + hr = GetChildObject(pi_acc_strip, var_array_child[tab_index], + &pi_access_temp); + if ((S_OK == hr) && + (var_array_child[tab_index].vt == VT_DISPATCH) && + (pi_access_temp) ) { + hr = pi_access_temp->get_accName(g_var_self, &str_name); + } else if (var_array_child[tab_index].vt == VT_I4) { + hr = pi_acc_strip->get_accName(var_array_child[1], &str_name); + } + CHK_RELEASE(pi_acc_strip); + return str_name; + } + } + + CHK_RELEASE(pi_acc_strip); + } + + return NULL; +} + +INT64 GetTabCnt() { + // Get accessibility object for Tabstrip. + IAccessible *pi_acc_strip = NULL; + GetTabStripWnd(&pi_acc_strip); + + // If Tabstrip is invalid, return -1, to indicate error. + if (!pi_acc_strip) { + return -1; + } + + // Get child count. + INT64 child_cnt = 0; + if (pi_acc_strip) { + child_cnt = GetChildCount(pi_acc_strip); + CHK_RELEASE(pi_acc_strip); + } + + // Don't count 1st child as it is '+' button. + return (child_cnt-1); +} + +std::wstring GetName(IAccessible* pi_access, VARIANT child) { + HRESULT hr = S_OK; + + // Validate input. + if (NULL == pi_access) { + return std::wstring(); + } + + // Get Name. + BSTR name; + hr = pi_access->get_accName(child, &name); + if (S_OK != hr) + return std::wstring(); + + return std::wstring(name); +} + +std::wstring GetRole(IAccessible* pi_access, VARIANT child) { + HRESULT hr = S_OK; + LPTSTR role_str = NULL; + + // Validate input. + if (NULL == pi_access) { + return std::wstring(); + } + + // Get Role. + VARIANT role; + VariantInit(&role); + hr = pi_access->get_accRole(child, &role); + if (S_OK != hr || VT_I4 != role.vt) { + VariantClear(&role); + return std::wstring(); + } + + // Get Role string. + unsigned int role_length = GetRoleText(role.lVal, NULL, 0); + role_str = (LPTSTR)calloc(role_length + 1, sizeof(TCHAR)); + if (role_str) + GetRoleText(role.lVal, role_str, role_length + 1); + + VariantClear(&role); + return std::wstring(role_str); +} + +std::wstring GetState(IAccessible* pi_access, VARIANT child) { + HRESULT hr = S_OK; + LPTSTR state_str = NULL; + std::wstring complete_state; + + // Validate input. + if (NULL == pi_access) { + return std::wstring(); + } + + // Get State. + VARIANT state; + VariantInit(&state); + hr = pi_access->get_accState(child, &state); + if (S_OK != hr || VT_I4 != state.vt) { + VariantClear(&state); + return std::wstring(); + } + + // Treat the "normal" state separately. + if (state.vt == 0) { + unsigned int state_length = GetStateText(state.lVal, NULL, 0); + state_str = (LPTSTR)calloc(state_length + 1, sizeof(TCHAR)); + if (state_str) { + GetStateText(state.lVal, state_str, state_length + 1); + complete_state = std::wstring(state_str); + } + } else { + // Number of bits. + UINT bit_cnt = 32; + // Convert state flags to comma separated list. + for (DWORD dwStateBit = 0x80000000; bit_cnt; bit_cnt--, dwStateBit >>= 1) { + if (state.lVal & dwStateBit) { + unsigned int state_length = GetStateText(dwStateBit, NULL, 0); + state_str = (LPTSTR)calloc(state_length + 1, sizeof(TCHAR)); + if (state_str) { + GetStateText(dwStateBit, state_str, state_length + 1); + if (complete_state.length() > 0) + complete_state.append(L", "); + complete_state.append(state_str); + free(state_str); + } + } + } + } + + VariantClear(&state); + return complete_state; +} diff --git a/chrome/test/accessibility/accessibility_util.h b/chrome/test/accessibility/accessibility_util.h new file mode 100644 index 0000000..77d0f03 --- /dev/null +++ b/chrome/test/accessibility/accessibility_util.h @@ -0,0 +1,136 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_ACCISSIBILITY_ACCISSIBILITY_UTIL_H__ +#define CHROME_TEST_ACCISSIBILITY_ACCISSIBILITY_UTIL_H__ + +#include <Oleacc.h> +#include <iostream> + +/////////////////////////////////////////////////////////////////////////////// +// Functions and Globals which are using IAccessible interface. +// These are the wrappers to fetch accessible object interface and properties. +/////////////////////////////////////////////////////////////////////////////// + +// Variant ID pointing to object itself. +extern VARIANT g_var_self; + +// Returns window handle to Chrome Browser. Retrives it's(having role as +// client) IAccessible pointer, if requested. +HWND GetChromeBrowserWnd(IAccessible** ppi_access); + +// Returns IAccessible pointer of object's child window, provided parent's name +// and it's 0 based child index. If child is element and not complete object, +// it's variant id is returned with S_FALSE. +HRESULT GetChildWndOf(std::wstring parent_name, unsigned int child_index, + IAccessible** ppi_access, VARIANT* child_var_id); + +// Returns IAccessible pointer for Tabstrip. It does not have window handle. +HRESULT GetTabStripWnd(IAccessible** ppi_access); + +// Returns IAccessible pointer for Toolbar. It does not have window handle. +HRESULT GetToolbarWnd(IAccessible** ppi_access); + +// Returns handle to OmniBox(AddressBar) and IAccessible pointer, if requested. +HWND GetAddressBarWnd(IAccessible** ppi_access); + +// Returns handle to Find box and IAccessible pointer, if requested. +HWND GetFindTextWnd(IAccessible** ppi_access); + +// Returns handle to authentication dialog and IAccessible pointer, if +// requested. +HWND GetAuthWnd(IAccessible** ppi_access); + +// Fetches IAccessible pointer for a child of given the IAccessible pointer +// and desired child id. +HRESULT GetChildObject(IAccessible* pi_access, VARIANT var_child, + IAccessible** ppi_child_access); + +// Fetches IAccessible pointer for a parent of specified IAccessible pointer. +HRESULT GetParentObject(IAccessible* pi_access, + IAccessible** ppi_parent_access); + +// Returns no. of child items of specified IAccessible pointer. If input +// parameter is NULL, -1 is returned. +INT64 GetChildCount(IAccessible* pi_access); + +// Extracts (VARIANT)array of child items of specified IAccessible pointer. +HRESULT GetChildrenArray(IAccessible* pi_access, VARIANT* var_array_child); + +// Activates specified window using IAccessible pointer and/or window handle. +HRESULT ActivateWnd(IAccessible *pi_access, HWND hwnd); + +// Returns title of tab whose index is specified. Tab index starts from 1. +BSTR GetTabName(INT64 tab_index); + +// Returns no. of tabs in tabstrip. If processing fails, it returns -1. +INT64 GetTabCnt(); + +// Returns Name of specified IAccessible pointer or it's child specified by +// variant. +std::wstring GetName(IAccessible* pi_access, VARIANT child = g_var_self); + +// Returns Role of specified IAccessible pointer or it's child specified by +// variant. +std::wstring GetRole(IAccessible* pi_access, VARIANT child = g_var_self); + +// Returns State of specified IAccessible pointer or it's child specified by +// variant. +std::wstring GetState(IAccessible* pi_access, VARIANT child = g_var_self); + +// Returns IAccessible pointer for Chrome Minimize Button. It does not have +// window handle. +HRESULT GetBrowserMinimizeButton(IAccessible** ppi_access, + VARIANT* child_var_id); + +// Returns IAccessible pointer for Chrome Maximize Button. It does not have +// window handle. +HRESULT GetBrowserMaximizeButton(IAccessible** ppi_access, + VARIANT* child_var_id); + +// Returns IAccessible pointer for Chrome Restore Button. It does not have +// window handle. +HRESULT GetBrowserRestoreButton(IAccessible** ppi_access, + VARIANT* child_var_id); + +// Returns IAccessible pointer for Chrome Close Button. It does not have +// window handle. +HRESULT GetBrowserCloseButton(IAccessible** ppi_access, VARIANT* child_var_id); + +// Returns IAccessible pointer for Star Button. It does not have window handle. +HRESULT GetStarButton(IAccessible** ppi_access, VARIANT* child_var_id); + +// Returns IAccessible pointer for Back Button. It does not have window handle. +HRESULT GetBackButton(IAccessible** ppi_access, VARIANT* child_var_id); + +// Returns IAccessible pointer for Forward Button. It does not have window +// handle. +HRESULT GetForwardButton(IAccessible** ppi_access, VARIANT* child_var_id); + +#endif // CHROME_TEST_ACCISSIBILITY_ACCISSIBILITY_UTIL_H__ diff --git a/chrome/test/accessibility/browser_impl.cc b/chrome/test/accessibility/browser_impl.cc new file mode 100644 index 0000000..50eb9f7 --- /dev/null +++ b/chrome/test/accessibility/browser_impl.cc @@ -0,0 +1,551 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/accessibility/browser_impl.h" + +#include <shellapi.h> + +#include "chrome/test/accessibility/accessibility_util.h" +#include "chrome/test/accessibility/keyboard_util.h" +#include "chrome/test/accessibility/registry_util.h" + +bool CBrowserImpl::Launch(void) { + // TODO: Check if chrome already running. + BSTR chrome_path = SysAllocString(GetChromeExePath()); + BOOL bool_return = FALSE; + + // Initialize and fill up structure. + SHELLEXECUTEINFO shell_execute_info; + memset(&shell_execute_info, 0, sizeof(SHELLEXECUTEINFO)); + shell_execute_info.cbSize = sizeof(SHELLEXECUTEINFO); + // To get Process handle. + shell_execute_info.fMask = SEE_MASK_NOCLOSEPROCESS; + shell_execute_info.nShow = SW_SHOW; + shell_execute_info.lpFile = + reinterpret_cast<TCHAR*>(malloc(sizeof(TCHAR) * + SysStringLen(chrome_path))); + _tcscpy_s((TCHAR*)(shell_execute_info.lpFile), SysStringLen(chrome_path), + chrome_path); + + // Execute. + bool_return = ShellExecuteEx(&shell_execute_info); + + if (bool_return && + (INT64(shell_execute_info.hInstApp) > 32) ) { + // TODO: Maintain instance and process handle. + + // Maintain active tab index. + SetActiveTabIndex(1); + + // Create initial tab collection. + UpdateTabCollection(); + + // Chrome launched. + return true; + } + + return false; +} + +bool CBrowserImpl::Quit(void) { + // Cleanup. + EraseTabCollection(); + + // Send close message to browser window. + HWND hwnd = GetChromeBrowserWnd(NULL); + if (!hwnd) + return false; + SendMessage(hwnd, WM_CLOSE, 0, 0); + return true; +} + +bool CBrowserImpl::ActivateTab(const INT64 index) { + // Validate index specified. + if (index < 1) { + return false; + } + + // Goto next tab till focused at desired tab. + // TODO: Change implementation when DoDefaultAction() for Tab is exported. + while (active_tab_index_ != index) { + GoToNextTab(NULL); + } + return true; +} + +bool CBrowserImpl::GetActiveTabURL(BSTR* url) { + // Validate input. + if (!url) + return false; + + // TODO: Implement. + return true; +} + +bool CBrowserImpl::GetActiveTabTitle(BSTR* title) { + if (!title) + return false; + + BSTR tab_title = SysAllocString(GetTabName(active_tab_index_)); + *title = SysAllocString(tab_title); + return true; +} + +bool CBrowserImpl::GetActiveTabIndex(INT64* index) { + if (!index) + return false; + + *index = active_tab_index_; + return true; +} + +void CBrowserImpl::SetActiveTabIndex(INT64 index) { + if ((index >= MIN_TAB_INDEX_DIGIT) && (index <= GetTabCnt())) + active_tab_index_ = index; + return; +} + +bool CBrowserImpl::GetActiveTab(CTabImpl** tab) { + return GetTab(active_tab_index_, tab); +} + +bool CBrowserImpl::GetTabCount(INT64* count) { + if (!count) + return false; + + *count = GetTabCnt(); + return true; +} + +bool CBrowserImpl::GetBrowserProcessCount(INT64* count) { + if (!count) + return false; + + // TODO: Add your implementation code here + + return true; +} + +bool CBrowserImpl::GetBrowserTitle(BSTR* title) { + if (!title) + return false; + + HWND hwnd = GetChromeBrowserWnd(NULL); + if (!hwnd) + return false; + + int text_length = GetWindowTextLength(hwnd); + *title = SysAllocStringLen(NULL, text_length); + GetWindowText(hwnd, *title, text_length); + return true; +} + +bool CBrowserImpl::AddTab(CTabImpl** tab) { + // Add new tab. + HWND hwnd = GetChromeBrowserWnd(NULL); + if (!hwnd) + return false; + ClickKey(hwnd, VK_CONTROL, 'T'); + + // Update active tab index. + INT64 new_tab_index = GetTabCnt(); + if (-1 == new_tab_index) + return false; + SetActiveTabIndex(new_tab_index); + + // Fill object. + CTabImpl *new_tab = new CTabImpl(); + if (!new_tab) + return false; + ChromeTab* tab_data = new_tab->InitTabData(); + new_tab->PutIndex(new_tab_index); + new_tab->PutTitle(GetTabName(new_tab_index)); + new_tab->SetBrowser(this); + + // Update tab collection. + tab_collection_.push_back(tab_data); + + // Create tab object, if requested. + if (tab) + *tab = new_tab; + + return true; +} + +bool CBrowserImpl::GetTab(const INT64 index, CTabImpl** tab) { + // Create tab object, if requested. + if (!tab) + return false; + + if (index > GetTabCnt()) + return false; + + *tab = new CTabImpl(); + if (!*tab) + return false; + + // Fill object. + ChromeTab* tab_data = (*tab)->InitTabData(); + (*tab)->PutIndex(index); + (*tab)->PutTitle(GetTabName(index)); + (*tab)->SetBrowser(this); + + return true; +} + +bool CBrowserImpl::GoToTab(const INT64 index, CTabImpl** tab) { + // Validate input. + if (index > MAX_TAB_INDEX_DIGIT) + return false; + + // Stay on current tab, if index doesnot exist. + if ((0 == index) || (GetTabCnt() < index)) + return true; + + // Move to a tab (indexed 1 to 9). + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (pi_access && hwnd) { + // Activate main window and operate key Ctrl+digit. + ActivateWnd(pi_access, hwnd); + ClickKey(hwnd, VK_CONTROL, WORD('0'+index)); + CHK_RELEASE(pi_access); + + // Set focused tab index. + active_tab_index_ = index; + // Return tab object. + if (tab) { + return GetTab(active_tab_index_, tab); + } + } + + return false; +} + +bool CBrowserImpl::GoToNextTab(CTabImpl** tab) { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (pi_access && hwnd) { + // Activate main window and operate key Ctrl+Tab. + ActivateWnd(pi_access, hwnd); + ClickKey(hwnd, VK_CONTROL, VK_TAB); + CHK_RELEASE(pi_access); + + // Set focused tab index. + if (active_tab_index_ == GetTabCnt()) { + active_tab_index_ = 1; + } else { + active_tab_index_ = active_tab_index_ + 1; + } + + // Return tab object. + if (tab) { + return GetTab(active_tab_index_, tab); + } + } + + return false; +} + +bool CBrowserImpl::GoToPrevTab(CTabImpl** tab) { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (pi_access && hwnd) { + // Activate main window and operate key Ctrl+Tab. + ActivateWnd(pi_access, hwnd); + ClickKey(hwnd, VK_SHIFT, VK_CONTROL, VK_TAB); + CHK_RELEASE(pi_access); + + // Set focused tab index. + if (active_tab_index_ == 1) { + active_tab_index_ = GetTabCnt(); + } else { + active_tab_index_ = active_tab_index_ - 1; + } + + // Return tab object. + if (tab) { + return GetTab(active_tab_index_, tab); + } + } + + return false; +} + +bool CBrowserImpl::WaitForChromeToBeVisible(const INT64 interval, + const INT64 timeout, + bool* visible) { + IAccessible *pi_access = NULL; + INT64 time_elapsed = 0; + *visible = false; + + // Check and wait. + while (timeout >= time_elapsed) { + GetTabStripWnd(&pi_access); + if (pi_access) { + *visible = true; + CHK_RELEASE(pi_access); + return true; + } + Sleep(DWORD(interval)); + time_elapsed = time_elapsed + interval; + } + + return false; +} + +bool CBrowserImpl::WaitForTabCountToChange(const INT64 interval, + const INT64 timeout, + bool* changed) { + // TODO: Add your implementation code here + + return true; +} + +bool CBrowserImpl::WaitForTabToBecomeActive(const INT64 index, + const INT64 interval, + const INT64 timeout, + bool* activated) { + // TODO: Add your implementation code here + + return true; +} + +bool CBrowserImpl::ApplyAccelerator(VARIANT keys) { + // Input should be -array of enum or strings + // or -IDispatch (jscript array object). + if ((keys.vt != (VT_ARRAY|VT_BSTR)) && // Array of string values. + (keys.vt != (VT_ARRAY|VT_I4)) && // Array of enum values. + (!(keys.vt & VT_DISPATCH)) ) { // Object. + return false; + } + + // Array to store keys in a single combination. Currently, valid keyboard + // -input combination can constitute of at the most 3 keys. + KEYBD_KEYS key_value[3]; + // Initialize key count. + int key_cnt = 0; + // Get variant array from object. + IDispatch *disp = NULL; + + // Not array of string values or integers. + if ((keys.vt != (VT_ARRAY|VT_BSTR)) && + (keys.vt != (VT_ARRAY|VT_I4)) ) { + // Retrive IDispatch. + if (keys.vt & VT_BYREF) + disp = *(keys.ppdispVal); + else + disp = keys.pdispVal; + + // Get array length. + DISPPARAMS params; + FillMemory(¶ms, sizeof(DISPPARAMS), 0); + VARIANT res; + DISPID id; + LPOLESTR ln = L"length"; + if (S_OK != disp->GetIDsOfNames(IID_NULL, &ln, 1, LOCALE_USER_DEFAULT, + &id)) { + return false; + } + + if (S_OK != disp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, + DISPATCH_PROPERTYGET, ¶ms, &res, NULL, + NULL)) { + return false; + } + + VARIANT len; + VariantInit(&len); + VariantChangeType(&len, &res, 0, VT_I4); + if (len.lVal > 3) + return false; + key_cnt = len.lVal; + + // Add elements to safe array. + for (int i = 0; i < len.lVal; i++) { + // Fetch element. + wchar_t wstr[5]; + memset(wstr, 0, 5*sizeof(wchar_t)); + wsprintf(wstr, L"%d", i); + LPOLESTR olestr = wstr; + + if (S_OK != disp->GetIDsOfNames(IID_NULL, &olestr, 1, + LOCALE_USER_DEFAULT, &id)) { + return false; + } + + if (S_OK != disp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, + DISPATCH_PROPERTYGET, ¶ms, &res, NULL, + NULL)) { + return false; + } + + VARIANT value; + VariantInit(&value); + VariantChangeType(&value, &res, 0, VT_BSTR); + + // Translate and add key to array. + key_value[i] = GetKeybdKeysVal(value.bstrVal); + + VariantClear(&value); + } + + VariantClear(&len); + } else { + // Directly fetch array. + SAFEARRAY *key_safe = NULL; + key_safe = V_ARRAY(&keys); + + // Operate on Variant Array. + HRESULT hr = S_OK; + LONG cElements, lLBound, lUBound; + + // Array is not 1-dimentional. + if (SafeArrayGetDim(key_safe) != 1) + return false; + + // Get array bounds. + hr = SafeArrayGetLBound(key_safe, 1, &lLBound); + if (S_OK !=hr) + return false; + hr = SafeArrayGetUBound(key_safe, 1, &lUBound); + if (S_OK !=hr) + return false; + + // Key combination can be of maximum 3 keys. + cElements = lUBound-lLBound+1; + if (cElements > 3) + return false; + key_cnt = cElements; + + // Read the data in array. + if (keys.vt == (VT_ARRAY|VT_I4)) { + KEYBD_KEYS *read_keys; + hr = SafeArrayAccessData(key_safe, + reinterpret_cast<void **>(&read_keys)); + if (S_OK !=hr) + return false; + for (int i = 0; i < cElements; i++) { + key_value[i] = read_keys[i]; + } + } else if (keys.vt == (VT_ARRAY|VT_BSTR)) { + BSTR *key_str_value; + hr = SafeArrayAccessData(key_safe, + reinterpret_cast<void **>(&key_str_value)); + if (S_OK !=hr) + return false; + + // Translate and add key to array. + for (int i = 0; i < cElements; i++) { + key_value[i] = GetKeybdKeysVal(key_str_value[i]); + } + } + } + + // Focus on main window and operate keys. + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (pi_access || hwnd) + ActivateWnd(pi_access, hwnd); + + if (1 == key_cnt) + ClickKey(hwnd, key_value[0]); + else if (2 == key_cnt) + ClickKey(hwnd, key_value[0], key_value[1]); + else if (3 == key_cnt) + ClickKey(hwnd, key_value[0], key_value[1], key_value[2]); + + CHK_RELEASE(pi_access); + + return true; +} + +void CBrowserImpl::UpdateTabCollection(void) { + // Get tab count and browser title. + INT64 tab_cnt = GetTabCnt(); + BSTR browser_title; + GetBrowserTitle(&browser_title); + + // Check tab-collection size and no. of existing tabs, + // work accordingly. + + // First time creation + if (0 == tab_collection_.size()) { + EraseTabCollection(); + for (int i = 0; i < tab_cnt; i++) { + tab_collection_[i]->index_ = i + 1; + tab_collection_[i]->title_ = + SysAllocString(GetTabName(tab_collection_[i]->index_)); + if (browser_title == tab_collection_[i]->title_) { + active_tab_index_ = tab_collection_[i]->index_; + } + } + } + + // TODO: If tabs are swapped. + // Add implementation here. +} + +void CBrowserImpl::EraseTabCollection(void) { + std::vector<ChromeTab*>::iterator tab_iterator; + for (tab_iterator = tab_collection_.begin(); + tab_iterator != tab_collection_.end(); + tab_iterator++) { + // Relese memory used for data. + CHK_DELETE(*tab_iterator); + } + tab_collection_.clear(); +} + +void CBrowserImpl::CloseTabFromCollection(INT64 index) { + std::vector <ChromeTab*>::size_type collection_size = tab_collection_.size(); + // Validate tab index. + if ((index < MIN_TAB_INDEX_DIGIT) || + (static_cast<unsigned int>(index) > collection_size) ) + return; + + // Index starts from 1. + tab_collection_.erase(tab_collection_.begin() + static_cast<int>(index) - 1); + + // Now update tab collection data. + collection_size = tab_collection_.size(); + + // Check if tab deleted is last tab. + if (index-1 == collection_size) { + // Change active tab index, only if tab deleted is last tab. + active_tab_index_ = index - 1; + } else { + for (std::vector <ChromeTab*>::size_type i = + static_cast<unsigned int>(index) - 1; + i < collection_size; + i++) { + tab_collection_[i]->index_--; + } + } +} diff --git a/chrome/test/accessibility/browser_impl.h b/chrome/test/accessibility/browser_impl.h new file mode 100644 index 0000000..51fda43 --- /dev/null +++ b/chrome/test/accessibility/browser_impl.h @@ -0,0 +1,134 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_ACCISSIBILITY_BROWSER_IMPL_H__ +#define CHROME_TEST_ACCISSIBILITY_BROWSER_IMPL_H__ + +#include <vector> + +#include "tab_impl.h" + +///////////////////////////////////////////////////////////////////// +// CBrowserImpl +// It is a wrapper to Browser specific functionalities. +// Note: +// In most of the tasks, keyboard messages are used for now. +// DoDefaultAction() will be called on accessibility objects, +// once implementation is available in chrome accessibility server. +// And keyboard messages will be tested using ApplyAccelerator(). +///////////////////////////////////////////////////////////////////// + +class CBrowserImpl { + public: + CBrowserImpl() { + active_tab_index_ = 0; + } + + // Starts Chrome. Sets active tab index. + bool Launch(void); + + // Closes Chrome. + bool Quit(void); + + // Activates the specified tab. + bool ActivateTab(const INT64 index); + + // Returns URL of the active tab. + bool GetActiveTabURL(BSTR* url); + + // Gets active tab's title. + bool GetActiveTabTitle(BSTR* title); + + // Gets active tab index. + bool GetActiveTabIndex(INT64* index); + + // Returns active tab object. + bool GetActiveTab(CTabImpl** tab); + + // Returns no. of tabs in tabstrip. + bool GetTabCount(INT64* count); + + bool GetBrowserProcessCount(INT64* count); + + // Reads browser title, which is also a active tab's title + bool GetBrowserTitle(BSTR* title); + + // Adds new tab. Maintain current active tab index. + // Returns created tab, if requested. + bool AddTab(CTabImpl** tab); + + // Returns tab object of specified index. + bool GetTab(const INT64 index, CTabImpl** tab); + + // Activate tab of specified index. Maintain current active tab index. + // Returns created tab, if requested. + bool GoToTab(const INT64 index, CTabImpl** tab); + + // Move to next tab. Maintain current active tab index. + // Returns created tab, if requested. + bool GoToNextTab(CTabImpl** tab); + + // Move to previous tab. Maintain current active tab index. + // Returns created tab, if requested. + bool GoToPrevTab(CTabImpl** tab); + + // Wait for chrome window to be visible. It checks for accessibility object + // for tabstrip after every 'interval' for the specified 'timeout'. + bool WaitForChromeToBeVisible(const INT64 interval, const INT64 timeout, + bool* visible); + bool WaitForTabCountToChange(const INT64 interval, const INT64 timeout, + bool* changed); + bool WaitForTabToBecomeActive(const INT64 index, const INT64 interval, + const INT64 timeout, bool* activated); + + // Sends keyboard message. Sends accelerators. + bool ApplyAccelerator(VARIANT keys); + + // Sets active tab index. + void SetActiveTabIndex(INT64 index); + + // Removed tab from tab collection vector. + void CloseTabFromCollection(INT64 index); + + // Updates tab collection vector + void UpdateTabCollection(void); + + // Removes tab from tab collection vector. + void EraseTabCollection(void); + + private: + // Index of active tab. + INT64 active_tab_index_; + + // Collection of tab data. + std::vector<ChromeTab*> tab_collection_; +}; + + +#endif // CHROME_TEST_ACCISSIBILITY_BROWSER_IMPL_H__ diff --git a/chrome/test/accessibility/constants.h b/chrome/test/accessibility/constants.h new file mode 100644 index 0000000..bb60d9e --- /dev/null +++ b/chrome/test/accessibility/constants.h @@ -0,0 +1,134 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_ACCISSIBILITY_CONSTANTS_H__ +#define CHROME_TEST_ACCISSIBILITY_CONSTANTS_H__ + +#include <windows.h> +#include <tchar.h> + +/////////////////////////////////////////////////////////////////// +// Constant Definitations specific to Chrome Accessibility Tests. +/////////////////////////////////////////////////////////////////// + +// Safe delete and release operations. +#define CHK_RELEASE(obj) { if (obj) { (obj)->Release(); (obj) = NULL; } } +#define CHK_DELETE(obj) { if (obj) { delete (obj); (obj) = NULL; } } + + +// Chrome Accessibility Tests specific strings. +#define CHROME_PATH _T("C:\\Program Files\\Google\\Chrome\\Chrome.exe") +#define CHROME_VIEWS_TEXT_FIELD_EDIT _T("ChromeViewsTextFieldEdit") +#define CHROME_AUTOCOMPLETE_EDIT _T("Chrome_AutocompleteEdit") +#define CHROME_VIEWS_NATIVE_CTRL_CONTNR _T("ChromeViewsNativeControlContainer") +#define CHROME_HWND_VIEW_CONTAINER _T("Chrome_HWNDViewContainer_0") +#define STD_BUTTON _T("Button") +#define AUTH_TITLE _T("Authentication Required - Chrome") +#define CHROME_TAB_CONTENTS _T("Chrome_TabContents") + +#define BROWSER_WIN_ROLE _T("window") +#define BROWSER_APP_ROLE _T("application") +#define BROWSER_CLIENT_ROLE _T("client") + +#define CHROME_APP_ACC_INDEX (3) +#define CHROME_CLIENT_ACC_INDEX (0) + +// Chrome Client chidren. +#define TOOLBAR_ACC_INDEX (0) +#define TABSTRIP_ACC_INDEX (1) +#define CHROME_MIN_ACC_INDEX (3) +#define CHROME_MAX_ACC_INDEX (4) +#define CHROME_RESTORE_ACC_INDEX (5) +#define CHROME_CLOSE_ACC_INDEX (6) + +// Toolbar children. +#define BACK_BTN_INDEX (0) +#define FORWARD_BTN_INDEX (1) +#define RELOAD_BTN_INDEX (2) +#define STAR_BTN_INDEX (4) +#define GO_BTN_INDEX (6) +#define PAGE_BTN_INDEX (7) +#define MENU_BTN_INDEX (8) + +// Digit limits for tab index which can be used in accelerator. +#define MAX_TAB_INDEX_DIGIT (9) +#define MIN_TAB_INDEX_DIGIT (1) + +// Object Names. +#define BROWSER_STR _T("browser") +#define TOOLBAR_STR _T("toolbar") +#define TABSTRIP_STR _T("tabstrip") +#define TAB_STR _T("tab") + +// Enums for keyboard keys. These values are directed to virtual-key values. +enum KEYBD_KEYS { + KEY_F3 = VK_F3, + KEY_F4 = VK_F4, + KEY_F5 = VK_F5, + KEY_F6 = VK_F6, + KEY_ALT = VK_MENU, + KEY_CONTROL = VK_CONTROL, + KEY_SHIFT = VK_SHIFT, + KEY_ENTER = VK_RETURN, + KEY_TAB = VK_TAB, + KEY_BACK = VK_BACK, + KEY_HOME = VK_HOME, + KEY_END = VK_END, + KEY_ESC = VK_ESCAPE, + KEY_INSERT = VK_INSERT, + KEY_DELETE = VK_DELETE, + KEY_LEFT = VK_LEFT, + KEY_RIGHT = VK_RIGHT, + KEY_PLUS = VK_ADD, + KEY_MINUS = VK_SUBTRACT, + KEY_0 = '0', + KEY_1 = '1', + KEY_2 = '2', + KEY_3 = '3', + KEY_4 = '4', + KEY_5 = '5', + KEY_6 = '6', + KEY_7 = '7', + KEY_8 = '8', + KEY_9 = '9', + KEY_D = 'D', + KEY_F = 'F', + KEY_G = 'G', + KEY_K = 'K', + KEY_L = 'L', + KEY_N = 'N', + KEY_O = 'O', + KEY_R = 'R', + KEY_T = 'T', + KEY_W = 'W', + KEY_INVALID = -1 +}; + + +#endif // CHROME_TEST_ACCISSIBILITY_CONSTANTS_H__ diff --git a/chrome/test/accessibility/keyboard_util.cc b/chrome/test/accessibility/keyboard_util.cc new file mode 100644 index 0000000..0e42776 --- /dev/null +++ b/chrome/test/accessibility/keyboard_util.cc @@ -0,0 +1,219 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "keyboard_util.h" + +void ClickKey(HWND hwnd, WORD key) { + INPUT input[2]; + memset(&input, 0, sizeof(INPUT)*2); + + // Press key. + input[0].type = INPUT_KEYBOARD; + input[0].ki.wVk = key; + input[0].ki.dwFlags = 0; + + // Release key. + input[1].type = INPUT_KEYBOARD; + input[1].ki.wVk = key; + input[1].ki.dwFlags = KEYEVENTF_KEYUP; + + SendInput(2, input, sizeof(INPUT)); +} + +void ClickKey(HWND hwnd, WORD extended_key, WORD key) { + INPUT input[4]; + memset(&input, 0, sizeof(INPUT)*4); + + // Press extended key. + input[0].type = INPUT_KEYBOARD; + input[0].ki.wVk = extended_key; + input[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY; + + // Press key. + input[1].type = INPUT_KEYBOARD; + input[1].ki.wVk = key; + input[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY; + + // Release key. + input[2].type = INPUT_KEYBOARD; + input[2].ki.wVk = key; + input[2].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP; + + // Release key. + input[3].type = INPUT_KEYBOARD; + input[3].ki.wVk = extended_key; + input[3].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP; + + SendInput(4, input, sizeof(INPUT)); +} + +void ClickKey(HWND hwnd, WORD extended_key1, WORD extended_key2, WORD key) { + INPUT input[6]; + memset(&input, 0, sizeof(INPUT)*6); + + // Press extended key1. + input[0].type = INPUT_KEYBOARD; + input[0].ki.wVk = extended_key1; + input[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY; + + // Press extended key2. + input[1].type = INPUT_KEYBOARD; + input[1].ki.wVk = extended_key2; + input[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY; + + // Press key. + input[2].type = INPUT_KEYBOARD; + input[2].ki.wVk = key; + input[2].ki.dwFlags = KEYEVENTF_EXTENDEDKEY; + + // Release key. + input[3].type = INPUT_KEYBOARD; + input[3].ki.wVk = key; + input[3].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP; + + // Release extended key2. + input[4].type = INPUT_KEYBOARD; + input[4].ki.wVk = extended_key2; + input[4].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP; + + // Release extended key1. + input[5].type = INPUT_KEYBOARD; + input[5].ki.wVk = extended_key1; + input[5].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP; + + SendInput(6, input, sizeof(INPUT)); +} + +void PressKey(HWND hwnd, WORD key) { + SendMessage(hwnd, WM_KEYDOWN, key, 0); + SendMessage(hwnd, WM_CHAR, key, 0); +} + +void ReleaseKey(HWND hwnd, WORD key) { + SendMessage(hwnd, WM_KEYUP, key, 0); +} + +KEYBD_KEYS GetKeybdKeysVal(BSTR str) { + if (0 == wcslen(str)) + return KEY_INVALID; + + if (0 == _wcsicmp(str, L"F3")) + return KEY_F3; + if (0 == _wcsicmp(str, L"F4")) + return KEY_F4; + if (0 == _wcsicmp(str, L"F5")) + return KEY_F5; + if (0 == _wcsicmp(str, L"F6")) + return KEY_F6; + if (0 == _wcsicmp(str, L"ALT")) + return KEY_ALT; + if (0 == _wcsicmp(str, L"ALTER")) + return KEY_ALT; + if (0 == _wcsicmp(str, L"CTRL")) + return KEY_CONTROL; + if (0 == _wcsicmp(str, L"CONTROL")) + return KEY_CONTROL; + if (0 == _wcsicmp(str, L"SHIFT")) + return KEY_SHIFT; + if (0 == _wcsicmp(str, L"ENTER")) + return KEY_ENTER; + if (0 == _wcsicmp(str, L"RETURN")) + return KEY_ENTER; + if (0 == _wcsicmp(str, L"TAB")) + return KEY_TAB; + if (0 == _wcsicmp(str, L"BACK")) + return KEY_BACK; + if (0 == _wcsicmp(str, L"HOME")) + return KEY_HOME; + if (0 == _wcsicmp(str, L"END")) + return KEY_END; + if (0 == _wcsicmp(str, L"ESC")) + return KEY_ESC; + if (0 == _wcsicmp(str, L"ESCAPE")) + return KEY_ESC; + if (0 == _wcsicmp(str, L"INSERT")) + return KEY_INSERT; + if (0 == _wcsicmp(str, L"INS")) + return KEY_INSERT; + if (0 == _wcsicmp(str, L"DEL")) + return KEY_DELETE; + if (0 == _wcsicmp(str, L"DELETE")) + return KEY_DELETE; + if (0 == _wcsicmp(str, L"LEFT")) + return KEY_LEFT; + if (0 == _wcsicmp(str, L"RIGHT")) + return KEY_RIGHT; + if (0 == _wcsicmp(str, L"0")) + return KEY_0; + if (0 == _wcsicmp(str, L"1")) + return KEY_1; + if (0 == _wcsicmp(str, L"2")) + return KEY_2; + if (0 == _wcsicmp(str, L"3")) + return KEY_3; + if (0 == _wcsicmp(str, L"4")) + return KEY_4; + if (0 == _wcsicmp(str, L"5")) + return KEY_5; + if (0 == _wcsicmp(str, L"6")) + return KEY_6; + if (0 == _wcsicmp(str, L"7")) + return KEY_7; + if (0 == _wcsicmp(str, L"8")) + return KEY_8; + if (0 == _wcsicmp(str, L"9")) + return KEY_9; + if (0 == _wcsicmp(str, L"D")) + return KEY_D; + if (0 == _wcsicmp(str, L"F")) + return KEY_F; + if (0 == _wcsicmp(str, L"G")) + return KEY_G; + if (0 == _wcsicmp(str, L"K")) + return KEY_K; + if (0 == _wcsicmp(str, L"L")) + return KEY_L; + if (0 == _wcsicmp(str, L"N")) + return KEY_N; + if (0 == _wcsicmp(str, L"O")) + return KEY_O; + if (0 == _wcsicmp(str, L"R")) + return KEY_R; + if (0 == _wcsicmp(str, L"T")) + return KEY_T; + if (0 == _wcsicmp(str, L"W")) + return KEY_W; + if (0 == _wcsicmp(str, L"+")) + return KEY_PLUS; + if (0 == _wcsicmp(str, L"-")) + return KEY_MINUS; + + // No key found. + return KEY_INVALID; +} diff --git a/chrome/test/accessibility/keyboard_util.h b/chrome/test/accessibility/keyboard_util.h new file mode 100644 index 0000000..d16b6a9 --- /dev/null +++ b/chrome/test/accessibility/keyboard_util.h @@ -0,0 +1,62 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_ACCISSIBILITY_KEYBOARD_UTIL_H__ +#define CHROME_TEST_ACCISSIBILITY_KEYBOARD_UTIL_H__ + +#include "constants.h" + +#include <oleauto.h> + +////////////////////////////////////////////////////// +// Function declarations to automate keyboard events. +////////////////////////////////////////////////////// + +// Enqueue keyboard message for a key. Currently, hwnd is not used. +void ClickKey(HWND hwnd, WORD key); + +// Enqueue keyboard message for a combination of 2 keys. Currently, hwnd is +// not used. +void ClickKey(HWND hwnd, WORD key, WORD extended_key); + +// Enqueue keyboard message for a combination of 2 keys. +// Currently, hwnd is not used. +void ClickKey(HWND hwnd, WORD key, WORD extended_key1, WORD extended_key2); + +// Sends key-down message to window. +void PressKey(HWND hwnd, WORD key); + +// Sends key-up message to window. +void ReleaseKey(HWND hwnd, WORD key); + +// Returns native enum values for a key-string specified. +KEYBD_KEYS GetKeybdKeysVal(BSTR str); + + +#endif // CHROME_TEST_ACCISSIBILITY_KEYBOARD_UTIL_H__ diff --git a/chrome/test/accessibility/registry_util.cc b/chrome/test/accessibility/registry_util.cc new file mode 100644 index 0000000..287c1df --- /dev/null +++ b/chrome/test/accessibility/registry_util.cc @@ -0,0 +1,37 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "registry_util.h" +#include "constants.h" + +BSTR GetChromeExePath() { + // TODO: once registry contains chrome exe path. + BSTR chrome_exe_path = SysAllocString(CHROME_PATH); + return chrome_exe_path; +} diff --git a/chrome/test/accessibility/registry_util.h b/chrome/test/accessibility/registry_util.h new file mode 100644 index 0000000..a3024d8 --- /dev/null +++ b/chrome/test/accessibility/registry_util.h @@ -0,0 +1,42 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_ACCISSIBILITY_REGISTRY_UTIL_H__ +#define CHROME_TEST_ACCISSIBILITY_REGISTRY_UTIL_H__ + +////////////////////////////////////////////////// +// Functions for registry operations. +////////////////////////////////////////////////// + +#include <ocidl.h> + +// Reads chrome installation path from registry. +BSTR GetChromeExePath(); + +#endif // CHROME_TEST_ACCISSIBILITY_REGISTRY_UTIL_H__ diff --git a/chrome/test/accessibility/tab_impl.cc b/chrome/test/accessibility/tab_impl.cc new file mode 100644 index 0000000..4393ffc --- /dev/null +++ b/chrome/test/accessibility/tab_impl.cc @@ -0,0 +1,389 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "browser_impl.h" +#include "tab_impl.h" +#include "accessibility_util.h" +#include "keyboard_util.h" +#include "constants.h" + +bool CTabImpl::Close(void) { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (!pi_access || !hwnd) + return false; + + // Activate main window and operate key Ctrl+F4. + ActivateWnd(pi_access, hwnd); + ClickKey(hwnd, VK_CONTROL, VK_F4); + CHK_RELEASE(pi_access); + + // Update tab information in browser object. + my_browser_->CloseTabFromCollection(tab_->index_); + return true; +} + +bool CTabImpl::GetTitle(BSTR* title) { + // Validation. + if (!title) + return false; + + // Read Tab name and store it in local member and return same value. + BSTR tab_title = GetTabName(tab_->index_); + *title = SysAllocString(tab_title); + tab_->title_ = SysAllocString(tab_title); + return true; +} + +bool CTabImpl::SetAddressBarText(const BSTR text) { + IAccessible *pi_access = NULL; + HWND hwnd_addr_bar = GetAddressBarWnd(&pi_access); + if (!pi_access || !hwnd_addr_bar) + return false; + + // Activate address bar. + ActivateWnd(pi_access, hwnd_addr_bar); + // Set text to address bar. + SendMessage(hwnd_addr_bar, WM_SETTEXT, 0, LPARAM(text)); + CHK_RELEASE(pi_access); + return true; +} + +bool CTabImpl::NavigateToURL(const BSTR url) { + IAccessible *pi_access = NULL; + HWND hwnd_addr_bar = GetAddressBarWnd(&pi_access); + + if (!pi_access || !hwnd_addr_bar) + return false; + + // Activate address bar. + ActivateWnd(pi_access, hwnd_addr_bar); + // Set text to address bar. + SendMessage(hwnd_addr_bar, WM_SETTEXT, 0, LPARAM(url)); + // Click Enter. Window is activated above for this. + ClickKey(hwnd_addr_bar, VK_RETURN); + CHK_RELEASE(pi_access); + return true; +} + +bool CTabImpl::FindInPage(const BSTR find_text) { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (!pi_access || !hwnd) + return false; + + // Activate main window and operate key 'F3' to invoke Find window. + ActivateWnd(pi_access, hwnd); + ClickKey(hwnd, VK_F3); + CHK_RELEASE(pi_access); + + // If no text is to be searched, return. + if (find_text != NULL) { + // TODO: Once FindWindow is exported through Accessibility. + // Instead of sleep, check if FindWindows exists or not. + Sleep(50); + + // Get Find window. + pi_access = NULL; + hwnd = GetFindTextWnd(&pi_access); + if (hwnd) { + HWND hwnd_find_edit = FindWindowEx(hwnd, 0, + CHROME_VIEWS_TEXT_FIELD_EDIT, 0); + if (hwnd_find_edit) { + ActivateWnd(pi_access, hwnd); + ActivateWnd(NULL, hwnd_find_edit); + // Set text in Find window edit box. + WCHAR* strTemp = + reinterpret_cast<WCHAR*>(calloc(wcslen(find_text), sizeof(WCHAR))); + wcscpy_s(strTemp, wcslen(find_text), find_text); + for (size_t i = 0; i < wcslen(strTemp); i++) { + SendMessage(hwnd_find_edit, WM_KEYDOWN, strTemp[i], 0); + SendMessage(hwnd_find_edit, WM_CHAR, strTemp[i], 0); + SendMessage(hwnd_find_edit, WM_KEYUP, strTemp[i], 0); + } + } + } + } + CHK_RELEASE(pi_access); + + return true; +} + +bool CTabImpl::Reload(void) { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (!pi_access || !hwnd) + return false; + + // Operate key F5. + ActivateWnd(pi_access, hwnd); + ClickKey(hwnd, VK_F5); + CHK_RELEASE(pi_access); + return true; +} + +bool CTabImpl::Duplicate(CTabImpl** tab) { + // TODO: Add your implementation code here + return true; +} + +bool CTabImpl::IsAuthDialogVisible() { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (!pi_access || !hwnd) + return false; + + // Activate main window. + ActivateWnd(pi_access, hwnd); + CHK_RELEASE(pi_access); + + // Check for Authentication Window. + pi_access = NULL; + hwnd = GetAuthWnd(&pi_access); + if (!hwnd || !pi_access) { + CHK_RELEASE(pi_access); + return false; + } + return true; +} + +bool CTabImpl::SetAuthDialog(const BSTR user_name, const BSTR password) { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (!pi_access || !hwnd) + return false; + + // Activate main window. + ActivateWnd(pi_access, hwnd); + CHK_RELEASE(pi_access); + + // Get editbox for user name and password. + pi_access = NULL; + hwnd = GetAuthWnd(&pi_access); + if (!hwnd) { + CHK_RELEASE(pi_access); + return false; + } + + // Get handle to password edit box. + HWND hwnd_auth_pwd = FindWindowEx(hwnd, 0, CHROME_VIEWS_TEXT_FIELD_EDIT, 0); + if (!hwnd_auth_pwd) { + CHK_RELEASE(pi_access); + return false; + } + + // Child after password edit box is edit box for name. + HWND hwnd_auth_name = FindWindowEx(hwnd, hwnd_auth_pwd, + CHROME_VIEWS_TEXT_FIELD_EDIT, 0); + if (!hwnd_auth_name) { + CHK_RELEASE(pi_access); + return false; + } + + // Activate Tab. + SetActiveWindow(GetParent(hwnd)); + // Activate Authentication window. + ActivateWnd(pi_access, hwnd); + + // Activate edit box for name. + ActivateWnd(NULL, hwnd_auth_name); + + // Set user name. + if (user_name != NULL) { + WCHAR* strTemp = + reinterpret_cast<WCHAR*>(calloc(wcslen(user_name), sizeof(WCHAR))); + wcscpy_s(strTemp, wcslen(user_name), user_name); + for (size_t i = 0; i < wcslen(strTemp); i++) { + SendMessage(hwnd_auth_name, WM_KEYDOWN, strTemp[i], 0); + SendMessage(hwnd_auth_name, WM_CHAR, strTemp[i], 0); + SendMessage(hwnd_auth_name, WM_KEYUP, strTemp[i], 0); + } + } + + // Activate edit box for password. + ActivateWnd(NULL, hwnd_auth_pwd); + + // Set password. + if (password != NULL) { + // set text + WCHAR* strTemp = + reinterpret_cast<WCHAR*>(calloc(wcslen(password), sizeof(WCHAR))); + wcscpy_s(strTemp, wcslen(password), password); + for (size_t i = 0; i < wcslen(strTemp); i++) { + SendMessage(hwnd_auth_pwd, WM_KEYDOWN, strTemp[i], 0); + SendMessage(hwnd_auth_pwd, WM_CHAR, strTemp[i], 0); + SendMessage(hwnd_auth_pwd, WM_KEYUP, strTemp[i], 0); + } + } + + CHK_RELEASE(pi_access); + return true; +} + +bool CTabImpl::CancelAuthDialog(void) { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (!pi_access || !hwnd) + return false; + + // Activate main window. + ActivateWnd(pi_access, hwnd); + CHK_RELEASE(pi_access); + + // Get editbox for user name which is after password. + pi_access = NULL; + hwnd = GetAuthWnd(&pi_access); + if (!hwnd) { + CHK_RELEASE(pi_access); + return false; + } + + // Get Cancel button. + HWND cancel_button_container = + FindWindowEx(hwnd, 0, CHROME_VIEWS_NATIVE_CTRL_CONTNR, 0); + if (!cancel_button_container) { + CHK_RELEASE(pi_access); + return false; + } + HWND cancel_button = FindWindowEx(cancel_button_container, 0, STD_BUTTON, 0); + if (!cancel_button) { + CHK_RELEASE(pi_access); + return false; + } + + // Click Cancel button. + SetActiveWindow(cancel_button_container); + SetActiveWindow(cancel_button); + SendMessage(cancel_button, BM_CLICK, 0, 0); + + return true; +} + +bool CTabImpl::UseAuthDialog(void) { + IAccessible *pi_access = NULL; + HWND hwnd = GetChromeBrowserWnd(&pi_access); + if (!pi_access || !hwnd) + return false; + + // Activate main window. + ActivateWnd(pi_access, hwnd); + CHK_RELEASE(pi_access); + + // Get editbox for user name which is after password. + pi_access = NULL; + hwnd = GetAuthWnd(&pi_access); + if (!hwnd) { + CHK_RELEASE(pi_access); + return false; + } + + // Get Ok button. + HWND cancel_button_container = + FindWindowEx(hwnd, 0, CHROME_VIEWS_NATIVE_CTRL_CONTNR, 0); + if (!cancel_button_container) { + CHK_RELEASE(pi_access); + return false; + } + + // Ok button is located after cancel button in window hierarchy. + HWND ok_button_container = FindWindowEx(hwnd, cancel_button_container, + CHROME_VIEWS_NATIVE_CTRL_CONTNR, 0); + if (!ok_button_container) { + CHK_RELEASE(pi_access); + return false; + } + HWND ok_button = FindWindowEx(ok_button_container, 0, STD_BUTTON, 0); + if (!ok_button) { + CHK_RELEASE(pi_access); + return false; + } + + // Click Ok. + SetActiveWindow(ok_button_container); + SetActiveWindow(ok_button); + SendMessage(ok_button, BM_CLICK, 0, 0); + + return true; +} + +bool CTabImpl::Activate(void) { + // TODO: Add your implementation code here + + return true; +} + +bool CTabImpl::WaitForTabToBecomeActive(const INT64 interval, + const INT64 timeout) { + // TODO: Add your implementation code here + + return true; +} + +bool CTabImpl::WaitForTabToGetLoaded(const INT64 interval, + const INT64 timeout) { + // TODO: Add your implementation code here + + return true; +} + +bool CTabImpl::IsSSLLockPresent(bool* present) { + // TODO: Add your implementation code here + + return true; +} + +bool CTabImpl::IsSSLSoftError(bool* soft_err) { + // TODO: Add your implementation code here + + return true; +} + +bool CTabImpl::OpenPageCertificateDialog(void) { + // TODO: Add your implementation code here + + return true; +} + +bool CTabImpl::ClosePageCertificateDialog(void) { + // TODO: Add your implementation code here + + return true; +} + +bool CTabImpl::GoBack(void) { + // TODO: Add your implementation code here + + return true; +} + +bool CTabImpl::GoForward(void) { + // TODO: Add your implementation code here + + return true; +} diff --git a/chrome/test/accessibility/tab_impl.h b/chrome/test/accessibility/tab_impl.h new file mode 100644 index 0000000..8bc5773 --- /dev/null +++ b/chrome/test/accessibility/tab_impl.h @@ -0,0 +1,163 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_ACCISSIBILITY_TAB_IMPL_H__ +#define CHROME_TEST_ACCISSIBILITY_TAB_IMPL_H__ + +#include "constants.h" + +#include <oleauto.h> + +///////////////////////////////////////////////////////////////////// +// CTabImpl +// It is a wrapper to Tab specific functionalities. +// Note: +// In most of the tasks, keyboard messages are used for now. +// DoDefaultAction() will be called on accessibility objects, +// once implementation is available in chrome accessibility server. +// And keyboard messages will be tested using ApplyAccelerator(). +///////////////////////////////////////////////////////////////////// + +// Forward declaration. +class CBrowserImpl; + +// Structure storing Tab parameters. +struct ChromeTab { + INT64 index_; + BSTR title_; +}; + +class CTabImpl { + public: + CTabImpl(): tab_(NULL), my_browser_(NULL) { + } + + public: + // Close this tab. + bool Close(void); + + // Returns title of this tab. + bool GetTitle(BSTR* title); + + // Sets the URL in address bar. + bool SetAddressBarText(const BSTR text); + + // Sets the URL and navigates tab to the page. + bool NavigateToURL(const BSTR url); + + // Find string by invoking Find Window. + bool FindInPage(const BSTR find_text); + + // Reloads/Refreshes the tab-page. + bool Reload(void); + + // Duplicates this tab. + bool Duplicate(CTabImpl** tab); + + // Returns true of Authentication dialog is opena nd visible. + bool IsAuthDialogVisible(); + + // Invokes authentication dialog with specified user name and password. + bool SetAuthDialog(const BSTR user_name, const BSTR password); + + // Cancels invoked authentication dialog. + bool CancelAuthDialog(void); + + // Authenticates with the credentials set in authentication dialog and + // closes it. + bool UseAuthDialog(void); + + // Activates this tab. + bool Activate(void); + + // Waits for specified time with the specified interval to get the tab + // activated. + bool WaitForTabToBecomeActive(const INT64 interval, const INT64 timeout); + + // Waits for specified time with the specified interval to get the tab-page + // loaded with URL. + bool WaitForTabToGetLoaded(const INT64 interval, const INT64 timeout); + + // Sets index of this tab. + void PutIndex(INT64 index) { + if (index < 0) + return; + if (!tab_) + InitTabData(); + tab_->index_ = index; + } + + // Sets title of this tab. + void PutTitle(BSTR title) { + if (!tab_) + InitTabData(); + tab_->title_ = SysAllocString(title); + } + + // Sets browser to which tab belongs. + bool SetBrowser(CBrowserImpl *browser) { + if (browser) + my_browser_ = browser; + else + return false; + + return true; + } + + // Initialize data specific to tab. + ChromeTab* InitTabData() { + if (tab_) + CHK_DELETE(tab_); + + tab_ = new ChromeTab(); + if (!tab_) + return NULL; + + memset(tab_, 0, sizeof(ChromeTab)); + return tab_; + } + + // TODO + bool IsSSLLockPresent(bool* present); + bool IsSSLSoftError(bool* soft_err); + bool OpenPageCertificateDialog(void); + bool ClosePageCertificateDialog(void); + bool GoBack(void); + bool GoForward(void); + + private: + // Structure to store tab data. + ChromeTab *tab_; + + // Pointer to browser to which this tab belongs. + CBrowserImpl *my_browser_; +}; + + +#endif // CHROME_TEST_ACCISSIBILITY_TAB_IMPL_H__ diff --git a/chrome/test/activex_test_control/SConscript b/chrome/test/activex_test_control/SConscript new file mode 100644 index 0000000..6f459c1 --- /dev/null +++ b/chrome/test/activex_test_control/SConscript @@ -0,0 +1,93 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env')
+
+env = env.Clone()
+
+
+env.Prepend(
+ CPPPATH = [
+ '.',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+
+ '/MANIFEST',
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+
+ '/DEBUG',
+ ],
+ LIBS = [
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'comsuppw.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+env.TypeLibrary('activex_test_control.idl')
+
+input_files = [
+ 'activex_test_control.cc',
+ 'activex_test_control.def',
+ 'chrome_test_control.cc',
+]
+
+dll = env.SharedLibrary(['activex_test_control', 'activex_test_control.lib'],
+ input_files)
+
+i = env.Install('$TARGET_ROOT', dll)
+env.Alias('chrome', i)
diff --git a/chrome/test/activex_test_control/activex_test_control.cc b/chrome/test/activex_test_control/activex_test_control.cc new file mode 100644 index 0000000..829cb9a --- /dev/null +++ b/chrome/test/activex_test_control/activex_test_control.cc @@ -0,0 +1,74 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <atlbase.h> +#include <atlcom.h> + +#include "activex_test_control.h" +#include "activex_test_control_i.c" +#include "chrome/test/activex_test_control/resource.h" + +class ActiveXTestControllModule + : public CAtlDllModuleT<ActiveXTestControllModule> { + public: + DECLARE_LIBID(LIBID_activex_test_controlLib) + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_ACTIVEX_TEST_CONTROL, + "{CDBC0D94-AFF6-4918-90A9-7967179A77D8}") +}; + +ActiveXTestControllModule g_atlmodule; + +// DLL Entry Point +extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, + LPVOID reserved) { + return g_atlmodule.DllMain(reason, reserved); +} + +// Used to determine whether the DLL can be unloaded by OLE +STDAPI DllCanUnloadNow(void) { + return g_atlmodule.DllCanUnloadNow(); +} + +// Returns a class factory to create an object of the requested type +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { + return g_atlmodule.DllGetClassObject(rclsid, riid, ppv); +} + +// DllRegisterServer - Adds entries to the system registry +STDAPI DllRegisterServer(void) { + // registers object, typelib and all interfaces in typelib + HRESULT hr = g_atlmodule.DllRegisterServer(); + return hr; +} + +// DllUnregisterServer - Removes entries from the system registry +STDAPI DllUnregisterServer(void) { + HRESULT hr = g_atlmodule.DllUnregisterServer(); + return hr; +} diff --git a/chrome/test/activex_test_control/activex_test_control.def b/chrome/test/activex_test_control/activex_test_control.def new file mode 100644 index 0000000..b006b57 --- /dev/null +++ b/chrome/test/activex_test_control/activex_test_control.def @@ -0,0 +1,9 @@ +; activex_test_control.def : Declares the module parameters. + +LIBRARY "activex_test_control.DLL" + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE diff --git a/chrome/test/activex_test_control/activex_test_control.idl b/chrome/test/activex_test_control/activex_test_control.idl new file mode 100644 index 0000000..04a2f42 --- /dev/null +++ b/chrome/test/activex_test_control/activex_test_control.idl @@ -0,0 +1,108 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file will be processed by the MIDL tool to +// produce the type library (activex_test_control.tlb) and marshalling code. + +#include "olectl.h" +import "oaidl.idl"; +import "ocidl.idl"; + +[ + object, + uuid(9AC37249-E247-4B82-AC1E-0917737528E9), + dual, + nonextensible, + helpstring("IChromeTestControl Interface"), + pointer_default(unique) +] +interface IChromeTestControl : IDispatch{ + [propput, bindable, requestedit, id(DISPID_BACKCOLOR)] + HRESULT BackColor([in]OLE_COLOR clr); + [propget, bindable, requestedit, id(DISPID_BACKCOLOR)] + HRESULT BackColor([out,retval]OLE_COLOR* pclr); + [propput, bindable, requestedit, id(DISPID_BORDERCOLOR)] + HRESULT BorderColor([in]OLE_COLOR clr); + [propget, bindable, requestedit, id(DISPID_BORDERCOLOR)] + HRESULT BorderColor([out, retval]OLE_COLOR* pclr); + [propput, bindable, requestedit, id(DISPID_FORECOLOR)] + HRESULT ForeColor([in]OLE_COLOR clr); + [propget, bindable, requestedit, id(DISPID_FORECOLOR)] + HRESULT ForeColor([out,retval]OLE_COLOR* pclr); + [propput, bindable, requestedit, id(DISPID_CAPTION)] + HRESULT Caption([in]BSTR strCaption); + [propget, bindable, requestedit, id(DISPID_CAPTION)] + HRESULT Caption([out,retval]BSTR* pstrCaption); + [propget, id(1), helpstring("property StringProp")] HRESULT StringProp([out, retval] BSTR* pVal); + [propput, id(1), helpstring("property StringProp")] HRESULT StringProp([in] BSTR newVal); + [propget, id(2), helpstring("property LongProp")] HRESULT LongProp([out, retval] LONG* pVal); + [propput, id(2), helpstring("property LongProp")] HRESULT LongProp([in] LONG newVal); + [propget, id(3), helpstring("property DoubleProp")] HRESULT DoubleProp([out, retval] DOUBLE* pVal); + [propput, id(3), helpstring("property DoubleProp")] HRESULT DoubleProp([in] DOUBLE newVal); + [propget, id(4), helpstring("property BoolProp")] HRESULT BoolProp([out, retval] VARIANT_BOOL* pVal); + [propput, id(4), helpstring("property BoolProp")] HRESULT BoolProp([in] VARIANT_BOOL newVal); + [propget, id(5), helpstring("property ByteProp")] HRESULT ByteProp([out, retval] BYTE* pVal); + [propput, id(5), helpstring("property ByteProp")] HRESULT ByteProp([in] BYTE newVal); + [propget, id(6), helpstring("property FloatProp")] HRESULT FloatProp([out, retval] FLOAT* pVal); + [propput, id(6), helpstring("property FloatProp")] HRESULT FloatProp([in] FLOAT newVal); + [id(7), helpstring("method BigSetMethod")] HRESULT BigSetMethodRet([in] BSTR string_param, [in] BYTE byte_param, [in] FLOAT float_param, [in] VARIANT_BOOL bool_param, [out,retval] BSTR* ret); + [id(8), helpstring("method SetByte")] HRESULT SetByte([in] BYTE val); + [id(9), helpstring("method SetByteRet")] HRESULT SetByteRet([in] BYTE byte_param, [out,retval] BYTE* ret); + [id(10), helpstring("method SetStringRet")] HRESULT SetStringRet([in] BSTR val, [out,retval] BSTR* ret); + [id(11), helpstring("method GetCookie")] HRESULT GetCookie([out,retval] BSTR* cookie); +}; + +[ + uuid(83D767F4-5C4F-4ACA-B0E8-928C54845C33), + version(1.0), + helpstring("activex_test_control 1.0 Type Library") +] +library activex_test_controlLib +{ + importlib("stdole2.tlb"); + [ + uuid(EF88DE01-35AF-463F-9802-1BF908F48696), + helpstring("_IChromeTestControlEvents Interface") + ] + dispinterface _IChromeTestControlEvents + { + properties: + methods: + }; + [ + uuid(4E174456-5EE6-494D-B6F2-2B52898A620E), + control, + helpstring("ChromeTestControl Class") + ] + coclass ChromeTestControl + { + [default] interface IChromeTestControl; + [default, source] dispinterface _IChromeTestControlEvents; + }; +}; diff --git a/chrome/test/activex_test_control/activex_test_control.rc b/chrome/test/activex_test_control/activex_test_control.rc new file mode 100644 index 0000000..e6046bd --- /dev/null +++ b/chrome/test/activex_test_control/activex_test_control.rc @@ -0,0 +1,128 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "1 TYPELIB ""activex_test_control.tlb""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Google Inc." + VALUE "FileDescription", "ActiveX Test Control" + VALUE "FileVersion", "1.0.0.1" + VALUE "LegalCopyright", "Google Inc. All rights reserved." + VALUE "InternalName", "activex_test_control.dll" + VALUE "OriginalFilename", "activex_test_control.dll" + VALUE "ProductName", "Google Chrome" + VALUE "ProductVersion", "1.0.0.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// REGISTRY +// + +IDR_ACTIVEX_TEST_CONTROL REGISTRY "activex_test_control.rgs" +IDR_CHROMETESTCONTROL REGISTRY "chrome_test_control.rgs" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_CHROMETESTCONTROL BITMAP "chrome_test_control.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_PROJNAME "activex_test_control" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +1 TYPELIB "activex_test_control.tlb" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/chrome/test/activex_test_control/activex_test_control.rgs b/chrome/test/activex_test_control/activex_test_control.rgs new file mode 100644 index 0000000..2873a48 --- /dev/null +++ b/chrome/test/activex_test_control/activex_test_control.rgs @@ -0,0 +1,11 @@ +HKCR +{ + NoRemove AppID + { + '%APPID%' = s 'activex_test_control' + 'activex_test_control.DLL' + { + val AppID = s '%APPID%' + } + } +} diff --git a/chrome/test/activex_test_control/activex_test_control.vcproj b/chrome/test/activex_test_control/activex_test_control.vcproj new file mode 100644 index 0000000..b40d9b3e --- /dev/null +++ b/chrome/test/activex_test_control/activex_test_control.vcproj @@ -0,0 +1,193 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="activex_test_control" + ProjectGUID="{414D4D24-5D65-498B-A33F-3A29AD3CDEDC}" + RootNamespace="activex_test_control" + Keyword="AtlProj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="2" + InheritedPropertySheets=".\activex_test_control.vsprops;$(SolutionDir)..\build\debug.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="2" + InheritedPropertySheets=".\activex_test_control.vsprops;$(SolutionDir)..\build\release.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="resource" + > + <File + RelativePath=".\activex_test_control.rc" + > + </File> + <File + RelativePath=".\activex_test_control.rgs" + > + </File> + <File + RelativePath=".\chrome_test_control.bmp" + > + </File> + <File + RelativePath=".\chrome_test_control.rgs" + > + </File> + </Filter> + <File + RelativePath=".\activex_test_control.cc" + > + </File> + <File + RelativePath=".\activex_test_control.def" + > + </File> + <File + RelativePath=".\activex_test_control.idl" + > + </File> + <File + RelativePath=".\chrome_test_control.cc" + > + </File> + <File + RelativePath=".\chrome_test_control.h" + > + </File> + <File + RelativePath=".\chrome_test_control_cp.h" + > + </File> + <File + RelativePath=".\resource.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/activex_test_control/activex_test_control.vsprops b/chrome/test/activex_test_control/activex_test_control.vsprops new file mode 100644 index 0000000..d873ddf --- /dev/null +++ b/chrome/test/activex_test_control/activex_test_control.vsprops @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="activex_test_control" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops" + UseOfATL="1" + ATLMinimizesCRunTimeLibraryUsage="false" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="$(IntDir)" + /> + <Tool + Name="VCLinkerTool" + RegisterOutput="false" + IgnoreImportLibrary="true" + AdditionalDependencies="comsuppw.lib" + OutputFile="$(OutDir)\activex_test_control.dll" + ModuleDefinitionFile=".\activex_test_control.def" + /> + <Tool + Name="VCResourceCompilerTool" + AdditionalIncludeDirectories="$(IntDir)" + /> +</VisualStudioPropertySheet> diff --git a/chrome/test/activex_test_control/chrome_test_control.bmp b/chrome/test/activex_test_control/chrome_test_control.bmp Binary files differnew file mode 100644 index 0000000..1229764 --- /dev/null +++ b/chrome/test/activex_test_control/chrome_test_control.bmp diff --git a/chrome/test/activex_test_control/chrome_test_control.cc b/chrome/test/activex_test_control/chrome_test_control.cc new file mode 100644 index 0000000..5b0655c --- /dev/null +++ b/chrome/test/activex_test_control/chrome_test_control.cc @@ -0,0 +1,59 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/activex_test_control/chrome_test_control.h" + +// CChromeTestControl +HRESULT ChromeTestControl::OnDraw(ATL_DRAWINFO& di) { + RECT& rc = *(RECT*)di.prcBounds; + // Set Clip region to the rectangle specified by di.prcBounds + HRGN rgn_old = NULL; + if (GetClipRgn(di.hdcDraw, rgn_old) != 1) + rgn_old = NULL; + bool select_old_rgn = false; + + HRGN rgn_new = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom); + + if (rgn_new != NULL) + select_old_rgn = (SelectClipRgn(di.hdcDraw, rgn_new) != ERROR); + + Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom); + SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE); + LPCTSTR pszText = _T("ATL 8.0 : ChromeTestControl"); + TextOut(di.hdcDraw, + (rc.left + rc.right) / 2, + (rc.top + rc.bottom) / 2, + pszText, + lstrlen(pszText)); + + if (select_old_rgn) + SelectClipRgn(di.hdcDraw, rgn_old); + + return S_OK; +} diff --git a/chrome/test/activex_test_control/chrome_test_control.h b/chrome/test/activex_test_control/chrome_test_control.h new file mode 100644 index 0000000..e923307 --- /dev/null +++ b/chrome/test/activex_test_control/chrome_test_control.h @@ -0,0 +1,286 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_H__ +#define CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_H__ + +#include <atlbase.h> +#include <atlcom.h> +#include <atlctl.h> +#include <comutil.h> +#include "activex_test_control.h" +#include "chrome/test/activex_test_control/chrome_test_control_cp.h" +#include "chrome/test/activex_test_control/resource.h" + +// ChromeTestControl +class ATL_NO_VTABLE ChromeTestControl + : public CComObjectRootEx<CComSingleThreadModel>, + public CStockPropImpl<ChromeTestControl, IChromeTestControl>, + public IPersistStreamInitImpl<ChromeTestControl>, + public IOleControlImpl<ChromeTestControl>, + public IOleObjectImpl<ChromeTestControl>, + public IOleInPlaceActiveObjectImpl<ChromeTestControl>, + public IViewObjectExImpl<ChromeTestControl>, + public IOleInPlaceObjectWindowlessImpl<ChromeTestControl>, + public ISupportErrorInfo, + public IConnectionPointContainerImpl<ChromeTestControl>, + public CProxy_IChromeTestControlEvents<ChromeTestControl>, + public IObjectWithSiteImpl<ChromeTestControl>, + public IServiceProviderImpl<ChromeTestControl>, + public IPersistStorageImpl<ChromeTestControl>, + public ISpecifyPropertyPagesImpl<ChromeTestControl>, + public IQuickActivateImpl<ChromeTestControl>, + public IDataObjectImpl<ChromeTestControl>, + public IProvideClassInfo2Impl<&CLSID_ChromeTestControl, + &__uuidof(_IChromeTestControlEvents), &LIBID_activex_test_controlLib>, + public IPropertyNotifySinkCP<ChromeTestControl>, + public IObjectSafetyImpl<ChromeTestControl, + INTERFACESAFE_FOR_UNTRUSTED_CALLER | + INTERFACESAFE_FOR_UNTRUSTED_DATA>, + public CComCoClass<ChromeTestControl, &CLSID_ChromeTestControl>, + public CComControl<ChromeTestControl> { + public: + ChromeTestControl() { + } + +DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE | + OLEMISC_CANTLINKINSIDE | + OLEMISC_INSIDEOUT | + OLEMISC_ACTIVATEWHENVISIBLE | + OLEMISC_SETCLIENTSITEFIRST) + +DECLARE_REGISTRY_RESOURCEID(IDR_CHROMETESTCONTROL) + +BEGIN_COM_MAP(ChromeTestControl) + COM_INTERFACE_ENTRY(IChromeTestControl) + COM_INTERFACE_ENTRY(IDispatch) + COM_INTERFACE_ENTRY(IViewObjectEx) + COM_INTERFACE_ENTRY(IViewObject2) + COM_INTERFACE_ENTRY(IViewObject) + COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless) + COM_INTERFACE_ENTRY(IOleInPlaceObject) + COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless) + COM_INTERFACE_ENTRY(IOleInPlaceActiveObject) + COM_INTERFACE_ENTRY(IOleControl) + COM_INTERFACE_ENTRY(IOleObject) + COM_INTERFACE_ENTRY(IPersistStreamInit) + COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) + COM_INTERFACE_ENTRY(ISupportErrorInfo) + COM_INTERFACE_ENTRY(IConnectionPointContainer) + COM_INTERFACE_ENTRY(ISpecifyPropertyPages) + COM_INTERFACE_ENTRY(IQuickActivate) + COM_INTERFACE_ENTRY(IPersistStorage) + COM_INTERFACE_ENTRY(IDataObject) + COM_INTERFACE_ENTRY(IProvideClassInfo) + COM_INTERFACE_ENTRY(IProvideClassInfo2) + COM_INTERFACE_ENTRY(IObjectWithSite) + COM_INTERFACE_ENTRY(IServiceProvider) + COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety) +END_COM_MAP() + +BEGIN_PROP_MAP(ChromeTestControl) + PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4) + PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4) + PROP_ENTRY("BackColor", DISPID_BACKCOLOR, CLSID_StockColorPage) + PROP_ENTRY("BorderColor", DISPID_BORDERCOLOR, CLSID_StockColorPage) + PROP_ENTRY("Caption", DISPID_CAPTION, CLSID_NULL) + PROP_ENTRY("ForeColor", DISPID_FORECOLOR, CLSID_StockColorPage) + // Example entries + // PROP_ENTRY("Property Description", dispid, clsid) + // PROP_PAGE(CLSID_StockColorPage) +END_PROP_MAP() + +BEGIN_CONNECTION_POINT_MAP(ChromeTestControl) + CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink) + CONNECTION_POINT_ENTRY(__uuidof(_IChromeTestControlEvents)) +END_CONNECTION_POINT_MAP() + +BEGIN_MSG_MAP(ChromeTestControl) + CHAIN_MSG_MAP(CComControl<ChromeTestControl>) + DEFAULT_REFLECTION_HANDLER() +END_MSG_MAP() + + // ISupportsErrorInfo + STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) { + static const IID* arr[] = { + &IID_IChromeTestControl, + }; + + for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++) { + if (InlineIsEqualGUID(*arr[i], riid)) + return S_OK; + } + return S_FALSE; + } + + // IViewObjectEx + DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE) + +// IChromeTestControl + public: + HRESULT OnDraw(ATL_DRAWINFO& di); + + void OnBackColorChanged() { + ATLTRACE(_T("OnBackColorChanged\n")); + } + void OnBorderColorChanged() { + ATLTRACE(_T("OnBorderColorChanged\n")); + } + void OnCaptionChanged() { + ATLTRACE(_T("OnCaptionChanged\n")); + } + void OnForeColorChanged() { + ATLTRACE(_T("OnForeColorChanged\n")); + } + STDMETHOD(_InternalQueryService)(REFGUID guidService, REFIID riid, + void** ppvObject) { + return E_NOTIMPL; + } + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + HRESULT FinalConstruct() { + return S_OK; + } + + void FinalRelease() { + } + + STDMETHOD(get_StringProp)(BSTR* val) { + *val = string_prop_.copy(); + return S_OK; + } + + STDMETHOD(put_StringProp)(BSTR val) { + string_prop_ = val; + return S_OK; + } + STDMETHOD(get_LongProp)(LONG* val) { + *val = long_prop_; + return S_OK; + } + + STDMETHOD(put_LongProp)(LONG val) { + long_prop_ = val; + return S_OK; + } + STDMETHOD(get_DoubleProp)(DOUBLE* val) { + *val = double_prop_; + return S_OK; + } + + STDMETHOD(put_DoubleProp)(DOUBLE val) { + double_prop_ = val; + return S_OK; + } + + STDMETHOD(get_BoolProp)(VARIANT_BOOL* val) { + *val = bool_prop_; + return S_OK; + } + + STDMETHOD(put_BoolProp)(VARIANT_BOOL val) { + bool_prop_ = val; + return S_OK; + } + + STDMETHOD(get_ByteProp)(BYTE* val) { + *val = byte_prop_; + return S_OK; + } + + STDMETHOD(put_ByteProp)(BYTE val) { + byte_prop_ = val; + return S_OK; + } + + STDMETHOD(get_FloatProp)(FLOAT* val) { + *val = float_prop_; + return S_OK; + } + + STDMETHOD(put_FloatProp)(FLOAT val) { + float_prop_ = val; + return S_OK; + } + + STDMETHOD(SetByte)(BYTE val) { + byte_prop_ = val; + return S_OK; + } + STDMETHOD(SetByteRet)(BYTE val, BYTE* ret) { + byte_prop_ = val; + *ret = val; + return S_OK; + } + STDMETHOD(SetStringRet)(BSTR val, BSTR* ret) { + string_prop_ = val; + *ret = string_prop_.copy(); + return S_OK; + } + STDMETHOD(BigSetMethodRet)(BSTR string_param, BYTE byte_param, + FLOAT float_param, VARIANT_BOOL bool_param, + BSTR* ret) { + string_prop_ = string_param; + byte_prop_ = byte_param; + float_prop_ = float_param; + bool_prop_ = bool_param; + *ret = SysAllocString(string_param); + return S_OK; + } + STDMETHOD(GetCookie)(BSTR* cookie) { + CComPtr<IOleContainer> container; + m_spClientSite->GetContainer(&container); + CComQIPtr<IHTMLDocument2> doc = container; + if (doc == NULL) { + *cookie = SysAllocString(L"Bad"); + return S_FALSE; + } else { + return doc->get_cookie(cookie); + } + } + + // These varialbes are used by CStockPropImpl invisibly and they have to be + // be public to be accessible. + OLE_COLOR m_clrBackColor; + OLE_COLOR m_clrBorderColor; + CComBSTR m_bstrCaption; + OLE_COLOR m_clrForeColor; + private: + _bstr_t string_prop_; + LONG long_prop_; + DOUBLE double_prop_; + VARIANT_BOOL bool_prop_; + BYTE byte_prop_; + FLOAT float_prop_; +}; + +OBJECT_ENTRY_AUTO(__uuidof(ChromeTestControl), ChromeTestControl) + +#endif // #ifndef CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_H__ diff --git a/chrome/test/activex_test_control/chrome_test_control.rgs b/chrome/test/activex_test_control/chrome_test_control.rgs new file mode 100644 index 0000000..9e327bc --- /dev/null +++ b/chrome/test/activex_test_control/chrome_test_control.rgs @@ -0,0 +1,34 @@ +HKCR +{ + activex_test_control.ChromeTestContro.1 = s 'ChromeTestControl Class' + { + CLSID = s '{4E174456-5EE6-494D-B6F2-2B52898A620E}' + } + activex_test_control.ChromeTestControl = s 'ChromeTestControl Class' + { + CLSID = s '{4E174456-5EE6-494D-B6F2-2B52898A620E}' + CurVer = s 'activex_test_control.ChromeTestContro.1' + } + NoRemove CLSID + { + ForceRemove {4E174456-5EE6-494D-B6F2-2B52898A620E} = s 'ChromeTestControl Class' + { + ProgID = s 'activex_test_control.ChromeTestContro.1' + VersionIndependentProgID = s 'activex_test_control.ChromeTestControl' + ForceRemove 'Programmable' + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + val AppID = s '%APPID%' + ForceRemove 'Control' + ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 102' + 'MiscStatus' = s '0' + { + '1' = s '%OLEMISC%' + } + 'TypeLib' = s '{83D767F4-5C4F-4ACA-B0E8-928C54845C33}' + 'Version' = s '1.0' + } + } +} diff --git a/chrome/test/activex_test_control/chrome_test_control_cp.h b/chrome/test/activex_test_control/chrome_test_control_cp.h new file mode 100644 index 0000000..734b326 --- /dev/null +++ b/chrome/test/activex_test_control/chrome_test_control_cp.h @@ -0,0 +1,42 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_CP_H__ +#define CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_CP_H__ + + +template <class T> +class CProxy_IChromeTestControlEvents + : public IConnectionPointImpl<T, &__uuidof(_IChromeTestControlEvents), + CComDynamicUnkArray> { + //Warning this class will be regenerated by the wizard. + public: +}; + +#endif // #ifndef CHROME_TEST_ACTIVEX_TEST_CONTROL_CHROME_TEST_CONTROL_CP_H__ diff --git a/chrome/test/activex_test_control/resource.h b/chrome/test/activex_test_control/resource.h new file mode 100644 index 0000000..fc3cd4e --- /dev/null +++ b/chrome/test/activex_test_control/resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by activex_test_control.rc +// +#define IDS_PROJNAME 100 +#define IDR_ACTIVEX_TEST_CONTROL 101 +#define IDB_CHROMETESTCONTROL 102 +#define IDR_CHROMETESTCONTROL 103 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 201 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.cc b/chrome/test/automated_ui_tests/automated_ui_tests.cc new file mode 100644 index 0000000..0129e81 --- /dev/null +++ b/chrome/test/automated_ui_tests/automated_ui_tests.cc @@ -0,0 +1,887 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <fstream> + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/view_ids.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/libxml_utils.h" +#include "chrome/common/rand_util.h" +#include "chrome/common/win_util.h" +#include "chrome/test/automated_ui_tests/automated_ui_tests.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "chrome/views/view.h" +#include "googleurl/src/gurl.h" + +namespace { + +const wchar_t* const kReproSwitch = L"key"; + +const wchar_t* const kReproRepeatSwitch = L"num-reproductions"; + +const wchar_t* const kInputFilePathSwitch = L"input"; + +const wchar_t* const kOutputFilePathSwitch = L"output"; + +const wchar_t* const kDebugModeSwitch = L"debug"; + +const wchar_t* const kDefaultInputFilePath = L"C:\\automated_ui_tests.txt"; + +const wchar_t* const kDefaultOutputFilePath + = L"C:\\automated_ui_tests_error_report.txt"; + +const int kDebuggingTimeoutMsec = 5000; + +// How many commands to run when testing a dialog box. +const int kTestDialogActionsToRun = 7; + +} // namespace + +// This subset of commands is used to test dialog boxes, which aren't likely +// to respond to most other commands. +std::string AutomatedUITest::test_dialog_possible_actions_[] = { + "PressTabKey", + "PressEnterKey", + "PressSpaceBar", + "DownArrow" +}; + +AutomatedUITest::AutomatedUITest() + : total_crashes_(0), + debug_logging_enabled_(false) { + show_window_ = true; + GetSystemTimeAsFileTime(&test_start_time_); + CommandLine parsed_command_line; + if (parsed_command_line.HasSwitch(kDebugModeSwitch)) + debug_logging_enabled_ = true; +} + +AutomatedUITest::~AutomatedUITest() {} + +void AutomatedUITest::RunReproduction() { + CommandLine parsed_command_line; + xml_writer_.StartWriting(); + xml_writer_.StartElement("Report"); + std::string action_string = + WideToASCII(parsed_command_line.GetSwitchValue(kReproSwitch)); + + int64 num_reproductions = 1; + if (parsed_command_line.HasSwitch(kReproRepeatSwitch)) { + std::wstring num_reproductions_string = + parsed_command_line.GetSwitchValue(kReproRepeatSwitch); + std::string test = WideToASCII(num_reproductions_string); + num_reproductions = StringToInt64(num_reproductions_string); + } + std::vector<std::string> actions; + SplitString(action_string, L',', &actions); + bool did_crash = false; + bool command_complete = false; + + for (int64 i = 0; i < num_reproductions && !did_crash; ++i) { + bool did_teardown = false; + xml_writer_.StartElement("Executed"); + for (size_t j = 0; j < actions.size(); ++j) { + DoAction(actions[j]); + if (DidCrash(true)) { + did_crash = true; + if (j >= (actions.size() - 1)) + command_complete = true; + break; + } + if (LowerCaseEqualsASCII(actions[j], "teardown")) + did_teardown = true; + } + + // Force proper teardown after each run, if it didn't already happen. But + // don't teardown after crashes. + if (!did_teardown && !did_crash) + DoAction("TearDown"); + + xml_writer_.EndElement(); // End "Executed" element. + } + + if (did_crash) { + std::string crash_dump = WideToASCII(GetMostRecentCrashDump()); + std::string result = + "*** Crash dump produced. See result file for more details. Dump = "; + result.append(crash_dump); + result.append(" ***\n"); + printf("%s", result.c_str()); + LogCrashResult(crash_dump, command_complete); + EXPECT_TRUE(false) << "Crash detected."; + } else { + printf("*** No crashes. See result file for more details. ***\n"); + LogSuccessResult(); + } + + WriteReportToFile(); +} + + +void AutomatedUITest::RunAutomatedUITest() { + ASSERT_TRUE(InitXMLReader()) << "Error initializing XMLReader"; + xml_writer_.StartWriting(); + xml_writer_.StartElement("Report"); + + while (init_reader_.Read()) { + init_reader_.SkipToElement(); + std::string node_name = init_reader_.NodeName(); + if (LowerCaseEqualsASCII(node_name, "command")) { + bool no_errors = true; + xml_writer_.StartElement("Executed"); + std::string command_number; + if (init_reader_.NodeAttribute("number", &command_number)) { + xml_writer_.AddAttribute("command_number", command_number); + } + xml_writer_.StopIndenting(); + + // Starts the browser, logging it as an action. + DoAction("SetUp"); + + // Record the depth of the root of the command subtree, then advance to + // the first element in preperation for parsing. + int start_depth = init_reader_.Depth(); + ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file."; + init_reader_.SkipToElement(); + + // Check for a crash right after startup. + if (DidCrash(true)) { + LogCrashResult(WideToASCII(GetMostRecentCrashDump()), false); + // Try and start up again. + CloseBrowserAndServer(); + LaunchBrowserAndServer(); + if (DidCrash(true)) { + no_errors = false; + // We crashed again, so skip to the end of the this command. + while (init_reader_.Depth() != start_depth) { + ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file."; + } + } else { + // We didn't crash, so end the old element, logging a crash for that. + // Then start a new element to log this command. + xml_writer_.StartIndenting(); + xml_writer_.EndElement(); + xml_writer_.StartElement("Executed"); + xml_writer_.AddAttribute("command_number", command_number); + xml_writer_.StopIndenting(); + xml_writer_.StartElement("SetUp"); + xml_writer_.EndElement(); + } + } + // Parse the command, performing the specified actions and checking + // for a crash after each one. + while (init_reader_.Depth() != start_depth) { + node_name = init_reader_.NodeName(); + + DoAction(node_name); + + // Advance to the next element + ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file."; + init_reader_.SkipToElement(); + if (DidCrash(true)) { + no_errors = false; + // This was the last action if we've returned to the initial depth + // of the command subtree. + bool wasLastAction = init_reader_.Depth() == start_depth; + LogCrashResult(WideToASCII(GetMostRecentCrashDump()), wasLastAction); + // Skip to the beginning of the next command. + while (init_reader_.Depth() != start_depth) { + ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file."; + } + } + } + + if (no_errors) { + // If there were no previous crashes, log our tear down and check for + // a crash, log success for the entire command if this doesn't crash. + DoAction("TearDown"); + if (DidCrash(true)) + LogCrashResult(WideToASCII(GetMostRecentCrashDump()), true); + else + LogSuccessResult(); + } else { + // If there was a previous crash, just tear down without logging, so + // that we know what the last command was before we crashed. + CloseBrowserAndServer(); + } + + xml_writer_.StartIndenting(); + xml_writer_.EndElement(); // End "Executed" element. + } + } + // The test is finished so write our report. + WriteReportToFile(); +} + +bool AutomatedUITest::DoAction(const std::string & action) { + bool did_complete_action = false; + xml_writer_.StartElement(action); + if (debug_logging_enabled_) + AppendToOutputFile(action); + + if (LowerCaseEqualsASCII(action, "navigate")) { + did_complete_action = Navigate(); + } else if (LowerCaseEqualsASCII(action, "newtab")) { + did_complete_action = NewTab(); + } else if (LowerCaseEqualsASCII(action, "back")) { + did_complete_action = BackButton(); + } else if (LowerCaseEqualsASCII(action, "forward")) { + did_complete_action = ForwardButton(); + } else if (LowerCaseEqualsASCII(action, "closetab")) { + did_complete_action = CloseActiveTab(); + } else if (LowerCaseEqualsASCII(action, "openwindow")) { + did_complete_action = OpenAndActivateNewBrowserWindow(); + } else if (LowerCaseEqualsASCII(action, "reload")) { + did_complete_action = ReloadPage(); + } else if (LowerCaseEqualsASCII(action, "star")) { + did_complete_action = StarPage(); + } else if (LowerCaseEqualsASCII(action, "findinpage")) { + did_complete_action = FindInPage(); + } else if (LowerCaseEqualsASCII(action, "selectnexttab")) { + did_complete_action = SelectNextTab(); + } else if (LowerCaseEqualsASCII(action, "selectprevtab")) { + did_complete_action = SelectPreviousTab(); + } else if (LowerCaseEqualsASCII(action, "zoomplus")) { + did_complete_action = ZoomPlus(); + } else if (LowerCaseEqualsASCII(action, "zoomminus")) { + did_complete_action = ZoomMinus(); + } else if (LowerCaseEqualsASCII(action, "history")) { + did_complete_action = ShowHistory(); + } else if (LowerCaseEqualsASCII(action, "downloads")) { + did_complete_action = ShowDownloads(); + } else if (LowerCaseEqualsASCII(action, "importsettings")) { + did_complete_action = ImportSettings(); + } else if (LowerCaseEqualsASCII(action, "viewpasswords")) { + did_complete_action = ViewPasswords(); + } else if (LowerCaseEqualsASCII(action, "clearbrowserdata")) { + did_complete_action = ClearBrowserData(); + } else if (LowerCaseEqualsASCII(action, "taskmanager")) { + did_complete_action = TaskManager(); + } else if (LowerCaseEqualsASCII(action, "goofftherecord")) { + did_complete_action = GoOffTheRecord(); + } else if (LowerCaseEqualsASCII(action, "pressescapekey")) { + did_complete_action = PressEscapeKey(); + } else if (LowerCaseEqualsASCII(action, "presstabkey")) { + did_complete_action = PressTabKey(); + } else if (LowerCaseEqualsASCII(action, "pressenterkey")) { + did_complete_action = PressEnterKey(); + } else if (LowerCaseEqualsASCII(action, "pressspacebar")) { + did_complete_action = PressSpaceBar(); + } else if (LowerCaseEqualsASCII(action, "pagedown")) { + did_complete_action = PageDown(); + } else if (LowerCaseEqualsASCII(action, "pageup")) { + did_complete_action = PageUp(); + } else if (LowerCaseEqualsASCII(action, "dragtabright")) { + did_complete_action = DragActiveTab(true, false); + } else if (LowerCaseEqualsASCII(action, "dragtableft")) { + did_complete_action = DragActiveTab(false, false); + } else if (LowerCaseEqualsASCII(action, "dragtabout")) { + did_complete_action = DragActiveTab(false, true); + } else if (LowerCaseEqualsASCII(action, "uparrow")) { + did_complete_action = UpArrow(); + } else if (LowerCaseEqualsASCII(action, "downarrow")) { + did_complete_action = DownArrow(); + } else if (LowerCaseEqualsASCII(action, "testeditkeywords")) { + did_complete_action = TestEditKeywords(); + } else if (LowerCaseEqualsASCII(action, "testtaskmanager")) { + did_complete_action = TestTaskManager(); + } else if (LowerCaseEqualsASCII(action, "testviewpasswords")) { + did_complete_action = TestViewPasswords(); + } else if (LowerCaseEqualsASCII(action, "testclearbrowserdata")) { + did_complete_action = TestClearBrowserData(); + } else if (LowerCaseEqualsASCII(action, "testimportsettings")) { + did_complete_action = TestImportSettings(); + } else if (LowerCaseEqualsASCII(action, "crash")) { + did_complete_action = ForceCrash(); + } else if (LowerCaseEqualsASCII(action, "sleep")) { + // This is for debugging, it probably shouldn't be used real tests. + Sleep(kDebuggingTimeoutMsec); + did_complete_action = true; + } else if (LowerCaseEqualsASCII(action, "setup")) { + LaunchBrowserAndServer(); + did_complete_action = true; + } else if (LowerCaseEqualsASCII(action, "teardown")) { + CloseBrowserAndServer(); + did_complete_action = true; + } + + if (!did_complete_action) + xml_writer_.AddAttribute("failed_to_complete", "yes"); + xml_writer_.EndElement(); + + return did_complete_action; +} + +bool AutomatedUITest::Navigate() { + scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow()); + if (browser.get() == NULL) { + AddErrorAttribute("browser_window_not_found"); + return false; + } + bool did_timeout; + scoped_ptr<TabProxy> tab( + browser->GetActiveTabWithTimeout(kWaitForActionMaxMsec, &did_timeout)); + // TODO(devint): This might be masking a bug. I can't think of many + // valid cases where we would get a browser window, but not be able + // to return an active tab. Yet this has happened and has triggered crashes. + // Investigate this. + if (tab.get() == NULL) { + AddErrorAttribute("active_tab_not_found"); + return false; + } + std::string url = "about:blank"; + if (init_reader_.NodeAttribute("url", &url)) { + xml_writer_.AddAttribute("url", url); + } + GURL test_url(url); + did_timeout = false; + tab->NavigateToURLWithTimeout(test_url, kMaxTestExecutionTime, &did_timeout); + + if (did_timeout) { + AddWarningAttribute("timeout"); + return false; + } + return true; +} + +bool AutomatedUITest::NewTab() { + scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow()); + if (browser.get() == NULL) { + AddErrorAttribute("browser_window_not_found"); + return false; + } + int old_tab_count; + int new_tab_count; + bool is_timeout; + browser->GetTabCountWithTimeout(&old_tab_count, kWaitForActionMaxMsec, + &is_timeout); + // Apply accelerator and wait for a new tab to open, if either + // fails, return false. Apply Accelerator takes care of logging its failure. + bool return_value = ApplyAccelerator(IDC_NEWTAB); + if (!browser->WaitForTabCountToChange( + old_tab_count, &new_tab_count, kWaitForActionMaxMsec)) { + AddWarningAttribute("tab_count_failed_to_change"); + return false; + } + return return_value; +} + +bool AutomatedUITest::BackButton() { + return ApplyAccelerator(IDC_BACK); +} + +bool AutomatedUITest::ForwardButton() { + return ApplyAccelerator(IDC_FORWARD); +} + +bool AutomatedUITest::CloseActiveTab() { + bool return_value = false; + scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow()); + if (browser.get() == NULL) { + AddErrorAttribute("browser_window_not_found"); + return false; + } + int browser_windows_count; + int tab_count; + bool is_timeout; + browser->GetTabCountWithTimeout(&tab_count, kWaitForActionMaxMsec, + &is_timeout); + automation()->GetBrowserWindowCount(&browser_windows_count); + // Avoid quitting the application by not closing the last window. + if (tab_count > 1) { + int new_tab_count; + return_value = browser->ApplyAccelerator(IDC_CLOSETAB); + // Wait for the tab to close before we continue. + if (!browser->WaitForTabCountToChange( + tab_count, &new_tab_count, kWaitForActionMaxMsec)) { + AddWarningAttribute("tab_count_failed_to_change"); + return false; + } + } else if (tab_count == 1 && browser_windows_count > 1) { + int new_window_count; + return_value = browser->ApplyAccelerator(IDC_CLOSETAB); + // Wait for the window to close before we continue. + if (!automation()->WaitForWindowCountToChange( + browser_windows_count, &new_window_count, kWaitForActionMaxMsec)) { + AddWarningAttribute("window_count_failed_to_change"); + return false; + } + } else { + AddInfoAttribute("would_have_exited_application"); + return false; + } + return return_value; +} + +bool AutomatedUITest::OpenAndActivateNewBrowserWindow() { + if (!automation()->OpenNewBrowserWindow(SW_SHOWNORMAL)) { + AddWarningAttribute("failed_to_open_new_browser_window"); + return false; + } + int num_browser_windows; + automation()->GetBrowserWindowCount(&num_browser_windows); + // Get the most recently opened browser window and activate the tab + // in order to activate this browser window. + scoped_ptr<BrowserProxy> browser( + automation()->GetBrowserWindow(num_browser_windows - 1)); + if (browser.get() == NULL) { + AddErrorAttribute("browser_window_not_found"); + return false; + } + bool is_timeout; + if (!browser->ActivateTabWithTimeout(0, kWaitForActionMaxMsec, + &is_timeout)) { + AddWarningAttribute("failed_to_activate_tab"); + return false; + } + return true; +} + +bool AutomatedUITest::ReloadPage() { + return ApplyAccelerator(IDC_RELOAD); +} + +bool AutomatedUITest::StarPage() { + return ApplyAccelerator(IDC_STAR); +} + +bool AutomatedUITest::FindInPage() { + return ApplyAccelerator(IDC_FIND); +} + +bool AutomatedUITest::SelectNextTab() { + return ApplyAccelerator(IDC_SELECT_NEXT_TAB); +} + +bool AutomatedUITest::SelectPreviousTab() { + return ApplyAccelerator(IDC_SELECT_PREV_TAB); +} + +bool AutomatedUITest::ZoomPlus() { + return ApplyAccelerator(IDC_ZOOM_PLUS); +} + +bool AutomatedUITest::ZoomMinus() { + return ApplyAccelerator(IDC_ZOOM_MINUS); +} + +bool AutomatedUITest::ShowHistory() { + return ApplyAccelerator(IDC_SHOW_HISTORY); +} + +bool AutomatedUITest::ShowDownloads() { + return ApplyAccelerator(IDC_SHOW_DOWNLOADS); +} + +bool AutomatedUITest::ImportSettings() { + return ApplyAccelerator(IDC_IMPORT_SETTINGS); +} + +bool AutomatedUITest::ViewPasswords() { + return ApplyAccelerator(IDC_VIEW_PASSWORDS); +} + +bool AutomatedUITest::ClearBrowserData() { + return ApplyAccelerator(IDC_CLEAR_BROWSING_DATA); +} + +bool AutomatedUITest::TaskManager() { + return ApplyAccelerator(IDC_TASKMANAGER); +} + +bool AutomatedUITest::GoOffTheRecord() { + return ApplyAccelerator(IDC_GOOFFTHERECORD); +} + +bool AutomatedUITest::PressEscapeKey() { + return SimulateKeyPressInActiveWindow(VK_ESCAPE, 0); +} + +bool AutomatedUITest::PressTabKey() { + return SimulateKeyPressInActiveWindow(VK_TAB, 0); +} + +bool AutomatedUITest::PressEnterKey() { + return SimulateKeyPressInActiveWindow(VK_RETURN, 0); +} + +bool AutomatedUITest::PressSpaceBar() { + return SimulateKeyPressInActiveWindow(VK_SPACE, 0); +} + +bool AutomatedUITest::PageDown() { + return SimulateKeyPressInActiveWindow(VK_PRIOR, 0); +} + + +bool AutomatedUITest::PageUp() { + return SimulateKeyPressInActiveWindow(VK_NEXT, 0); +} + +bool AutomatedUITest::UpArrow() { + return SimulateKeyPressInActiveWindow(VK_UP, 0); +} + +bool AutomatedUITest::DownArrow() { + return SimulateKeyPressInActiveWindow(VK_DOWN, 0); +} + +bool AutomatedUITest::TestEditKeywords() { + DoAction("EditKeywords"); + return TestDialog(kTestDialogActionsToRun); +} + +bool AutomatedUITest::TestTaskManager() { + DoAction("TaskManager"); + return TestDialog(kTestDialogActionsToRun); +} + +bool AutomatedUITest::TestViewPasswords() { + DoAction("ViewPasswords"); + return TestDialog(kTestDialogActionsToRun); +} + +bool AutomatedUITest::TestClearBrowserData() { + DoAction("ClearBrowserData"); + return TestDialog(kTestDialogActionsToRun); +} + +bool AutomatedUITest::TestImportSettings() { + DoAction("ImportSettings"); + return TestDialog(kTestDialogActionsToRun); +} + +bool AutomatedUITest::TestDialog(int num_actions) { + bool return_value = true; + + for (int i = 0; i < num_actions; i++) { + int action_index = rand_util::RandInt(0, kNumTestDialogActions - 1); + return_value = return_value && + DoAction(test_dialog_possible_actions_[action_index]); + if (DidCrash(false)) + break; + } + return DoAction("PressEscapeKey") && return_value; +} + +bool AutomatedUITest::ForceCrash() { + scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow()); + if (browser.get() == NULL) { + AddErrorAttribute("browser_window_not_found"); + return false; + } + scoped_ptr<TabProxy> tab(browser->GetActiveTab()); + GURL test_url("about:crash"); + bool did_timeout; + tab->NavigateToURLWithTimeout(test_url, kDebuggingTimeoutMsec, &did_timeout); + if (!did_timeout) { + AddInfoAttribute("expected_crash"); + return false; + } + return true; +} + +bool AutomatedUITest::DragActiveTab(bool drag_right, bool drag_out) { + scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow()); + scoped_ptr<WindowProxy> window( + GetAndActivateWindowForBrowser(browser.get())); + if (window.get() == NULL) { + AddErrorAttribute("active_window_not_found"); + return false; + } + bool is_timeout; + + if (browser.get() == NULL) { + AddErrorAttribute("browser_window_not_found"); + return false; + } + int tab_count; + browser->GetTabCountWithTimeout(&tab_count, kWaitForActionMaxMsec, + &is_timeout); + // As far as we're concerned, if we can't get a view for a tab, it doesn't + // exist, so cap tab_count at the number of tab view ids there are. + tab_count = std::min(tab_count, VIEW_ID_TAB_LAST - VIEW_ID_TAB_0); + + int tab_index; + if (!browser->GetActiveTabIndexWithTimeout(&tab_index, + kWaitForActionMaxMsec, + &is_timeout)) { + AddWarningAttribute("no_active_tab"); + return false; + } + + gfx::Rect dragged_tab_bounds; + if (!window->GetViewBoundsWithTimeout(VIEW_ID_TAB_0 + tab_index, + &dragged_tab_bounds, false, + kWaitForActionMaxMsec, + &is_timeout)) { + AddWarningAttribute("no_tab_view_found"); + return false; + } + + // Click on the center of the tab, and drag it to the left or the right. + POINT dragged_tab_point(dragged_tab_bounds.CenterPoint().ToPOINT()); + POINT destination_point(dragged_tab_point); + + int window_count; + if (drag_out) { + destination_point.y += 3*dragged_tab_bounds.height(); + automation()->GetBrowserWindowCount(&window_count); + } else if (drag_right) { + if (tab_index >= (tab_count-1)) { + AddInfoAttribute("index_cant_be_moved"); + return false; + } + destination_point.x += 2*dragged_tab_bounds.width()/3; + } else { + if (tab_index <= 0) { + AddInfoAttribute("index_cant_be_moved"); + return false; + } + destination_point.x -= 2*dragged_tab_bounds.width()/3; + } + + if (!browser->SimulateDragWithTimeout(dragged_tab_point, + destination_point, + ChromeViews::Event::EF_LEFT_BUTTON_DOWN, + kWaitForActionMaxMsec, + &is_timeout)) { + AddWarningAttribute("failed_to_simulate_drag"); + return false; + } + + // If we try to drag the tab out and the window we drag from contains more + // than just the dragged tab, we would expect the window count to increase + // because the dragged tab should open in a new window. If not, we probably + // just dragged into another tabstrip. + if (drag_out && tab_count > 1) { + int new_window_count; + automation()->GetBrowserWindowCount(&new_window_count); + if (new_window_count == window_count) { + AddInfoAttribute("no_new_browser_window"); + return false; + } + } + return true; +} + +WindowProxy* AutomatedUITest::GetAndActivateWindowForBrowser( + BrowserProxy* browser) { + WindowProxy* window = automation()->GetWindowForBrowser(browser); + + bool did_timeout; + if (!browser->BringToFrontWithTimeout(kWaitForActionMaxMsec, &did_timeout)) { + AddWarningAttribute("failed_to_bring_window_to_front"); + return NULL; + } + return window; +} + +bool AutomatedUITest::ApplyAccelerator(int id) { + scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow()); + if (browser.get() == NULL) { + AddErrorAttribute("browser_window_not_found"); + return false; + } + if (!browser->ApplyAccelerator(id)) { + AddWarningAttribute("failure_applying_accelerator"); + return false; + } + return true; +} + +bool AutomatedUITest::SimulateKeyPressInActiveWindow(wchar_t key, int flags) { + scoped_ptr<BrowserProxy> browser(automation()->GetLastActiveBrowserWindow()); + scoped_ptr<WindowProxy> window( + GetAndActivateWindowForBrowser(browser.get())); + if (window.get() == NULL) { + AddErrorAttribute("active_window_not_found"); + return false; + } + if (!window->SimulateOSKeyPress(key, flags)) { + AddWarningAttribute("failure_simulating_key_press"); + return false; + } + return true; +} + +bool AutomatedUITest::InitXMLReader() { + std::wstring input_path; + CommandLine parsed_command_line; + if (parsed_command_line.HasSwitch(kInputFilePathSwitch)) + input_path = parsed_command_line.GetSwitchValue(kInputFilePathSwitch); + else + input_path = kDefaultInputFilePath; + + if (!file_util::ReadFileToString(input_path, &xml_init_file_)) + return false; + return init_reader_.Load(xml_init_file_); +} + +bool AutomatedUITest::WriteReportToFile() { + std::ofstream error_file; + std::wstring path; + CommandLine parsed_command_line; + if (parsed_command_line.HasSwitch(kOutputFilePathSwitch)) + path = parsed_command_line.GetSwitchValue(kOutputFilePathSwitch); + else + path = kDefaultOutputFilePath; + + if (!path.empty()) + error_file.open(path.c_str(), std::ios::out); + + // Closes all open elements and free the writer. This is required + // in order to retrieve the contents of the buffer. + xml_writer_.StopWriting(); + error_file << xml_writer_.GetWrittenString(); + error_file.close(); + return true; +} + +void AutomatedUITest::AppendToOutputFile(const std::string &append_string) { + std::ofstream error_file; + std::wstring path; + CommandLine parsed_command_line; + if (parsed_command_line.HasSwitch(kOutputFilePathSwitch)) + path = parsed_command_line.GetSwitchValue(kOutputFilePathSwitch); + else + path = kDefaultOutputFilePath; + + if (!path.empty()) + error_file.open(path.c_str(), std::ios::out | std::ios_base::app); + + error_file << append_string << " "; + error_file.close(); +} + +void AutomatedUITest::LogCrashResult(const std::string &crash_dump, + bool command_completed) { + xml_writer_.StartElement("result"); + xml_writer_.StartElement("crash"); + xml_writer_.AddAttribute("crash_dump", crash_dump); + if (command_completed) + xml_writer_.AddAttribute("command_completed", "yes"); + else + xml_writer_.AddAttribute("command_completed", "no"); + xml_writer_.EndElement(); + xml_writer_.EndElement(); +} + +void AutomatedUITest::LogSuccessResult() { + xml_writer_.StartElement("result"); + xml_writer_.StartElement("success"); + xml_writer_.EndElement(); + xml_writer_.EndElement(); +} + +void AutomatedUITest::AddInfoAttribute(const std::string &info) { + xml_writer_.AddAttribute("info", info); +} + +void AutomatedUITest::AddWarningAttribute(const std::string &warning) { + xml_writer_.AddAttribute("warning", warning); +} + +void AutomatedUITest::AddErrorAttribute(const std::string &error) { + xml_writer_.AddAttribute("error", error); +} + +std::wstring AutomatedUITest::GetMostRecentCrashDump() { + std::wstring crash_dump_path; + int file_count = 0; + FILETIME most_recent_file_time; + std::wstring most_recent_file_name; + WIN32_FIND_DATA find_file_data; + + PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path); + // All files in the given directory. + std::wstring filename_spec = crash_dump_path + L"\\*"; + HANDLE find_handle = FindFirstFile(filename_spec.c_str(), &find_file_data); + if (find_handle != INVALID_HANDLE_VALUE) { + most_recent_file_time = find_file_data.ftCreationTime; + most_recent_file_name = find_file_data.cFileName; + do { + // Don't count current or parent directories. + if ((wcscmp(find_file_data.cFileName, L"..") == 0) || + (wcscmp(find_file_data.cFileName, L".") == 0)) + continue; + + long result = CompareFileTime(&find_file_data.ftCreationTime, + &most_recent_file_time); + + // File was created on or after the current most recent file. + if ((result == 1) || (result == 0)) { + most_recent_file_time = find_file_data.ftCreationTime; + most_recent_file_name = find_file_data.cFileName; + } + } while (FindNextFile(find_handle, &find_file_data)); + FindClose(find_handle); + } + + if (most_recent_file_name.empty()) { + return L""; + } else { + file_util::AppendToPath(&crash_dump_path, most_recent_file_name); + return crash_dump_path; + } +} + +bool AutomatedUITest::DidCrash(bool update_total_crashes) { + std::wstring crash_dump_path; + PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path); + // Each crash creates two dump files, so we divide by two here. + int actual_crashes = file_util::CountFilesCreatedAfter( + crash_dump_path, test_start_time_) / 2; + + // If there are more crash dumps than the total dumps which we have recorded + // then this is a new crash. + if (actual_crashes > total_crashes_) { + if (update_total_crashes) + total_crashes_ = actual_crashes; + return true; + } else { + return false; + } +} + +TEST_F(AutomatedUITest, TheOneAndOnlyTest) { + CommandLine parsed_command_line; + if (parsed_command_line.HasSwitch(kReproSwitch)) + RunReproduction(); + else + RunAutomatedUITest(); +} diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.h b/chrome/test/automated_ui_tests/automated_ui_tests.h new file mode 100644 index 0000000..96475ee --- /dev/null +++ b/chrome/test/automated_ui_tests/automated_ui_tests.h @@ -0,0 +1,443 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__ +#define CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__ + +// This takes an input file of commands, which consist of a series of +// actions, and runs every command, reporting the status of each one +// to an output file once all the commands have been run. +// +// The input file should be an XML file that has a root of any name followed +// by a series of elements named "command" with child elements representing +// the various actions, in order, to be performed during each command. A +// command element can optionally include an "number" attribute to identify it. +// +// Example: +// <CommandList> +// <command number="1"><NewTab/><Navigate/><OpenWindow/><Navigate/><Back/> +// </command> +// <command number="2"><NewTab/><Navigate/><Navigate/><Back/><Forward/> +// </command> +// <command number="3"><CloseTab/><OpenWindow/><NewTab/><Navigate/><CloseTab/> +// </command> +// </CommandList> +// +// When the test is finished it will output results to the output file, +// overwriting any previous version of this file. The output file is an +// XML file which reports on each command, indicating whether it successfully +// ran and if there were any errors. +// +// Example: (actual output will probably contain more actions per command): +// <Report> +// <Executed command_number="1"><NewTab/><Navigate/><result><success/> +// </result> </Executed> +// <Executed command_number="2"><Back/><Forward/><result><success/></result> +// </Executed> +// <Executed command_number="3"><CloseTab/><result> +// <crash crash_dump="C:\a_crash.txt" command_completed="no"/></result> +// </Executed> +// </Report> +// +// A "crash" result will have two attributes, crash_dump, which points +// to the full path of crash dump associated with this crash, and +// command_completed which indicates whether or not the last +// action recorded was the final action of the command. +// +// Furthermore, each individual action may contain additional attributes +// to log non-fatal failures. If the attribute 'failed_to_complete="yes"' +// is present, then the action did not complete. If that attribute is present, +// an info, warning, or error attribute will also be present, and will contain +// a string describing the error. The presence of info means the failure was +// expected, probably due to a state making the action impossible to perform +// like trying to close the last remaining window. Warnings usually mean the +// action couldn't complete for an unknown and unexpected reason, but that the +// test state is probably fine. Errors are like warnings, but they mean the test +// state is probably incorrect, and more failures are likely to be caused by +// the same problem. +// +// Example of some failed actions: +// <CloseTab failed_to_complete="yes" info="would_have_exited_application"/> +// <Reload failed_to_complete="yes" warning="failed_to_apply_accelerator"/> +// <Star failed_to_complete="yes" error="browser_window_not_found"/> +// +// +// Switches +// --input : Specifies the input file, must be an absolute directory. +// Default is "C:\automated_ui_tests.txt" +// +// --output : Specifies the output file, must be an absolute directory. +// Default is "C:\automated_ui_tests_error_report.txt" +// +// +// Test reproduction options: +// +// If you're trying to reproduce the results from crash reports use the +// following switches +// +// --key : Specifies, via a comma delimited list, what actions to run. Examples: +// --key=SetUp,ZoomPlus,Forward,History,Navigate,Back,TearDown +// --key=SetUp,ZoomPlus +// Note, the second key doesn't include a TearDown, that will +// automatically be added if the result doesn't crash. +// +// --num-reproductions : Specifies the number of reproductions to run, the +// default is 1. Suggested use: run without this flag +// to see if we reproduce a crash, then run with the flag +// if there isn't a crash, to see if it might be a rare +// race condition that causes the crash. +// +// +// Debugging options: +// +// --debug : Will append each action that is performed to the output file, as +// soon as the action is performed. If the program finishes, this file +// will be overwritten with the normal results. This flag is used to +// help debug the tests if they are crashing before they get a chance +// to write their results to file. + +#include "chrome/test/ui/ui_test.h" + +// Size of the array of possible actions to use when testing a dialog. +const int kNumTestDialogActions = 4; + +class AutomatedUITest : public UITest { + protected: + AutomatedUITest(); + ~AutomatedUITest(); + + // Runs a reproduction of one set of actions, reporting whether they crash + // or not. + void RunReproduction(); + + // Runs automated UI tests which are read from the input file. + // Reports crashes to the output file. + void RunAutomatedUITest(); + + // Attempts to perform an action based on the input string. See below for + // possible actions. Returns true if the action completes, false otherwise. + bool DoAction(const std::string &action); + + // Actions ------------------------------------------------------------------ + + // Navigates the activate tab to about:blank. + // XML element: <Navigate/> + // Optional Attributes: url="|address|" will navigate to |address| + bool Navigate(); + + // Opens a new tab in the active window using an accelerator. + // Returns true if call to activate the accelerator is successful. + // XML element: <NewTab/> + bool NewTab(); + + // Activates back button in active window. + // Returns true if call to activate the accelerator is successful. + // XML element: <Back/> + bool BackButton(); + + // Activates forward button in active window. + // Returns true if call to activate the accelerator is successful. + // XML element: <Forward/> + bool ForwardButton(); + + // Uses accelerator to close the active tab if it isn't the only tab. + // Returns false if active tab is the only tab, true otherwise. + // XML element: <CloseTab/> + bool CloseActiveTab(); + + // Opens a new browser window by calling automation()->OpenNewBrowserWindow + // Then activates the tab opened in the new window. + // Returns true if window is successfully created. + // XML element: <OpenWindow/> + bool OpenAndActivateNewBrowserWindow(); + + // Reload the active tab. Returns false on failure. + // XML element: <Reload/> + bool ReloadPage(); + + // Stars the current page. This opens a dialog that may or may not be + // dismissed. + // XML element: <Star/> + bool StarPage(); + + // Activates "find in page" on the current page. + // XML element: <FindInPage/> + bool FindInPage(); + + // Activates the next tab on the active browser window. + // XML element: <SelectNextTab/> + bool SelectNextTab(); + + // Activates the previous tab on the active browser window. + // XML element: <SelectPrevTab/> + bool SelectPreviousTab(); + + // Increases the text size on the current active tab. + // XML element: <ZoomPlus/> + bool ZoomPlus(); + + // Decreases the text size on the current active tab. + // XML element: <ZoomMinus/> + bool ZoomMinus(); + + // Opens the History page in the current active browser window. + // XML element: <History/> + bool ShowHistory(); + + // Opens the Downloads page in the current active browser window. + // XML element: <Downloads/> + bool ShowDownloads(); + + // Opens the Import Settings dialog, this dialog is modal so a majority of + // the test can't be completed until it is dismissed. + // XML element: <ImportSettings/> + bool ImportSettings(); + + // Opens the View Passwords dialog, this dialog is modal so a majority of + // the test can't be completed until it is dismissed. + // XML element: <ViewPasswords/> + bool ViewPasswords(); + + // Opens the Clear Browser Data dialog, this dialog is modal so a majority of + // the test can't be completed until it is dismissed. + // XML element: <ClearBrowserData/> + bool ClearBrowserData(); + + // Opens the Task Manager dialog. While it isn't modal, it takes focus from + // the current browser window, so most of the test can't continue until is + // dismissed. + // XML element: <TaskManager/> + bool TaskManager(); + + // Opens and focuses an OffTheRecord browser window. + // XML element: <GoOffTheRecord/> + bool GoOffTheRecord(); + + // Simulates an escape key press on the active window. + // XML element: <PressEscapeKey/> + bool PressEscapeKey(); + + // Simulates a tab key press on the active window. + // XML element: <PressTabKey/> + bool PressTabKey(); + + // Simulates an enter key press on the active window. + // XML element: <PressEnterKey/> + bool PressEnterKey(); + + // Simulates a space bar press on the active window. + // XML element: <PressSpaceBar/> + bool PressSpaceBar(); + + // Simulates a page down key press on the active window. + // XML element: <PageDown/> + bool PageDown(); + + // Simulates a page up key press on the active window. + // XML element: <PageUp/> + bool PageUp(); + + // Simulates a page up key press on the active window. + // XML element: <UpArrow/> + bool UpArrow(); + + // Simulates a page up key press on the active window. + // XML element: <DownArrow/> + bool DownArrow(); + + // Test Dialog Actions ****************************************************** + // These are a special set of actions that perform multiple actions on a + // specified dialog. They run kTestDialogActionsToRun actions randomly + // chosen from test_dialog_possible_actions_ after opening the dialog. They + // then always end with a PressEscapeKey action, to attempt to close the + // dialog. + // + // The randomly performed actions are logged as child elements of the + // TestDialog action. For example (for kTestDialogActionsToRun = 4): + // <TestEditKeywords> <PressTabKey/><PressEnterKey/><DownArrow/> + // <DownArrow/><PressEscapeKey/> </TestEditKeywords> + + // Opens Edit Keywords dialog and runs random actions on it. + // XML element: <TestEditKeywords/> + bool TestEditKeywords(); + + // Opens Task Manager and runs random actions on it. + // This has the possibility of killing both the browser and renderer + // processes, which will cause non-fatal errors for the remaining actions + // in this command. + // XML element: <TestTaskManager/> + bool TestTaskManager(); + + // Opens View Passwords dialog and runs random actions on it. + // XML element: <TestViewPasswords/> + bool TestViewPasswords(); + + // Opens Clear Browser Data dialog and runs random actions on it. + // XML element: <TestClearBrowserData/> + bool TestClearBrowserData(); + + // Opens Import Settings dialog and runs random actions on it. + // XML element: <TestImportSettings/> + bool TestImportSettings(); + + // End Test Dialog Actions ************************************************** + + // Runs a limited set of actions designed to test dialogs. Will run + // |num_actions| from the set defined in test_dialog_possible_actions_. + bool TestDialog(int num_actions); + + // Navigates to about:crash. + // XML element: <Crash/> + bool ForceCrash(); + + // Drags the active tab. If |drag_out| is true, |drag_right| is ignored and + // the tab is dragged vertically to remove it from the tabstrip. Otherwise, + // If |drag_right| is true, if there is a tab to the right of the active tab, + // the active tab is dragged to that tabs position. If |drag_right| is false, + // if there is a tab to the left of the active tab, the active tab is dragged + // to that tabs position. Returns false if the tab isn't dragged, or if an + // attempt to drag out doesn't create a new window (likely because it was + // dragged in to another window). + // XML element (multiple elements use this): + // <DragTabRight/> - Calls DragActiveTab(true, false) (attempt to drag right) + // <DragTabLeft/> - Calls DragActiveTab(false, false) (attempt to drag left) + // <DragTabOut/> - Calls DragActiveTab(false, true) (attempt to drag tab out) + bool DragActiveTab(bool drag_right, bool drag_out); + + // Utility functions -------------------------------------------------------- + + // Returns the WindowProxy associated with the given BrowserProxy + // (transferring ownership of the pointer to the caller) and brings that + // window to the top. + WindowProxy* GetAndActivateWindowForBrowser(BrowserProxy* browser); + + // Applies the accelerator with the given ID to the current active window. + // Returns true if the call is successful. + // Returns false if the active window is not a browser window or if the + // message to apply the accelerator fails. + bool ApplyAccelerator(int id); + + // Calls SimulateOSKeyPress on the active window. Simulates a key press at + // the OS level. |key| is the key pressed and |flags| specifies which + // modifiers keys are also pressed (as defined inchrome/views/event.h). + bool SimulateKeyPressInActiveWindow(wchar_t key, int flags); + + // Opens init file, reads it into the reader, and closes the file. + // Returns false if there are any errors. + bool InitXMLReader(); + + // Closes the xml_writer and outputs the contents of its buffer to + // the output file. + bool WriteReportToFile(); + + // Appends the provided string to the output file. + void AppendToOutputFile(const std::string &append_string); + + // Logs a crash to the xml_writer in the form of: + // <result><crash crash_dump="|crash_dump|" command_completed="yes/no"/> + // </result> + // crash_dump - Location of crash dump if applicable. + // command_completed - True if all actions in the command were completed + // before the crash occured. + void LogCrashResult(const std::string &crash_dump, bool command_completed); + + // Logs a successful command to the xml_writer in the form of: + // <result><success/><result/> + void LogSuccessResult(); + + // Adds the attribute "reason=|reason|" to the current element. + // Used to log the reason for a given failure while performing an action. + void LogActionFailureReason(const std::string &reason); + + // Adds the attribute 'info="|info|"' to the current element. Used when an + // action could not complete for a non-serious issue. Usually because the + // state of the test wouldn't allow for a particular action. + void AddInfoAttribute(const std::string &info); + + // Adds the attribute "warning=|warning|" to the current element. Used when + // an action could not complete because of a potentially troublesome issue. + void AddWarningAttribute(const std::string &warning); + + // Adds the attribute "error=|error|" to the current element. Used when an + // action could not complete due to an unexpected problem which might + // invalidate the results of the entire command (not just the action). + // This is usually used when the testing environment isn't acting as we'd + // expect. For example, no chrome windows are focused, or key presses aren't + // being registered. + void AddErrorAttribute(const std::string &error); + + // Returns the full path of the crash dump. This is likely to be the + // .txt file, not the actual crash dump. Although they do share + // a common name. + std::wstring GetMostRecentCrashDump(); + + // Returns true if the test has produced any new crash logs. + // A "new" crash log is one that was produced since DidCrash was last called + // with |update_total_crashes| set to true. + bool DidCrash(bool update_total_crashes); + + // Overridden so that UI Test doesn't set up when the tests start. + // We use DoAction("SetUp") to set up, because it logs it and makes + // it easier to check for crashes when we start the browser. + virtual void SetUp() {} + + // Overridden so that UI Test doesn't close the browser (which is already + // closed) at the end of the test. + // We use DoAction("TearDown") to tear down, because it logs it and makes + // it easier to check for crashes when we close the browser. + virtual void TearDown() {} + + private: + // Parses the init file. + XmlReader init_reader_; + + // Builds the output file. + XmlWriter xml_writer_; + + // Time the test was started. Used to find crash dumps. + FILETIME test_start_time_; + + // Number of times the browser has crashed during this run. + // Used to check for new crashes. + int total_crashes_; + + // Used to init the init_reader_. It must exist as long as the reader does. + std::string xml_init_file_; + + // If true, appends the commands to the output file as they are executed. + // Used for debugging when automated_ui_tests.cc crashes before it outputs + // results. + bool debug_logging_enabled_; + + static std::string test_dialog_possible_actions_[kNumTestDialogActions]; + + DISALLOW_EVIL_CONSTRUCTORS(AutomatedUITest); +}; + +#endif // #define CHROME_TEST_AUTOMATED_UI_TESTS_AUTOMATED_UI_TESTS_H__ diff --git a/chrome/test/automated_ui_tests/automated_ui_tests.vcproj b/chrome/test/automated_ui_tests/automated_ui_tests.vcproj new file mode 100644 index 0000000..71914d1 --- /dev/null +++ b/chrome/test/automated_ui_tests/automated_ui_tests.vcproj @@ -0,0 +1,212 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="automated_ui_tests" + ProjectGUID="{D2250C20-3A94-4FB9-AF73-11BC5B73884B}" + RootNamespace="page_cycler_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath="..\ui\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath="..\ui\ui_test.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.h" + > + </File> + <File + RelativePath="..\ui\ui_test_suite.cc" + > + </File> + </Filter> + <Filter + Name="MemoryUsage" + > + <File + RelativePath="..\perf\mem_usage.cc" + > + </File> + <File + RelativePath="..\perf\mem_usage.h" + > + </File> + </Filter> + <Filter + Name="AutomatedUITest" + > + <File + RelativePath=".\automated_ui_tests.cc" + > + </File> + <File + RelativePath=".\automated_ui_tests.h" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/automation/SConscript b/chrome/test/automation/SConscript new file mode 100644 index 0000000..79286f2 --- /dev/null +++ b/chrome/test/automation/SConscript @@ -0,0 +1,58 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env')
+
+env = env.Clone()
+
+env.Prepend(
+ CPPPATH = [
+ #'../../..',
+ #'$GTEST_DIR/include',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+)
+
+input_files = [
+ 'autocomplete_edit_proxy.cc',
+ 'automation_handle_tracker.cc',
+ 'automation_proxy.cc',
+ 'browser_proxy.cc',
+ 'constrained_window_proxy.cc',
+ 'tab_proxy.cc',
+ 'window_proxy.cc',
+]
+
+lib = env.StaticLibrary('automation', input_files)
+
+i = env.Install('$TARGET_ROOT', lib)
+env.Alias('chrome', i)
diff --git a/chrome/test/automation/autocomplete_edit_proxy.cc b/chrome/test/automation/autocomplete_edit_proxy.cc new file mode 100644 index 0000000..33303ad --- /dev/null +++ b/chrome/test/automation/autocomplete_edit_proxy.cc @@ -0,0 +1,136 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/automation/autocomplete_edit_proxy.h" + +#include <vector> + +#include "chrome/test/automation/automation_constants.h" +#include "chrome/test/automation/automation_messages.h" +#include "chrome/test/automation/automation_proxy.h" + +bool AutocompleteEditProxy::GetText(std::wstring* text) const { + if (!is_valid()) + return false; + if (!text) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + if (!sender_->SendAndWaitForResponse( + new AutomationMsg_AutocompleteEditGetTextRequest(0, handle_), &response, + AutomationMsg_AutocompleteEditGetTextResponse::ID)) + return false; + scoped_ptr<IPC::Message> response_deleter(response); + + Tuple2<bool, std::wstring> returned_result; + if (!AutomationMsg_AutocompleteEditGetTextResponse::Read(response, + &returned_result) || !returned_result.a) + return false; + + text->swap(returned_result.b); + return true; +} + +bool AutocompleteEditProxy::SetText(const std::wstring& text) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + if (!sender_->SendAndWaitForResponse( + new AutomationMsg_AutocompleteEditSetTextRequest(0, handle_, text), + &response, AutomationMsg_AutocompleteEditSetTextResponse::ID)) + return false; + + delete response; + return true; +} + +bool AutocompleteEditProxy::IsQueryInProgress(bool* query_in_progress) const { + if (!is_valid()) + return false; + if (!query_in_progress) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + if (!sender_->SendAndWaitForResponse( + new AutomationMsg_AutocompleteEditIsQueryInProgressRequest(0, handle_), + &response, AutomationMsg_AutocompleteEditIsQueryInProgressResponse::ID)) + return false; + scoped_ptr<IPC::Message> response_deleter(response); + + Tuple2<bool, bool> returned_result; + if (!AutomationMsg_AutocompleteEditIsQueryInProgressResponse::Read( + response, &returned_result) || !returned_result.a) + return false; + + *query_in_progress = returned_result.b; + return true; +} + + +bool AutocompleteEditProxy::WaitForQuery(int wait_timeout_ms) const { + const TimeTicks start = TimeTicks::Now(); + const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout_ms); + bool query_in_progress; + while (TimeTicks::Now() - start < timeout) { + if (IsQueryInProgress(&query_in_progress) && !query_in_progress) + return true; + Sleep(automation::kSleepTime); + } + // If we get here the query is still in progress. + return false; +} + +bool AutocompleteEditProxy::GetAutocompleteMatches(Matches* matches) const { + if (!is_valid()) + return false; + if (!matches) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + if (!sender_->SendAndWaitForResponse( + new AutomationMsg_AutocompleteEditGetMatchesRequest(0, handle_), + &response, AutomationMsg_AutocompleteEditGetMatchesResponse::ID)) + return false; + scoped_ptr<IPC::Message> response_deleter(response); + + Tuple2<bool, Matches> returned_result; + if (!AutomationMsg_AutocompleteEditGetMatchesResponse::Read( + response, &returned_result) || !returned_result.a) + return false; + + *matches = returned_result.b; + return true; +} diff --git a/chrome/test/automation/autocomplete_edit_proxy.h b/chrome/test/automation/autocomplete_edit_proxy.h new file mode 100644 index 0000000..608d1f1 --- /dev/null +++ b/chrome/test/automation/autocomplete_edit_proxy.h @@ -0,0 +1,169 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATION_AUTOCOMPLETE_EDIT_PROXY_H__ +#define CHROME_TEST_AUTOMATION_AUTOCOMPLETE_EDIT_PROXY_H__ + +#include <string> +#include <vector> + +#include "chrome/browser/autocomplete/autocomplete.h" +#include "chrome/common/ipc_message.h" +#include "chrome/common/ipc_message_utils.h" +#include "chrome/test/automation/automation_handle_tracker.h" + +// The purpose of this class is to act as a searializable version of +// AutocompleteMatch. The reason for this class is because we don't want to +// searialize all elements of AutocompleteMatch and we want some data from the +// autocomplete provider without the hassle of serializing it. +struct AutocompleteMatchData { + public: + AutocompleteMatchData() {} + explicit AutocompleteMatchData(const AutocompleteMatch& match) + : contents(match.contents), + deletable(match.deletable), + description(match.description), + destination_url(match.destination_url), + fill_into_edit(match.fill_into_edit), + inline_autocomplete_offset(match.inline_autocomplete_offset), + is_history_what_you_typed_match(match.is_history_what_you_typed_match), + provider_name(match.provider->name()), + relevance(match.relevance), + starred(match.starred) { + switch (match.type) { + case AutocompleteMatch::URL: + str_type = L"URL"; + break; + case AutocompleteMatch::KEYWORD: + str_type = L"KEYWORD"; + break; + case AutocompleteMatch::SEARCH: + str_type = L"SEARCH"; + break; + case AutocompleteMatch::HISTORY_SEARCH: + str_type = L"HISTORY"; + break; + default: + NOTREACHED(); + } + } + std::wstring contents; + bool deletable; + std::wstring description; + std::wstring destination_url; + std::wstring fill_into_edit; + size_t inline_autocomplete_offset; + bool is_history_what_you_typed_match; + std::string provider_name; + int relevance; + bool starred; + std::wstring str_type; +}; +typedef std::vector<AutocompleteMatchData> Matches; + +namespace IPC { + +template <> +struct ParamTraits<AutocompleteMatchData> { + typedef AutocompleteMatchData param_type; + static void Write(Message* m, const param_type& p) { + m->WriteWString(p.contents); + m->WriteBool(p.deletable); + m->WriteWString(p.description); + m->WriteWString(p.destination_url); + m->WriteWString(p.fill_into_edit); + m->WriteSize(p.inline_autocomplete_offset); + m->WriteBool(p.is_history_what_you_typed_match); + m->WriteString(p.provider_name); + m->WriteInt(p.relevance); + m->WriteBool(p.starred); + m->WriteWString(p.str_type); + } + + static bool Read(const Message* m, void** iter, param_type* r) { + return m->ReadWString(iter, &r->contents) && + m->ReadBool(iter, &r->deletable) && + m->ReadWString(iter, &r->description) && + m->ReadWString(iter, &r->destination_url) && + m->ReadWString(iter, &r->fill_into_edit) && + m->ReadSize(iter, &r->inline_autocomplete_offset) && + m->ReadBool(iter, &r->is_history_what_you_typed_match) && + m->ReadString(iter, &r->provider_name) && + m->ReadInt(iter, &r->relevance) && + m->ReadBool(iter, &r->starred) && + m->ReadWString(iter, &r->str_type); + } + + static void Log(const param_type& p, std::wstring* l) { + l->append(StringPrintf(L"[%S %s %S %S %S %d %s %s %d %s %S]", + p.contents, p.deletable ? "true" : "false", p.description, + p.destination_url, p.fill_into_edit, p.inline_autocomplete_offset, + p.is_history_what_you_typed_match ? "true" : "false", p.provider_name, + p.relevance, p.starred ? "true" : "false", p.str_type)); + } +}; +} // namespace IPC + +class AutocompleteEditProxy : public AutomationResourceProxy { + public: + AutocompleteEditProxy(AutomationMessageSender* sender, + AutomationHandleTracker* tracker, + int handle) + : AutomationResourceProxy(tracker, sender, handle) {} + virtual ~AutocompleteEditProxy() {} + + // All these functions return true if the autocomplete edit is valid and + // there are no IPC errors. + + // Gets the text visible in the omnibox. + bool GetText(std::wstring* text) const; + + // Sets the text visible in the omnibox. + bool SetText(const std::wstring& text); + + // Determines if a query to an autocomplete provider is still in progress. + // NOTE: No autocomplete queries will be made if the omnibox doesn't have + // focus. This can be achieved by sending a IDC_FOCUS_LOCATION accelerator + // to the browser. + bool IsQueryInProgress(bool* query_in_progress) const; + + // Gets a list of autocomplete matches that have been gathered so far. + bool GetAutocompleteMatches(Matches* matches) const; + + // Waits for all queries to autocomplete providers to complete. + // |wait_timeout_ms| gives the number of milliseconds to wait for the query + // to finish. Returns false if IPC call failed or if the function times out. + bool WaitForQuery(int wait_timeout_ms) const; + + private: + DISALLOW_EVIL_CONSTRUCTORS(AutocompleteEditProxy); +}; + +#endif // #define CHROME_TEST_AUTOMATION_AUTOCOMPLETE_EDIT_PROXY_H__ + diff --git a/chrome/test/automation/automation.vcproj b/chrome/test/automation/automation.vcproj new file mode 100644 index 0000000..38781fc --- /dev/null +++ b/chrome/test/automation/automation.vcproj @@ -0,0 +1,193 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="automation" + ProjectGUID="{1556EF78-C7E6-43C8-951F-F6B43AC0DD12}" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="4" + InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\automation.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="4" + InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\automation.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath=".\autocomplete_edit_proxy.cc" + > + </File> + <File + RelativePath=".\autocomplete_edit_proxy.h" + > + </File> + <File + RelativePath=".\automation_constants.h" + > + </File> + <File + RelativePath=".\automation_handle_tracker.cc" + > + </File> + <File + RelativePath=".\automation_handle_tracker.h" + > + </File> + <File + RelativePath=".\automation_messages.h" + > + </File> + <File + RelativePath=".\automation_messages_internal.h" + > + </File> + <File + RelativePath=".\automation_proxy.cc" + > + </File> + <File + RelativePath=".\automation_proxy.h" + > + </File> + <File + RelativePath=".\browser_proxy.cc" + > + </File> + <File + RelativePath=".\browser_proxy.h" + > + </File> + <File + RelativePath=".\constrained_window_proxy.cc" + > + </File> + <File + RelativePath=".\constrained_window_proxy.h" + > + </File> + <File + RelativePath=".\tab_proxy.cc" + > + </File> + <File + RelativePath=".\tab_proxy.h" + > + </File> + <File + RelativePath=".\window_proxy.cc" + > + </File> + <File + RelativePath=".\window_proxy.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/automation/automation.vsprops b/chrome/test/automation/automation.vsprops new file mode 100644 index 0000000..4cc3b79 --- /dev/null +++ b/chrome/test/automation/automation.vsprops @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="automation" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\skia\using_skia.vsprops" + > + <Tool + Name="VCCLCompilerTool" + /> +</VisualStudioPropertySheet> diff --git a/chrome/test/automation/automation_constants.h b/chrome/test/automation/automation_constants.h new file mode 100644 index 0000000..994d233 --- /dev/null +++ b/chrome/test/automation/automation_constants.h @@ -0,0 +1,38 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATION_AUTOMATION_CONSTANTS_H__ +#define CHROME_TEST_AUTOMATION_AUTOMATION_CONSTANTS_H__ + +namespace automation { + // Amount of time to wait before querying the browser. + static const int kSleepTime = 250; +} + +#endif // CHROME_TEST_AUTOMATION_AUTOMATION_CONSTANTS_H__
\ No newline at end of file diff --git a/chrome/test/automation/automation_handle_tracker.cc b/chrome/test/automation/automation_handle_tracker.cc new file mode 100644 index 0000000..a31d125 --- /dev/null +++ b/chrome/test/automation/automation_handle_tracker.cc @@ -0,0 +1,97 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/automation/automation_handle_tracker.h" + +#include "chrome/test/automation/automation_messages.h" +#include "chrome/test/automation/automation_proxy.h" + +AutomationResourceProxy::AutomationResourceProxy( + AutomationHandleTracker* tracker, AutomationMessageSender* sender, + AutomationHandle handle) + : tracker_(tracker), + sender_(sender), + handle_(handle), + is_valid_(true) { + tracker_->Add(this); +} + +AutomationResourceProxy::~AutomationResourceProxy() { + if (tracker_) + tracker_->Remove(this); +} + +AutomationHandleTracker::~AutomationHandleTracker() { + // Tell any live objects that the tracker is going away so they don't try to + // call us when they are being destroyed. + for (HandleToObjectMap::iterator iter = handle_to_object_.begin(); + iter != handle_to_object_.end(); ++iter) { + iter->second->Invalidate(); + iter->second->TrackerGone(); + } +} + +void AutomationHandleTracker::Add(AutomationResourceProxy* proxy) { + handle_to_object_.insert(MapEntry(proxy->handle(), proxy)); +} + +void AutomationHandleTracker::Remove(AutomationResourceProxy* proxy) { + HandleToObjectMap::iterator iter = handle_to_object_.find(proxy->handle()); + if (iter == handle_to_object_.end()) + return; + + HandleToObjectMap::iterator end_of_matching_objects = + handle_to_object_.upper_bound(proxy->handle()); + + while(iter != end_of_matching_objects) { + if (iter->second == proxy) { + handle_to_object_.erase(iter); + + // If we have no more proxy objects using this handle, tell the + // app that it can clean up that handle. If the proxy isn't valid, + // that means that the app has already discarded this handle, and + // thus doesn't need to be notified that the handle is unused. + if (proxy->is_valid() && handle_to_object_.count(proxy->handle()) == 0) { + sender_->Send(new AutomationMsg_HandleUnused(0, proxy->handle())); + } + return; + } + ++iter; + } +} + +void AutomationHandleTracker::InvalidateHandle(AutomationHandle handle) { + HandleToObjectMap::iterator iter = handle_to_object_.lower_bound(handle); + HandleToObjectMap::const_iterator end_of_matching_objects = + handle_to_object_.upper_bound(handle); + + for (; iter != end_of_matching_objects; ++iter) { + iter->second->Invalidate(); + } +} diff --git a/chrome/test/automation/automation_handle_tracker.h b/chrome/test/automation/automation_handle_tracker.h new file mode 100644 index 0000000..8f064e3 --- /dev/null +++ b/chrome/test/automation/automation_handle_tracker.h @@ -0,0 +1,128 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file defines a mapping between Automation Proxy objects and +// their associated app-side handles. + +#ifndef CHROME_TEST_AUTOMATION_AUTOMATION_HANDLE_TRACKER_H__ +#define CHROME_TEST_AUTOMATION_AUTOMATION_HANDLE_TRACKER_H__ + +#include <map> + +#include "base/basictypes.h" + +// This represents a value that the app's AutomationProvider returns +// when asked for a resource (like a window or tab). +typedef int AutomationHandle; + +class AutomationHandleTracker; +class AutomationMessageSender; + +class AutomationResourceProxy { + public: + AutomationResourceProxy(AutomationHandleTracker* tracker, + AutomationMessageSender* sender, + AutomationHandle handle); + virtual ~AutomationResourceProxy(); + + // Marks this proxy object as no longer valid; this generally means + // that the corresponding resource on the app side is gone. + void Invalidate() { is_valid_ = false; } + bool is_valid() const { return is_valid_; } + + // Returns the handle that the app has generated to refer to this resource. + AutomationHandle handle() { return handle_; } + + protected: + friend class AutomationHandleTracker; + + AutomationHandle handle_; + + // Called by the tracker when it is being destroyed so we know not to call + // it back. + void TrackerGone() { + tracker_ = NULL; + } + + // Not owned by us, owned by the AutomationProxy object. May be NULL if the + // tracker has been destroyed (and hence the object is invalid). + AutomationHandleTracker* tracker_; + + // Not owned by us. + AutomationMessageSender* sender_; + + private: + // True if the resource that this object is a proxy for on the app side + // still exists. + bool is_valid_; + + DISALLOW_EVIL_CONSTRUCTORS(AutomationResourceProxy); +}; + +// This class keeps track of the mapping between AutomationHandles and +// AutomationResourceProxy objects. This is important because (1) multiple +// AutomationResourceProxy objects can be generated for the same handle +// (2) handles can be invalidated by the app, and all the associated +// proxy objects then need to be invalidated, and (3) when a handle is no +// longer being used on this end, we need to tell the app that it can +// discard the handle. +class AutomationHandleTracker { + public: + AutomationHandleTracker(AutomationMessageSender* sender) + : sender_(sender) {} + ~AutomationHandleTracker(); + + // Adds the specified proxy object to the tracker. + void Add(AutomationResourceProxy* proxy); + + // Removes a given proxy object from the mapping, and unregisters the + // handle on the app side if this was the last proxy object that was using + // that handle. This is a no-op if the proxy object is not currently + // in the tracker. + void Remove(AutomationResourceProxy* proxy); + + // Marks all proxy objects related to a given handle invalid. This is + // used when a resource (like a window) on the app side is closed, meaning + // that no further operations can be completed using the handle that + // identified that resource. + void InvalidateHandle(AutomationHandle handle); + + private: + typedef + std::multimap<AutomationHandle, AutomationResourceProxy*> HandleToObjectMap; + typedef std::pair<AutomationHandle, AutomationResourceProxy*> MapEntry; + + HandleToObjectMap handle_to_object_; + + AutomationMessageSender* sender_; + + DISALLOW_EVIL_CONSTRUCTORS(AutomationHandleTracker); +}; + +#endif // CHROME_TEST_AUTOMATION_AUTOMATION_HANDLE_TRACKER_H__
\ No newline at end of file diff --git a/chrome/test/automation/automation_messages.h b/chrome/test/automation/automation_messages.h new file mode 100644 index 0000000..a106e38 --- /dev/null +++ b/chrome/test/automation/automation_messages.h @@ -0,0 +1,65 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATION_AUTOMATION_MESSAGES_H__ +#define CHROME_TEST_AUTOMATION_AUTOMATION_MESSAGES_H__ + +#include <string> + +#include "base/basictypes.h" +#include "chrome/common/ipc_message.h" +#include "chrome/common/ipc_message_utils.h" + +enum AutomationMsg_NavigationResponseValues { + AUTOMATION_MSG_NAVIGATION_ERROR = 0, + AUTOMATION_MSG_NAVIGATION_SUCCESS, + AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED, +}; + +// Two-pass include of render_messages_internal. Preprocessor magic allows +// us to use 1 header to define the enums and classes for our render messages. +#define IPC_MESSAGE_MACROS_ENUMS +#include "chrome/test/automation/automation_messages_internal.h" + +#ifdef IPC_MESSAGE_MACROS_LOG_ENABLED +# undef IPC_MESSAGE_MACROS_LOG +# define IPC_MESSAGE_MACROS_CLASSES +#include "chrome/test/automation/automation_messages_internal.h" + +# undef IPC_MESSAGE_MACROS_CLASSES +# define IPC_MESSAGE_MACROS_LOG +#include "chrome/test/automation/automation_messages_internal.h" +#else +// No debug strings requested, just define the classes +# define IPC_MESSAGE_MACROS_CLASSES +#include "chrome/test/automation/automation_messages_internal.h" +#endif + + +#endif // CHROME_TEST_AUTOMATION_AUTOMATION_MESSAGES_H__ diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h new file mode 100644 index 0000000..64ee503 --- /dev/null +++ b/chrome/test/automation/automation_messages_internal.h @@ -0,0 +1,723 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Defines the IPC messages used by the automation interface. + +// This header is meant to be included in multiple passes, hence no traditional +// header guard. +// See ipc_message_macros.h for explanation of the macros and passes. + +#include <string> +#include <vector> + +#include "chrome/common/ipc_message_macros.h" +#include "chrome/common/navigation_types.h" +#include "chrome/test/automation/autocomplete_edit_proxy.h" + +// NOTE: All IPC messages have either a routing_id of 0 (for asynchronous +// messages), or one that's been assigned by the proxy (for calls +// which expect a response). The routing_id shouldn't be used for +// any other purpose in these message types. + +// NOTE: All the new IPC messages should go at the end (before IPC_END_MESSAGES) +// The IPC message IDs are part of an enum and hence the value +// assumed to be constant across the builds may change. +// The messages AutomationMsg_WindowHWND* in particular should not change +// since the PageCyclerReferenceTest depend on the correctness of the +// the message IDs across the builds. + +// By using a start value of 0 for automation messages, we keep backward +// compatability with old builds. +IPC_BEGIN_MESSAGES(Automation, 0) + + // This message is fired when the AutomationProvider is up and running + // in the app (the app is not fully up at this point). + IPC_MESSAGE_ROUTED0(AutomationMsg_Hello) + + // This message is fired when the initial tab(s) are finished loading. + IPC_MESSAGE_ROUTED0(AutomationMsg_InitialLoadsComplete) + + // This message notifies the AutomationProvider to append a new tab the window + // with the given handle. The response contains the index of the new tab, or + // -1 if the request failed. + // The second parameter is the url to be loaded in the new tab. + IPC_MESSAGE_ROUTED2(AutomationMsg_AppendTabRequest, int, GURL) + IPC_MESSAGE_ROUTED1(AutomationMsg_AppendTabResponse, int) + + // This message requests the (zero-based) index for the currently + // active tab in the window with the given handle. The response contains + // the index of the active tab, or -1 if the request failed. + IPC_MESSAGE_ROUTED1(AutomationMsg_ActiveTabIndexRequest, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_ActiveTabIndexResponse, int) + + // This message notifies the AutomationProvider to active the tab. + // The first parameter is the handle to window resource. + // The second parameter is the (zero-based) index to be activated + IPC_MESSAGE_ROUTED2(AutomationMsg_ActivateTabRequest, int, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_ActivateTabResponse, int) + + // This message requests the cookie value for given url in the + // profile of the tab identified by the second parameter. The first + // parameter is the URL string. The response contains the length of the cookie + // value string. On failure, this length = -1. + IPC_MESSAGE_ROUTED2(AutomationMsg_GetCookiesRequest, GURL, int) + IPC_MESSAGE_ROUTED2(AutomationMsg_GetCookiesResponse, int, std::string) + + // This message notifies the AutomationProvider to set and broadcast a cookie + // with given name and value for the given url in the profile of the tab + // identified by the third parameter. The first parameter is the URL + // string, and the second parameter is the cookie name and value to be set. + // The response returns a non-negative value on success. + IPC_MESSAGE_ROUTED3(AutomationMsg_SetCookieRequest, GURL, std::string, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_SetCookieResponse, int) + + // This message notifies the AutomationProvider to navigate to a specified url + // in the tab with given handle. The first parameter is the handle to the tab + // resource. The second parameter is the target url. The response contains a + // status code which is nonnegative on success. + IPC_MESSAGE_ROUTED2(AutomationMsg_NavigateToURLRequest, int, GURL) + IPC_MESSAGE_ROUTED1(AutomationMsg_NavigateToURLResponse, + int) // see AutomationMsg_NavigationResponseValues + + // This message is used to implement the asynchronous version of + // NavigateToURL. + IPC_MESSAGE_ROUTED2(AutomationMsg_NavigationAsyncRequest, + int /* tab handle */, + GURL) + IPC_MESSAGE_ROUTED1(AutomationMsg_NavigationAsyncResponse, + bool /* error value */) + + // This message notifies the AutomationProvider to navigate back in session + // history in the tab with given handle. The first parameter is the handle + // to the tab resource. The response contains a status code which is + // nonnegative on success. + IPC_MESSAGE_ROUTED1(AutomationMsg_GoBackRequest, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_GoBackResponse, + int) // see AutomationMsg_NavigationResponseValues + + // This message notifies the AutomationProvider to navigate forward in session + // history in the tab with given handle. The first parameter is the handle + // to the tab resource. The response contains a status code which is + // nonnegative on success. + IPC_MESSAGE_ROUTED1(AutomationMsg_GoForwardRequest, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_GoForwardResponse, + int) // see AutomationMsg_NavigationResponseValues + + // This message requests the number of browser windows that the app currently + // has open. The parameter in the response is the number of windows. + IPC_MESSAGE_ROUTED0(AutomationMsg_BrowserWindowCountRequest) + IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserWindowCountResponse, int) + + // This message requests the handle (int64 app-unique identifier) of the + // window with the given (zero-based) index. On error, the returned handle + // value is 0. + IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserWindowRequest, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserWindowResponse, int) + + // This message requests the number of tabs in the window with the given + // handle. The response contains the number of tabs, or -1 if the request + // failed. + IPC_MESSAGE_ROUTED1(AutomationMsg_TabCountRequest, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_TabCountResponse, int) + + // This message requests the handle of the tab with the given (zero-based) + // index in the given app window. First parameter specifies the given window + // handle, second specifies the given tab_index. On error, the returned handle + // value is 0. + IPC_MESSAGE_ROUTED2(AutomationMsg_TabRequest, int, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_TabResponse, int) + + // This message requests the the title of the tab with the given handle. + // The response contains the size of the title string. On error, this value + // should be -1 and empty string. Note that the title can be empty in which + // case the size would be 0. + IPC_MESSAGE_ROUTED1(AutomationMsg_TabTitleRequest, int) + IPC_MESSAGE_ROUTED2(AutomationMsg_TabTitleResponse, int, std::wstring) + + // This message requests the the url of the tab with the given handle. + // The response contains a success flag and the URL string. The URL will + // be empty on failure, and it still may be empty on success. + IPC_MESSAGE_ROUTED1(AutomationMsg_TabURLRequest, + int /* tab handle */) + IPC_MESSAGE_ROUTED2(AutomationMsg_TabURLResponse, + bool /* success flag*/, + GURL) + + // This message requests the HWND of the top-level window that corresponds + // to the given automation handle. + // The response contains the HWND value, which is 0 if the call fails. + IPC_MESSAGE_ROUTED1(AutomationMsg_WindowHWNDRequest, + int /* automation handle */) + IPC_MESSAGE_ROUTED1(AutomationMsg_WindowHWNDResponse, + HWND /* Win32 handle */) + + // This message notifies the AutomationProxy that a handle that it has + // previously been given is now invalid. (For instance, if the handle + // represented a window which has now been closed.) The parameter + // value is the handle. + IPC_MESSAGE_ROUTED1(AutomationMsg_InvalidateHandle, int) + + // This message notifies the AutomationProvider that a handle is no + // longer being used, so it can stop paying attention to the + // associated resource. The parameter value is the handle. + IPC_MESSAGE_ROUTED1(AutomationMsg_HandleUnused, int) + + // This message requests the HWND of the tab that corresponds + // to the given automation handle. + // The response contains the HWND value, which is 0 if the call fails. + IPC_MESSAGE_ROUTED1(AutomationMsg_TabHWNDRequest, + int /* tab_handle */) + IPC_MESSAGE_ROUTED1(AutomationMsg_TabHWNDResponse, + HWND /* win32 Window Handle*/) + + // This message tells the AutomationProvider to provide the given + // authentication data to the specified tab, in response to an HTTP/FTP + // authentication challenge. + // The response status will be negative on error. + IPC_MESSAGE_ROUTED3(AutomationMsg_SetAuthRequest, + int, // tab handle + std::wstring, // username + std::wstring) // password + IPC_MESSAGE_ROUTED1(AutomationMsg_SetAuthResponse, + int) // status + + // This message tells the AutomationProvider to cancel the login in the + // specified tab. + // The response status will be negative on error. + IPC_MESSAGE_ROUTED1(AutomationMsg_CancelAuthRequest, + int) // tab handle + IPC_MESSAGE_ROUTED1(AutomationMsg_CancelAuthResponse, + int) // status + + // Requests that the automation provider ask history for the most recent + // chain of redirects coming from the given URL. The response must be + // decoded by the caller manually; it contains an integer indicating the + // number of URLs, followed by that many wstrings indicating a chain of + // redirects. On failure, the count will be negative. + IPC_MESSAGE_ROUTED2(AutomationMsg_RedirectsFromRequest, + int, // tab handle + GURL) // source URL + IPC_MESSAGE_EMPTY(AutomationMsg_RedirectsFromResponse) + + // This message asks the AutomationProvider whether a tab is waiting for + // login info. + IPC_MESSAGE_ROUTED1(AutomationMsg_NeedsAuthRequest, + int) // tab handle + IPC_MESSAGE_ROUTED1(AutomationMsg_NeedsAuthResponse, + bool) // status + + // This message requests the AutomationProvider to apply a certain + // accelerator. It is completely asynchronous with the resulting accelerator + // action. + IPC_MESSAGE_ROUTED2(AutomationMsg_ApplyAcceleratorRequest, + int, // window handle + int) // accelerator id like (IDC_BACK, IDC_FORWARD ...) + // The list can be found at + // chrome/app/chrome_dll_resource.h + + // This message requests that the AutomationProvider executes a JavaScript, + // which is sent embedded in a 'javascript:' URL. + // The javascript is executed in context of child frame whose xpath + // is passed as parameter (context_frame). The execution results in + // a serialized JSON string response. + IPC_MESSAGE_ROUTED3(AutomationMsg_DomOperationRequest, + int, // tab handle + std::wstring, // context_frame + std::wstring) // the javascript to be executed + + // This message is used to communicate the values received by the + // callback binding the JS to Cpp. This message forms the second leg in + // the communication channel. The values are originally received in the + // renderer which are then sent to the app (wrapped as json) using + // corresponding message in render_messages_internal.h + // This message simply relays the json string. + IPC_MESSAGE_ROUTED1(AutomationMsg_DomOperationResponse, + std::string) // the serialized json string containing + // the result of a javascript execution + + // Is the Download Shelf visible for the specified tab? + IPC_MESSAGE_ROUTED1(AutomationMsg_ShelfVisibilityRequest, + int /* tab_handle */) + IPC_MESSAGE_ROUTED1(AutomationMsg_ShelfVisibilityResponse, + bool /* is_visible */) + + // This message requests the number of constrained windows in the tab with + // the given handle. The response contains the number of constrained windows, + // or -1 if the request failed. + IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedWindowCountRequest, + int /* tab_handle */) + IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedWindowCountResponse, + int /* constrained_window_count */) + + // This message requests the handle of the constrained window with the given + // (zero-based) index in the given tab. First parameter specifies the given + // tab handle, second specifies the given child_index. On error, the returned + // handle value is 0. + IPC_MESSAGE_ROUTED2(AutomationMsg_ConstrainedWindowRequest, + int, /* window_handle */ + int) /* child_index */ + + IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedWindowResponse, + int) /* constrained_handle */ + + // This message requests the the title of the constrained window with the + // given handle. The response contains the size of the title string and title + // string. On error, this value should be -1 and empty string. Note that the + // title can be empty in which case the size would be 0. + IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedTitleRequest, int) + IPC_MESSAGE_ROUTED2(AutomationMsg_ConstrainedTitleResponse, int, std::wstring) + + // This message requests the bounds of the specified View element in + // window coordinates. + // Request: + // int - the handle of the window in which the view appears + // int - the ID of the view, as specified in chrome/browser/view_ids.h + // bool - whether the bounds should be returned in the screen coordinates + // (if true) or in the browser coordinates (if false). + // Response: + // bool - true if the view was found + // gfx::Rect - the bounds of the view, in window coordinates + IPC_MESSAGE_ROUTED3(AutomationMsg_WindowViewBoundsRequest, int, int, bool) + IPC_MESSAGE_ROUTED2(AutomationMsg_WindowViewBoundsResponse, bool, gfx::Rect) + + // This message requests that a drag be performed in window coordinate space + // Request: + // int - the handle of the window that's the context for this drag + // std::vector<POINT> - the path of the drag in window coordinate space; + // it should have at least 2 points (start and end) + // int - the flags which identify the mouse button(s) for the drag, as + // defined in chrome/views/event.h + // Response: + // bool - true if the drag could be performed + IPC_MESSAGE_ROUTED3(AutomationMsg_WindowDragRequest, + int, std::vector<POINT>, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_WindowDragResponse, bool) + + // Similar to AutomationMsg_InitialLoadsComplete, this indicates that the + // new tab ui has completed the initial load of its data. + // Time is how many milliseconds the load took. + IPC_MESSAGE_ROUTED1(AutomationMsg_InitialNewTabUILoadComplete, + int /* time */) + + // This message starts a find within a tab corresponding to the supplied + // tab handle. The response contains the number of matches found on the page + // within the tab specified. The parameter 'search_string' specifies what + // string to search for, 'forward' specifies whether to search in forward + // direction (1=forward, 0=back), 'match_case' specifies case sensitivity + // (1=case sensitive, 0=case insensitive). If an error occurs, matches_found + // will be -1. + IPC_MESSAGE_ROUTED4(AutomationMsg_FindInPageRequest, + int, /* tab_handle */ + std::wstring, /* find_request */ + int, /* forward */ + int /* match_case */) + IPC_MESSAGE_ROUTED1(AutomationMsg_FindInPageResponse, + int /* matches_found */) + + // This message sends a inspect element request for a given tab. The response + // contains the number of resources loaded by the inspector controller. + IPC_MESSAGE_ROUTED3(AutomationMsg_InspectElementRequest, + int, /* tab_handle */ + int, /* x */ + int /* y */) + IPC_MESSAGE_ROUTED1(AutomationMsg_InspectElementResponse, int) + + // This message requests the process ID of the tab that corresponds + // to the given automation handle. + // The response has an integer corresponding to the PID of the tab's + // renderer, 0 if the tab currently has no renderer process, or -1 on error. + IPC_MESSAGE_ROUTED1(AutomationMsg_TabProcessIDRequest, + int /* tab_handle */) + IPC_MESSAGE_ROUTED1(AutomationMsg_TabProcessIDResponse, + int /* process ID */) + + // This tells the browser to enable or disable the filtered network layer. + IPC_MESSAGE_ROUTED1(AutomationMsg_SetFilteredInet, + bool /* enabled */) + + // Gets the directory that downloads will occur in for the active profile. + IPC_MESSAGE_ROUTED1(AutomationMsg_DownloadDirectoryRequest, + int /* tab_handle */) + IPC_MESSAGE_ROUTED1(AutomationMsg_DownloadDirectoryResponse, + std::wstring /* directory */) + + // This message requests the id of the view that has the focus in the + // specified window. If no view is focused, -1 is returned. Note that the + // window should either be a ViewWindow or a Browser. + IPC_MESSAGE_ROUTED1(AutomationMsg_GetFocusedViewIDRequest, + int /* view_handle */) + IPC_MESSAGE_ROUTED1(AutomationMsg_GetFocusedViewIDResponse, + int /* focused_view_id */) + + // This message shows/hides the window. + IPC_MESSAGE_ROUTED2(AutomationMsg_SetWindowVisibleRequest, + int /* view_handle */, bool /* visible */) + IPC_MESSAGE_ROUTED1(AutomationMsg_SetWindowVisibleResponse, + bool /* success */) + + // Gets the active status of a window. + IPC_MESSAGE_ROUTED1(AutomationMsg_IsWindowActiveRequest, + int /* view_handle */) + IPC_MESSAGE_ROUTED2(AutomationMsg_IsWindowActiveResponse, + bool /* success */, bool /* active */) + + // Makes the specified window the active window. + IPC_MESSAGE_ROUTED1(AutomationMsg_ActivateWindow, int /* view_handle */) + + // Opens a new browser window. + IPC_MESSAGE_ROUTED1(AutomationMsg_OpenNewBrowserWindow, + int /* show_command*/ ) + + // This message requests the handle (int64 app-unique identifier) of the + // current active top window. On error, the returned handle value is 0. + IPC_MESSAGE_ROUTED0(AutomationMsg_ActiveWindowRequest) + IPC_MESSAGE_ROUTED1(AutomationMsg_ActiveWindowResponse, int) + + // This message requests the browser associated with the specified window + // handle. + // The response contains a success flag and the handle of the browser. + IPC_MESSAGE_ROUTED1(AutomationMsg_BrowserForWindowRequest, + int /* window handle */) + IPC_MESSAGE_ROUTED2(AutomationMsg_BrowserForWindowResponse, + bool /* success flag */, + int /* browser handle */) + + // This message requests the window associated with the specified browser + // handle. + // The response contains a success flag and the handle of the window. + IPC_MESSAGE_ROUTED1(AutomationMsg_WindowForBrowserRequest, + int /* browser handle */) + IPC_MESSAGE_ROUTED2(AutomationMsg_WindowForBrowserResponse, + bool /* success flag */, + int /* window handle */) + + // This message requests the AutocompleteEdit associated with the specified + // browser handle. + // The response contains a success flag and the handle of the omnibox. + IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditForBrowserRequest, + int /* browser handle */) + IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditForBrowserResponse, + bool /* success flag */, + int /* AutocompleteEdit handle */) + + // This message requests that a mouse click be performed in window coordinate + // space. + // Request: + // int - the handle of the window that's the context for this click + // POINT - the point to click + // int - the flags which identify the mouse button(s) for the click, as + // defined in chrome/views/event.h + IPC_MESSAGE_ROUTED3(AutomationMsg_WindowClickRequest, int, POINT, int) + + // This message requests that a key press be performed. + // Request: + // int - the handle of the window that's the context for this click + // wchar_t - char of the key that was pressed. + // int - the flags which identify the modifiers (shift, ctrl, alt) + // associated for, as defined in chrome/views/event.h + IPC_MESSAGE_ROUTED3(AutomationMsg_WindowKeyPressRequest, int, wchar_t, int) + + // This message notifies the AutomationProvider to create a tab which is + // hosted by an external process. The response contains the HWND of the + // window that contains the external tab and the handle to the newly + // created tab + // The second parameter is the url to be loaded in the new tab. + IPC_MESSAGE_ROUTED0(AutomationMsg_CreateExternalTab) + IPC_MESSAGE_ROUTED2(AutomationMsg_CreateExternalTabResponse, HWND, int) + + // This message notifies the AutomationProvider to navigate to a specified + // url in the external tab with given handle. The first parameter is the + // handle to the tab resource. The second parameter is the target url. + // The response contains a status code which is nonnegative on success. + IPC_MESSAGE_ROUTED2(AutomationMsg_NavigateInExternalTabRequest, int, GURL) + IPC_MESSAGE_ROUTED1(AutomationMsg_NavigateInExternalTabResponse, + int) // see AutomationMsg_NavigationResponseValues + + // This message is an outgoing message from Chrome to an external host. + // It is a notification that the NavigationState was changed + // Request: + // -int: The flags specifying what changed + // (see TabContents::InvalidateTypes) + // Response: + // None expected + IPC_MESSAGE_ROUTED1(AutomationMsg_NavigationStateChanged, int) + + // This message is an outgoing message from Chrome to an external host. + // It is a notification that the target URL has changed (the target URL + // is the URL of the link that the user is hovering on) + // Request: + // -std::wstring: The new target URL + // Response: + // None expected + IPC_MESSAGE_ROUTED1(AutomationMsg_UpdateTargetUrl, std::wstring) + + // This message notifies the AutomationProvider to show the specified html + // text in an interstitial page in the tab with given handle. The first + // parameter is the handle to the tab resource. The second parameter is the + // html text to be displayed. + // The response contains a success flag. + IPC_MESSAGE_ROUTED2(AutomationMsg_ShowInterstitialPageRequest, + int, + std::string) + IPC_MESSAGE_ROUTED1(AutomationMsg_ShowInterstitialPageResponse, bool) + + // This message notifies the AutomationProvider to hide the current + // interstitial page in the tab with given handle. The parameter is the handle + // to the tab resource. + // The response contains a success flag. + IPC_MESSAGE_ROUTED1(AutomationMsg_HideInterstitialPageRequest, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_HideInterstitialPageResponse, bool) + + // This message requests that a tab be closed. + // Request: + // - int: handle of the tab to close + // - bool: if true the proxy blocks until the tab has completely closed, + // otherwise the proxy only blocks until it initiates the close. + IPC_MESSAGE_ROUTED2(AutomationMsg_CloseTabRequest, int, bool) + IPC_MESSAGE_ROUTED1(AutomationMsg_CloseTabResponse, bool) + + // This message requests that the browser be closed. + // Request: + // - int: handle of the browser which contains the tab + // Response: + // - bool: whether the operation was successfull. + // - bool: whether the browser process will be terminated as a result (if + // this was the last closed browser window). + IPC_MESSAGE_ROUTED1(AutomationMsg_CloseBrowserRequest, int) + IPC_MESSAGE_ROUTED2(AutomationMsg_CloseBrowserResponse, bool, bool) + + // This message sets the keyboard accelarators to be used by an externally + // hosted tab. This call is not valid on a regular tab hosted within + // Chrome. + // Request: + // - int: handle of the tab + // - HACCEL: The accelerator table to be set + // - int: The number of entries in the accelerator table + // Response: + // -bool: whether the operation was successful. + IPC_MESSAGE_ROUTED3(AutomationMsg_SetAcceleratorsForTab, int, HACCEL, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_SetAcceleratorsForTabResponse, bool) + + // This message is an outgoing message from Chrome to an external host. + // It is a request to process a keyboard accelerator. + // Request: + // -MSG: The keyboard message + // Response: + // None expected + // TODO(sanjeevr): Ideally we need to add a response from the external + // host saying whether it processed the accelerator + IPC_MESSAGE_ROUTED1(AutomationMsg_HandleAccelerator, MSG) + + // This message is an outgoing message from Chrome to an external host. + // It is a request to open a url + // Request: + // -GURL: The URL to open + // -int: The WindowOpenDisposition that specifies where the URL should + // be opened (new tab, new window etc). + // Response: + // None expected + IPC_MESSAGE_ROUTED2(AutomationMsg_OpenURL, GURL, int) + + // This message is sent by the container of an externally hosted tab to + // reflect any accelerator keys that it did not process. This gives the + // tab a chance to handle the keys + // Request: + // - int: handle of the tab + // -MSG: The keyboard message that the container did not handle + // Response: + // None expected + IPC_MESSAGE_ROUTED2(AutomationMsg_ProcessUnhandledAccelerator, int, MSG) + + // This message requests the provider to wait until the specified tab has + // finished restoring after session restore. + // Request: + // - int: handle of the tab + // Response: + // - bool: whether the operation was successful. + IPC_MESSAGE_ROUTED1(AutomationMsg_WaitForTabToBeRestored, int) + + // Sent in response to AutomationMsg_WaitForTabToBeRestored once the tab has + // finished loading. + IPC_MESSAGE_ROUTED0(AutomationMsg_TabFinishedRestoring) + + // This message is an outgoing message from Chrome to an external host. + // It is a notification that a navigation happened + // Request: + // -int : Indicates the type of navigation (see the NavigationType enum) + // -int: If this was not a new navigation, then this value indicates the + // relative offset of the navigation. A positive offset means a + // forward navigation, a negative value means a backward navigation + // and 0 means this was a redirect + // Response: + // None expected + IPC_MESSAGE_ROUTED2(AutomationMsg_DidNavigate, int, int) + + // This message requests the different security states of the page displayed + // in the specified tab. + // Request: + // - int: handle of the tab + // Response: + // - bool: whether the operation was successful. + // - int: the security style of the tab (enum SecurityStyle see + // security_style.h)). + // - int: the status of the server's ssl cert (0 means no errors or no ssl + // was used). + // - int: the mixed content state, 0 means no mixed/unsafe contents. + IPC_MESSAGE_ROUTED1(AutomationMsg_GetSecurityState, int) + IPC_MESSAGE_ROUTED4(AutomationMsg_GetSecurityStateResponse, + bool, + int, + int, + int) + + // This message requests the page type of the page displayed in the specified + // tab (normal, error or interstitial). + // Request: + // - int: handle of the tab + // Response: + // - bool: whether the operation was successful. + // - int: the type of the page currently displayed (enum PageType see + // entry_navigation.h). + IPC_MESSAGE_ROUTED1(AutomationMsg_GetPageType, int) + IPC_MESSAGE_ROUTED2(AutomationMsg_GetPageTypeResponse, bool, int) + + // This message simulates the user action on the SSL blocking page showing in + // the specified tab. This message is only effective if an interstitial page + // is showing in the tab. + // Request: + // - int: handle of the tab + // - bool: whether to proceed or abort the navigation + // Response: + // - bool: whether the operation was successful. + IPC_MESSAGE_ROUTED2(AutomationMsg_ActionOnSSLBlockingPage, int, bool) + IPC_MESSAGE_ROUTED1(AutomationMsg_ActionOnSSLBlockingPageResponse, bool) + + // Message to request that a browser window is brought to the front and activated. + // Request: + // - int: handle of the browser window. + // Response: + // - bool: True if the browser is brought to the front. + IPC_MESSAGE_ROUTED1(AutomationMsg_BringBrowserToFront, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_BringBrowserToFrontResponse, bool) + + // Message to request whether a certain item is enabled of disabled in the "Page" + // menu in the browser window + // + // Request: + // - int: handle of the browser window. + // - int: IDC message identifier to query if enabled + // Response: + // - bool: True if the command is enabled on the Page menu + IPC_MESSAGE_ROUTED2(AutomationMsg_IsPageMenuCommandEnabled, int, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_IsPageMenuCommandEnabledResponse, bool) + + // This message notifies the AutomationProvider to print the tab with given + // handle. The first parameter is the handle to the tab resource. The + // response contains a bool which is true on success. + IPC_MESSAGE_ROUTED1(AutomationMsg_PrintNowRequest, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_PrintNowResponse, bool) + + // This message notifies the AutomationProvider to reload the current page in + // the tab with given handle. The first parameter is the handle to the tab + // resource. The response contains a status code which is nonnegative on + // success. + IPC_MESSAGE_ROUTED1(AutomationMsg_ReloadRequest, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_ReloadResponse, + int) // see AutomationMsg_NavigationResponseValues + + // This message requests the handle (int64 app-unique identifier) of the + // last active browser window, or the browser at index 0 if there is no last + // active browser, or it no longer exists. Returns 0 if no browser windows + // exist. + IPC_MESSAGE_ROUTED0(AutomationMsg_LastActiveBrowserWindowRequest) + IPC_MESSAGE_ROUTED1(AutomationMsg_LastActiveBrowserWindowResponse, int) + + // This message requests the bounds of a constrained window (relative to its + // containing TabContents). On an internal error, the boolean in the result will + // be set to false. + IPC_MESSAGE_ROUTED1(AutomationMsg_ConstrainedWindowBoundsRequest, + int /* tab_handle */) + IPC_MESSAGE_ROUTED2(AutomationMsg_ConstrainedWindowBoundsResponse, + bool /* the requested window exists */, + gfx::Rect /* constrained_window_count */) + + // This message notifies the AutomationProvider to save the page with given + // handle. The first parameter is the handle to the tab resource. The second + // parameter is the main HTML file name. The third parameter is the directory + // for saving resources. The fourth parameter is the saving type: 0 for HTML + // only; 1 for complete web page. + // The response contains a bool which is true on success. + IPC_MESSAGE_ROUTED4(AutomationMsg_SavePageRequest, int, std::wstring, + std::wstring, int) + IPC_MESSAGE_ROUTED1(AutomationMsg_SavePageResponse, bool) + + + // This message requests the text currently being displayed in the + // AutocompleteEdit. The parameter is the handle to the AutocompleteEdit. + // The response is a string indicating the text in the AutocompleteEdit. + IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditGetTextRequest, + int /* autocomplete edit handle */) + IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditGetTextResponse, + bool /* the requested autocomplete edit exists */, + std::wstring /* omnibox text */) + + // This message sets the text being displayed in the AutocompleteEdit. The + // first parameter is the handle to the omnibox and the second parameter is + // the text to be displayed in the AutocompleteEdit. + // The response has no parameters and is returned when the operation has + // completed. + IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditSetTextRequest, + int /* autocomplete edit handle */, + std::wstring /* text to set */) + IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditSetTextResponse, + bool /* the requested autocomplete edit exists */) + + // This message requests if a query to a autocomplete provider is still in + // progress. The first parameter in the request is the handle to the + // autocomplete edit. + // The first parameter in the response indicates if the request succeeded. + // The second parameter in indicates if a query is still in progress. + IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditIsQueryInProgressRequest, + int /* autocomplete edit handle*/) + IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditIsQueryInProgressResponse, + bool /* the requested autocomplete edit exists */, + bool /* indicates if a query is in progress */) + + // This message requests a list of the autocomplete messages currently being + // displayed by the popup. The parameter in the request is a handle to the + // autocomplete edit. + // The first parameter in the response indicates if the request was + // successful while the second parameter is the actual list of matches. + IPC_MESSAGE_ROUTED1(AutomationMsg_AutocompleteEditGetMatchesRequest, + int /* autocomplete edit handle*/) + IPC_MESSAGE_ROUTED2(AutomationMsg_AutocompleteEditGetMatchesResponse, + bool /* the requested autocomplete edit exists */, + std::vector<AutocompleteMatchData> /* matches */) + +IPC_END_MESSAGES(Automation) diff --git a/chrome/test/automation/automation_proxy.cc b/chrome/test/automation/automation_proxy.cc new file mode 100644 index 0000000..07e5387 --- /dev/null +++ b/chrome/test/automation/automation_proxy.cc @@ -0,0 +1,567 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <sstream> + +#include "chrome/test/automation/automation_proxy.h" + +#include "base/logging.h" +#include "base/ref_counted.h" +#include "chrome/common/ipc_message_macros.h" +#include "chrome/test/automation/autocomplete_edit_proxy.h" +#include "chrome/test/automation/automation_constants.h" +#include "chrome/test/automation/automation_messages.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" + +// This class exists to group together the data and functionality used for +// synchronous automation requests. +class AutomationRequest : + public base::RefCountedThreadSafe<AutomationRequest> { +public: + AutomationRequest() { + static int32 routing_id = 0; + routing_id_ = ++routing_id; + received_response_ = ::CreateEvent(NULL, TRUE, FALSE, NULL); + DCHECK(received_response_); + } + ~AutomationRequest() { + DCHECK(received_response_); + ::CloseHandle(received_response_); + } + + // This is called on the foreground thread to block while waiting for a + // response from the app. + // The function returns true if response is received, and returns false + // if there is a failure or timeout. + bool WaitForResponse(uint32 timeout_ms, bool* is_timeout) { + uint32 result = ::WaitForSingleObject(received_response_, timeout_ms); + if (is_timeout) + *is_timeout = (result == WAIT_TIMEOUT); + + return result != WAIT_FAILED && result != WAIT_TIMEOUT; + } + + // This is called on the background thread once the response has been + // received and the foreground thread can resume execution. + bool SignalResponseReady(const IPC::Message& response) { + response_.reset(new IPC::Message(response)); + + DCHECK(received_response_); + return !!::SetEvent(received_response_); + } + + // This can be used to take ownership of the response object that + // we've received, reducing the need to copy the message. + void GrabResponse(IPC::Message** response) { + DCHECK(response); + *response = response_.get(); + response_.release(); + } + + int32 routing_id() { return routing_id_; } + + const IPC::Message& response() { + DCHECK(response_.get()); + return *(response_.get()); + } + +private: + DISALLOW_EVIL_CONSTRUCTORS(AutomationRequest); + + int32 routing_id_; + scoped_ptr<IPC::Message> response_; + HANDLE received_response_; +}; + +namespace { + +// This object allows messages received on the background thread to be +// properly triaged. +class AutomationMessageFilter : public IPC::ChannelProxy::MessageFilter { + public: + AutomationMessageFilter(AutomationProxy* server) : server_(server) {} + + // Return true to indicate that the message was handled, or false to let + // the message be handled in the default way. + virtual bool OnMessageReceived(const IPC::Message& message) { + { + // Here we're checking to see if it matches the (because there should + // be at most one) synchronous request. If the received message is + // the response to the synchronous request, we clear the server's + // "current_request" pointer and signal to the request object that + // the response is ready for processing. We're clearing current_request + // here rather than on the foreground thread so that we can assert + // that both threads perceive it as cleared at the time that the + // foreground thread wakes up. + scoped_refptr<AutomationRequest> request = server_->current_request(); + if (request.get() && (message.routing_id() == request->routing_id())) { + server_->clear_current_request(); + request->SignalResponseReady(message); + return true; + } + if (message.routing_id() > 0) { + // The message is either the previous async response or arrived + // after timeout. + return true; + } + } + + bool handled = true; + + IPC_BEGIN_MESSAGE_MAP(AutomationMessageFilter, message) + IPC_MESSAGE_HANDLER_GENERIC( + AutomationMsg_Hello, server_->SignalAppLaunch()); + IPC_MESSAGE_HANDLER_GENERIC( + AutomationMsg_InitialLoadsComplete, server_->SignalInitialLoads()); + IPC_MESSAGE_HANDLER(AutomationMsg_InitialNewTabUILoadComplete, + NewTabLoaded); + IPC_MESSAGE_HANDLER_GENERIC( + AutomationMsg_InvalidateHandle, server_->InvalidateHandle(message)); + IPC_MESSAGE_UNHANDLED(handled = false); + IPC_END_MESSAGE_MAP() + + return handled; + } + + void NewTabLoaded(int load_time) { + server_->SignalNewTabUITab(load_time); + } + + private: + AutomationProxy* server_; +}; + +} // anonymous namespace + + +const int AutomationProxy::kMaxCommandExecutionTime = 30000; + +AutomationProxy::AutomationProxy() : current_request_(NULL) { + InitializeEvents(); + InitializeChannelID(); + InitializeThread(); + InitializeChannel(); + InitializeHandleTracker(); +} + +AutomationProxy::~AutomationProxy() { +} + +void AutomationProxy::InitializeEvents() { + app_launched_ = + CreateEvent(NULL, // Handle cannot be inherited by child processes. + TRUE, // No automatic reset after a waiting thread released. + FALSE, // Initially not signalled. + NULL); // No name. + DCHECK(app_launched_); + + // See the above call to CreateEvent to understand these parameters. + initial_loads_complete_ = CreateEvent(NULL, TRUE, FALSE, NULL); + DCHECK(initial_loads_complete_); + + // See the above call to CreateEvent to understand these parameters. + new_tab_ui_load_complete_ = CreateEvent(NULL, TRUE, FALSE, NULL); + DCHECK(new_tab_ui_load_complete_); +} + +void AutomationProxy::InitializeChannelID() { + // The channel counter keeps us out of trouble if we create and destroy + // several AutomationProxies sequentially over the course of a test run. + // (Creating the channel sometimes failed before when running a lot of + // tests in sequence, and our theory is that sometimes the channel ID + // wasn't getting freed up in time for the next test.) + static int channel_counter = 0; + + std::wostringstream buf; + buf << L"ChromeTestingInterface:" << GetCurrentProcessId() << + L"." << ++channel_counter; + channel_id_ = buf.str(); +} + +void AutomationProxy::InitializeThread() { + scoped_ptr<Thread> thread(new Thread("AutomationProxy_BackgroundThread")); + bool thread_result = thread->Start(); + DCHECK(thread_result); + thread_.swap(thread); +} + +void AutomationProxy::InitializeChannel() { + channel_.reset(new IPC::ChannelProxy( + channel_id_, + IPC::Channel::MODE_SERVER, + this, // we are the listener + new AutomationMessageFilter(this), + thread_->message_loop())); +} + +void AutomationProxy::InitializeHandleTracker() { + tracker_.reset(new AutomationHandleTracker(this)); +} + +bool AutomationProxy::WaitForAppLaunch() { + return ::WaitForSingleObject(app_launched_, + kMaxCommandExecutionTime) == WAIT_OBJECT_0; +} + +void AutomationProxy::SignalAppLaunch() { + ::SetEvent(app_launched_); +} + +bool AutomationProxy::WaitForInitialLoads() { + return ::WaitForSingleObject(initial_loads_complete_, + kMaxCommandExecutionTime) == WAIT_OBJECT_0; +} + +bool AutomationProxy::WaitForInitialNewTabUILoad(int* load_time) { + if (::WaitForSingleObject(new_tab_ui_load_complete_, + kMaxCommandExecutionTime) == WAIT_OBJECT_0) { + *load_time = new_tab_ui_load_time_; + ::ResetEvent(new_tab_ui_load_complete_); + return true; + } + return false; +} + +void AutomationProxy::SignalInitialLoads() { + ::SetEvent(initial_loads_complete_); +} + +void AutomationProxy::SignalNewTabUITab(int load_time) { + new_tab_ui_load_time_ = load_time; + ::SetEvent(new_tab_ui_load_complete_); +} + +bool AutomationProxy::GetBrowserWindowCount(int* num_windows) { + if (!num_windows) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool is_timeout = true; + bool succeeded = SendAndWaitForResponseWithTimeout( + new AutomationMsg_BrowserWindowCountRequest(0), &response, + AutomationMsg_BrowserWindowCountResponse::ID, + kMaxCommandExecutionTime, &is_timeout); + if (!succeeded) + return false; + + if (is_timeout) { + DLOG(ERROR) << "GetWindowCount did not complete in a timely fashion"; + return false; + } + + void* iter = NULL; + if (!response->ReadInt(&iter, num_windows)) { + succeeded = false; + } + + delete response; + return succeeded; +} + +bool AutomationProxy::WaitForWindowCountToChange(int count, int* new_count, + int wait_timeout) { + const TimeTicks start = TimeTicks::Now(); + const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout); + while (TimeTicks::Now() - start < timeout) { + bool succeeded = GetBrowserWindowCount(new_count); + if (!succeeded) return false; + if (count != *new_count) return true; + Sleep(automation::kSleepTime); + } + // Window count never changed. + return false; +} + +bool AutomationProxy::WaitForWindowCountToBecome(int count, + int wait_timeout) { + const TimeTicks start = TimeTicks::Now(); + const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout); + while (TimeTicks::Now() - start < timeout) { + int new_count; + bool succeeded = GetBrowserWindowCount(&new_count); + if (!succeeded) { + // Try again next round, but log it. + DLOG(ERROR) << "GetBrowserWindowCount returned false"; + } else if (count == new_count) { + return true; + } + Sleep(automation::kSleepTime); + } + // Window count never reached the value we sought. + return false; +} + +bool AutomationProxy::SetFilteredInet(bool enabled) { + return Send(new AutomationMsg_SetFilteredInet(0, enabled)); +} + +void AutomationProxy::OnMessageReceived(const IPC::Message& msg) { + // This won't get called unless AutomationProxy is run from + // inside a message loop. + NOTREACHED(); +} + +void AutomationProxy::OnChannelError() { + DLOG(ERROR) << "Channel error in AutomationProxy."; +} + +WindowProxy* AutomationProxy::GetActiveWindow() { + IPC::Message* response = NULL; + bool is_timeout = true; + bool succeeded = SendAndWaitForResponseWithTimeout( + new AutomationMsg_ActiveWindowRequest(0), &response, + AutomationMsg_ActiveWindowResponse::ID, + kMaxCommandExecutionTime, &is_timeout); + if (!succeeded) + return NULL; + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit. + if (is_timeout) { + DLOG(ERROR) << "GetActiveWindow did not complete in a timely fashion"; + return NULL; + } + + void* iter = NULL; + int handle; + if (response->ReadInt(&iter, &handle) && (handle != 0)) + return new WindowProxy(this, tracker_.get(), handle); + + return NULL; +} + + +BrowserProxy* AutomationProxy::GetBrowserWindow(int window_index) { + IPC::Message* response; + bool is_timeout = true; + bool succeeded = SendAndWaitForResponseWithTimeout( + new AutomationMsg_BrowserWindowRequest(0, window_index), &response, + AutomationMsg_BrowserWindowResponse::ID, + kMaxCommandExecutionTime, &is_timeout); + if (!succeeded) + return NULL; + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit. + if (is_timeout) { + DLOG(ERROR) << "GetBrowserWindow did not complete in a timely fashion"; + return NULL; + } + + void* iter = NULL; + int handle; + if (!response->ReadInt(&iter, &handle) || (handle == 0)) { + DLOG(ERROR) << "Bad response from the window getter."; + return NULL; + } + return new BrowserProxy(this, tracker_.get(), handle); +} + +BrowserProxy* AutomationProxy::GetLastActiveBrowserWindow() { + IPC::Message* response; + bool is_timeout = true; + bool succeeded = SendAndWaitForResponseWithTimeout( + new AutomationMsg_LastActiveBrowserWindowRequest(0), + &response, AutomationMsg_LastActiveBrowserWindowResponse::ID, + kMaxCommandExecutionTime, &is_timeout); + if (!succeeded) + return NULL; + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit. + if (is_timeout) { + DLOG(ERROR) << "GetLastActiveBrowserWindow did not complete in a timely fashion"; + return NULL; + } + + void* iter = NULL; + int handle; + if (!response->ReadInt(&iter, &handle) || (handle == 0)) { + DLOG(ERROR) << "Bad response from the window getter."; + return NULL; + } + return new BrowserProxy(this, tracker_.get(), handle); +} + +BrowserProxy* AutomationProxy::GetBrowserForWindow(WindowProxy* window) { + return GetBrowserForWindowWithTimeout(window, INFINITE, NULL); +} + +BrowserProxy* AutomationProxy::GetBrowserForWindowWithTimeout( + WindowProxy* window, uint32 timeout_ms, bool* is_timeout) { + DCHECK(window); + if (!window->is_valid() || !window->handle()) + return false; + + IPC::Message* response = NULL; + bool succeeded = SendAndWaitForResponseWithTimeout( + new AutomationMsg_BrowserForWindowRequest(0, window->handle()), &response, + AutomationMsg_BrowserForWindowResponse::ID, timeout_ms, is_timeout); + if (!succeeded) + return NULL; + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit. + int browser_handle = 0; + void* iter = NULL; + bool handle_ok; + succeeded = response->ReadBool(&iter, &handle_ok); + if (succeeded) + succeeded = response->ReadInt(&iter, &browser_handle); + + if (succeeded) { + return new BrowserProxy(this, tracker_.get(), browser_handle); + } else { + return NULL; + } +} + +WindowProxy* AutomationProxy::GetWindowForBrowser(BrowserProxy* browser) { + if (!browser->is_valid() || !browser->handle()) + return false; + + IPC::Message* response = NULL; + bool succeeded = SendAndWaitForResponse( + new AutomationMsg_WindowForBrowserRequest(0, browser->handle()), &response, + AutomationMsg_WindowForBrowserResponse::ID); + if (!succeeded) + return NULL; + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit. + int window_handle; + void* iter = NULL; + bool handle_ok; + succeeded = response->ReadBool(&iter, &handle_ok); + if (succeeded) + succeeded = response->ReadInt(&iter, &window_handle); + + if (succeeded) { + return new WindowProxy(this, tracker_.get(), window_handle); + } else { + return NULL; + } +} + +AutocompleteEditProxy* AutomationProxy::GetAutocompleteEditForBrowser( + BrowserProxy* browser) { + if (!browser->is_valid() || !browser->handle()) + return NULL; + + IPC::Message* response = NULL; + if (!SendAndWaitForResponse( + new AutomationMsg_AutocompleteEditForBrowserRequest(0, browser->handle()), + &response, AutomationMsg_AutocompleteEditForBrowserResponse::ID)) + return NULL; + scoped_ptr<IPC::Message> response_deleter(response); + + int autocomplete_edit_handle; + void* iter = NULL; + bool handle_ok; + if (!response->ReadBool(&iter, &handle_ok) || + !response->ReadInt(&iter, &autocomplete_edit_handle)) + return NULL; + + return new AutocompleteEditProxy(this, tracker_.get(), + autocomplete_edit_handle); +} + +bool AutomationProxy::SendAndWaitForResponse(IPC::Message* request, + IPC::Message** response, + int response_type) { + return SendAndWaitForResponseWithTimeout(request, response, response_type, + INFINITE, NULL); +} + +bool AutomationProxy::SendAndWaitForResponseWithTimeout( + IPC::Message* request, + IPC::Message** response, + int response_type, + uint32 timeout_ms, + bool* is_timeout) { + + DCHECK(request); + DCHECK(response); + DCHECK(!current_request_) << + "Only one synchronous request should exist at any given time."; + + scoped_refptr<AutomationRequest> req = new AutomationRequest; + current_request_ = req; + + // Rewrite the message's routing ID so that we'll recognize the response + // to it when it comes back. + request->set_routing_id(req->routing_id()); + bool result = Send(request) && req->WaitForResponse(timeout_ms, is_timeout); + if (!result || req->response().type() != response_type) { + // If Send() or WaitForResponse() failed, current_request_ may not have + // gotten cleared by the background thread, so we'll clear it here. + current_request_ = NULL; + return false; + } + req->GrabResponse(response); + + return true; +} + +void AutomationProxy::InvalidateHandle(const IPC::Message& message) { + void* iter = NULL; + int handle; + + if (message.ReadInt(&iter, &handle)) { + tracker_->InvalidateHandle(handle); + } +} + +bool AutomationProxy::OpenNewBrowserWindow(int show_command) { + return Send(new AutomationMsg_OpenNewBrowserWindow(0, show_command)); +} + +TabProxy* AutomationProxy::CreateExternalTab(HWND* external_tab_container) { + IPC::Message* response = NULL; + bool succeeded = SendAndWaitForResponse( + new AutomationMsg_CreateExternalTab(0), &response, + AutomationMsg_CreateExternalTabResponse::ID); + if (!succeeded) { + return NULL; + } + void* iter = NULL; + int handle = 0; + TabProxy* tab_proxy = NULL; + if (IPC::ReadParam(response, &iter, external_tab_container) && + IsWindow(*external_tab_container)) { + if (response->ReadInt(&iter, &handle) && + (handle >= 0)) { + succeeded = true; + tab_proxy = new TabProxy(this, tracker_.get(), handle); + } + } else { + succeeded = false; + } + delete response; + return tab_proxy; +} diff --git a/chrome/test/automation/automation_proxy.h b/chrome/test/automation/automation_proxy.h new file mode 100644 index 0000000..e8d63b5 --- /dev/null +++ b/chrome/test/automation/automation_proxy.h @@ -0,0 +1,240 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATION_AUTOMATION_PROXY_H__ +#define CHROME_TEST_AUTOMATION_AUTOMATION_PROXY_H__ + +#include <string> + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "base/thread.h" +#include "chrome/common/ipc_channel_proxy.h" +#include "chrome/common/ipc_message.h" +#include "chrome/test/automation/automation_handle_tracker.h" +#include "chrome/test/automation/automation_messages.h" + +class AutomationRequest; +class BrowserProxy; +class WindowProxy; +class TabProxy; +class AutocompleteEditProxy; + +// This is an interface that AutomationProxy-related objects can use to +// access the message-sending abilities of the Proxy. +class AutomationMessageSender : public IPC::Message::Sender { + public: + // Sends a message synchronously (from the perspective of the caller's + // thread, at least); it doesn't return until a response has been received. + // This method takes ownership of the request object passed in. The caller + // is responsible for deleting the response object when they're done with it. + // response_type should be set to the message type of the expected response. + // A response object will only be available if the method returns true. + // NOTE: This method will overwrite any routing_id on the request message, + // since it uses this field to match the response up with the request. + virtual bool SendAndWaitForResponse(IPC::Message* request, + IPC::Message** response, + int response_type) = 0; + + // Sends a message synchronously; it doesn't return until a response has been + // received or a timeout has expired. + // The function returns true if a response is received, and returns false if + // there is a failure or timeout (in milliseconds). If return after timeout, + // is_timeout is set to true. + // See the comments in SendAndWaitForResponse for other details on usage. + // NOTE: When timeout occurs, the connection between proxy provider may be + // in transit state. Specifically, there might be pending IPC messages, + // and the proxy provider might be still working on the previous + // request. + virtual bool SendAndWaitForResponseWithTimeout(IPC::Message* request, + IPC::Message** response, + int response_type, + uint32 timeout_ms, + bool* is_timeout) = 0; +}; + +// This is the interface that external processes can use to interact with +// a running instance of the app. +class AutomationProxy : public IPC::Channel::Listener, + public AutomationMessageSender { + public: + AutomationProxy(); + virtual ~AutomationProxy(); + + // IPC callback + virtual void OnMessageReceived(const IPC::Message& msg); + virtual void OnChannelError(); + + // Waits for the app to launch and the automation provider to say hello + // (the app isn't fully done loading by this point). + // Returns true if the launch is successful + bool WaitForAppLaunch(); + + // Waits for any initial page loads to complete. + // NOTE: this only fires once for a run of the application. + // Returns true if the load is successful + bool WaitForInitialLoads(); + + // Waits for the initial destinations tab to report that it has finished + // querying. |load_time| is filled in with how long it took, in milliseconds. + // NOTE: this only fires once for a run of the application. + // Returns true if the load is successful. + bool WaitForInitialNewTabUILoad(int* load_time); + + // Open a new browser window, returning true on success. |show_command| + // identifies how the window should be shown. + // False likely indicates an IPC error. + bool OpenNewBrowserWindow(int show_command); + + // Fills the number of open browser windows into the given variable, returning + // true on success. False likely indicates an IPC error. + bool GetBrowserWindowCount(int* num_windows); + + // Block the thread until the window count changes. + // First parameter is the original window count. + // The second parameter is updated with the number of window tabs. + // The third parameter specifies the timeout length for the wait loop. + // Returns false if the window count does not change before time out. + // TODO(evanm): this function has a confusing name and semantics; it should + // be deprecated for WaitForWindowCountToBecome. + bool WaitForWindowCountToChange(int count, int* new_counter, + int wait_timeout); + + // Block the thread until the window count becomes the provided value. + // Returns true on success. + bool WaitForWindowCountToBecome(int target_count, int wait_timeout); + + // Returns the BrowserProxy for the browser window at the given index, + // transferring ownership of the pointer to the caller. + // On failure, returns NULL. + // + // Use GetBrowserWindowCount to see how many browser windows you can ask for. + // Window numbers are 0-based. + BrowserProxy* GetBrowserWindow(int window_index); + + // Returns the BrowserProxy for the browser window which was last active, + // transferring ownership of the pointer to the caller. + // If there was no last active browser window, or the last active browser + // window no longer exists (for example, if it was closed), returns + // GetBrowserWindow(0). + BrowserProxy* GetLastActiveBrowserWindow(); + + // Returns the WindowProxy for the currently active window, transferring + // ownership of the pointer to the caller. + // On failure, returns NULL. + WindowProxy* GetActiveWindow(); + + // Returns the browser this window corresponds to, or NULL if this window + // is not a browser. The caller owns the returned BrowserProxy. + BrowserProxy* GetBrowserForWindow(WindowProxy* window); + + // Same as GetBrowserForWindow except return NULL if response isn't received + // before the specified timeout. + BrowserProxy* GetBrowserForWindowWithTimeout(WindowProxy* window, + uint32 timeout_ms, + bool* is_timeout); + + // Returns the WindowProxy for this browser's window. It can be used to + // retreive view bounds, simulate clicks and key press events. The caller + // owns the returned WindowProxy. + // On failure, returns NULL. + WindowProxy* GetWindowForBrowser(BrowserProxy* browser); + + // Returns an AutocompleteEdit for this browser's window. It can be used to + // manipulate the omnibox. The caller owns the returned pointer. + // On failure, returns NULL. + AutocompleteEditProxy* GetAutocompleteEditForBrowser(BrowserProxy* browser); + + // Tells the browser to enable or disable network request filtering. Returns + // false if the message fails to send to the browser. + bool SetFilteredInet(bool enabled); + + // These methods are intended to be called by the background thread + // to signal that the given event has occurred, and that any corresponding + // Wait... function can return. + void SignalAppLaunch(); + void SignalInitialLoads(); + // load_time is how long, in ms, the tab contents took to load. + void SignalNewTabUITab(int load_time); + + // Returns the ID of the automation IPC channel, so that it can be + // passed to the app as a launch parameter. + const std::wstring& channel_id() const { return channel_id_; } + + // AutomationMessageSender implementations. + virtual bool Send(IPC::Message* message) { return channel_->Send(message); } + virtual bool SendAndWaitForResponse(IPC::Message* request, + IPC::Message** response, + int response_type); + virtual bool SendAndWaitForResponseWithTimeout(IPC::Message* request, + IPC::Message** response, + int response_type, + uint32 timeout_ms, + bool* is_timeout); + + // Returns the current AutomationRequest object. + AutomationRequest* current_request() { return current_request_; } + // Clears the current AutomationRequest object. + void clear_current_request() { current_request_ = NULL; } + + // Wrapper over AutomationHandleTracker::InvalidateHandle. Receives the message + // from AutomationProxy, unpacks the messages and routes that call to the + // tracker. + void InvalidateHandle(const IPC::Message& message); + + // Creates a tab that can hosted in an external process. The function + // returns a TabProxy representing the tab as well as a window handle + // that can be reparented in another process. + TabProxy* AutomationProxy::CreateExternalTab(HWND* external_tab_container); + private: + DISALLOW_EVIL_CONSTRUCTORS(AutomationProxy); + + void InitializeEvents(); + void InitializeChannelID(); + void InitializeThread(); + void InitializeChannel(); + void InitializeHandleTracker(); + + std::wstring channel_id_; + scoped_ptr<Thread> thread_; + scoped_ptr<IPC::ChannelProxy> channel_; + scoped_ptr<AutomationHandleTracker> tracker_; + + HANDLE app_launched_; + HANDLE initial_loads_complete_; + HANDLE new_tab_ui_load_complete_; + int new_tab_ui_load_time_; + + AutomationRequest* current_request_; + + static const int kMaxCommandExecutionTime; // Delay to let the browser + // execute the command.; +}; + +#endif // CHROME_TEST_AUTOMATION_AUTOMATION_PROXY_H__ diff --git a/chrome/test/automation/automation_proxy_uitest.cc b/chrome/test/automation/automation_proxy_uitest.cc new file mode 100644 index 0000000..b639007 --- /dev/null +++ b/chrome/test/automation/automation_proxy_uitest.cc @@ -0,0 +1,831 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <string> + +#include "base/file_util.h" +#include "base/string_util.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/view_ids.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/json_value_serializer.h" +#include "chrome/test/automation/constrained_window_proxy.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "chrome/views/event.h" +#include "net/base/net_util.h" + +typedef UITest AutomationProxyTest; + +class AutomationProxyVisibleTest : public UITest { + protected: + AutomationProxyVisibleTest() { + show_window_ = true; + } +}; + +TEST_F(AutomationProxyTest, GetBrowserWindowCount) { + int window_count = 0; + EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); + EXPECT_EQ(1, window_count); +#ifdef NDEBUG + ASSERT_FALSE(automation()->GetBrowserWindowCount(NULL)); +#endif +} + +TEST_F(AutomationProxyTest, GetBrowserWindow) { + { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + } + + { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(-1)); + ASSERT_FALSE(window.get()); + } + + { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(1)); + ASSERT_FALSE(window.get()); + } +}; + +TEST_F(AutomationProxyVisibleTest, WindowGetViewBounds) { + { + scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + scoped_ptr<WindowProxy> window( + automation()->GetWindowForBrowser(browser.get())); + ASSERT_TRUE(window.get()); + + scoped_ptr<TabProxy> tab1(browser->GetTab(0)); + ASSERT_TRUE(tab1.get()); + GURL tab1_url; + ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url)); + + // Add another tab so we can simulate dragging. + ASSERT_TRUE(browser->AppendTab(GURL("about:"))); + + scoped_ptr<TabProxy> tab2(browser->GetTab(1)); + ASSERT_TRUE(tab2.get()); + GURL tab2_url; + ASSERT_TRUE(tab2->GetCurrentURL(&tab2_url)); + + EXPECT_NE(tab1_url.spec(), tab2_url.spec()); + + gfx::Rect bounds; + ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds, false)); + EXPECT_GT(bounds.x(), 0); + EXPECT_GT(bounds.width(), 0); + EXPECT_GT(bounds.height(), 0); + + gfx::Rect bounds2; + ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_LAST, &bounds2, false)); + EXPECT_GT(bounds2.width(), 0); + EXPECT_GT(bounds2.height(), 0); + EXPECT_GT(bounds2.x(), bounds.x()); + EXPECT_EQ(bounds2.y(), bounds.y()); + + gfx::Rect urlbar_bounds; + ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds, + false)); + EXPECT_GT(urlbar_bounds.x(), 0); + EXPECT_GT(urlbar_bounds.y(), 0); + EXPECT_GT(urlbar_bounds.width(), 0); + EXPECT_GT(urlbar_bounds.height(), 0); + + /* + + TODO(beng): uncomment this section or move to interactive_ui_tests post + haste! + + // Now that we know where the tabs are, let's try dragging one. + POINT start; + POINT end; + start.x = bounds.x() + bounds.width() / 2; + start.y = bounds.y() + bounds.height() / 2; + end.x = start.x + 2 * bounds.width() / 3; + end.y = start.y; + ASSERT_TRUE(browser->SimulateDrag(start, end, + ChromeViews::Event::EF_LEFT_BUTTON_DOWN)); + + // Check to see that the drag event successfully swapped the two tabs. + tab1.reset(browser->GetTab(0)); + ASSERT_TRUE(tab1.get()); + GURL tab1_new_url; + ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url)); + + tab2.reset(browser->GetTab(1)); + ASSERT_TRUE(tab2.get()); + GURL tab2_new_url; + ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url)); + + EXPECT_EQ(tab1_url.spec(), tab2_new_url.spec()); + EXPECT_EQ(tab2_url.spec(), tab1_new_url.spec()); + + */ + } +} + +TEST_F(AutomationProxyTest, GetTabCount) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + int tab_count = 0; + ASSERT_TRUE(window->GetTabCount(&tab_count)); + ASSERT_EQ(1, tab_count); +} + +TEST_F(AutomationProxyTest, GetActiveTabIndex) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + int active_tab_index = -1; + ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index)); + ASSERT_EQ(0, active_tab_index); +} + +TEST_F(AutomationProxyVisibleTest, AppendTab) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + int original_tab_count; + ASSERT_TRUE(window->GetTabCount(&original_tab_count)); + ASSERT_EQ(1, original_tab_count); // By default there are 2 tabs opened. + + int original_active_tab_index; + ASSERT_TRUE(window->GetActiveTabIndex(&original_active_tab_index)); + ASSERT_EQ(0, original_active_tab_index); // By default 0-th tab is active + + ASSERT_TRUE(window->AppendTab(GURL("about:blank"))); + int tab_count; + ASSERT_TRUE(window->GetTabCount(&tab_count)); + ASSERT_EQ(original_tab_count + 1, tab_count); + + int active_tab_index = -1; + ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index)); + ASSERT_EQ(tab_count - 1, active_tab_index); + ASSERT_NE(original_active_tab_index, active_tab_index); + + std::wstring filename(test_data_directory_); + file_util::AppendToPath(&filename, L"title2.html"); + ASSERT_TRUE(window->AppendTab(net_util::FilePathToFileURL(filename))); + + int appended_tab_index; + // Append tab will also be active tab + ASSERT_TRUE(window->GetActiveTabIndex(&appended_tab_index)); + + scoped_ptr<TabProxy> tab(window->GetTab(appended_tab_index)); + ASSERT_TRUE(tab.get()); + std::wstring title; + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"Title Of Awesomeness", title.c_str()); +} + +TEST_F(AutomationProxyTest, ActivateTab) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + ASSERT_TRUE(window->AppendTab(GURL("about:blank"))); + + int at_index = 1; + ASSERT_TRUE(window->ActivateTab(at_index)); + int active_tab_index = -1; + ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index)); + ASSERT_EQ(at_index, active_tab_index); + + at_index = 0; + ASSERT_TRUE(window->ActivateTab(at_index)); + ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index)); + ASSERT_EQ(at_index, active_tab_index); +} + + +TEST_F(AutomationProxyTest, GetTab) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + { + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + std::wstring title; + ASSERT_TRUE(tab->GetTabTitle(&title)); + // BUG [634097] : expected title should be "about:blank" + ASSERT_STREQ(L"", title.c_str()); + } + + { + ASSERT_FALSE(window->GetTab(-1)); + } + + { + scoped_ptr<TabProxy> tab; + tab.reset(window->GetTab(1)); + ASSERT_FALSE(tab.get()); + } +}; + +TEST_F(AutomationProxyTest, NavigateToURL) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring title; + ASSERT_TRUE(tab->GetTabTitle(&title)); + // BUG [634097] : expected title should be "about:blank" + ASSERT_STREQ(L"", title.c_str()); + + std::wstring filename(test_data_directory_); + file_util::AppendToPath(&filename, L"title2.html"); + + tab->NavigateToURL(net_util::FilePathToFileURL(filename)); + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"Title Of Awesomeness", title.c_str()); + + // TODO(vibhor) : Add a test using testserver. +} + +// This test is disabled. See bug 794412 +TEST_F(AutomationProxyTest, DISABLED_NavigateToURLWithTimeout1) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring filename(test_data_directory_); + file_util::AppendToPath(&filename, L"title2.html"); + + bool is_timeout; + tab->NavigateToURLWithTimeout(net_util::FilePathToFileURL(filename), + 10000, &is_timeout); + ASSERT_FALSE(is_timeout); + + std::wstring title; + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"Title Of Awesomeness", title.c_str()); + + tab->NavigateToURLWithTimeout(net_util::FilePathToFileURL(filename), + 1, &is_timeout); + ASSERT_TRUE(is_timeout); + + Sleep(10); +} + +// This test is disabled. See bug 794412. +TEST_F(AutomationProxyTest, DISABLED_NavigateToURLWithTimeout2) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + scoped_ptr<TabProxy> tab(window->GetTab(0)); + tab.reset(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring filename1(test_data_directory_); + file_util::AppendToPath(&filename1, L"title1.html"); + + bool is_timeout; + tab->NavigateToURLWithTimeout(net_util::FilePathToFileURL(filename1), + 1, &is_timeout); + ASSERT_TRUE(is_timeout); + + std::wstring filename2(test_data_directory_); + file_util::AppendToPath(&filename2, L"title2.html"); + tab->NavigateToURLWithTimeout(net_util::FilePathToFileURL(filename2), + 10000, &is_timeout); + ASSERT_FALSE(is_timeout); + + Sleep(10); +} + +TEST_F(AutomationProxyTest, GoBackForward) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring title; + ASSERT_TRUE(tab->GetTabTitle(&title)); + // BUG [634097] : expected title should be "about:blank" + ASSERT_STREQ(L"", title.c_str()); + + ASSERT_FALSE(tab->GoBack()); + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"", title.c_str()); + + std::wstring filename(test_data_directory_); + file_util::AppendToPath(&filename, L"title2.html"); + ASSERT_TRUE(tab->NavigateToURL(net_util::FilePathToFileURL(filename))); + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"Title Of Awesomeness", title.c_str()); + + ASSERT_TRUE(tab->GoBack()); + ASSERT_TRUE(tab->GetTabTitle(&title)); + // BUG [634097] : expected title should be "about:blank" + ASSERT_STREQ(L"", title.c_str()); + + ASSERT_TRUE(tab->GoForward()); + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"Title Of Awesomeness", title.c_str()); + + ASSERT_FALSE(tab->GoForward()); + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"Title Of Awesomeness", title.c_str()); +} + +TEST_F(AutomationProxyTest, GetCurrentURL) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + GURL url; + ASSERT_TRUE(tab->GetCurrentURL(&url)); + ASSERT_STREQ("about:blank", url.spec().c_str()); + + std::wstring filename(test_data_directory_); + file_util::AppendToPath(&filename, L"cookie1.html"); + GURL newurl = net_util::FilePathToFileURL(filename); + ASSERT_TRUE(tab->NavigateToURL(newurl)); + ASSERT_TRUE(tab->GetCurrentURL(&url)); + // compare canonical urls... + ASSERT_STREQ(newurl.spec().c_str(), url.spec().c_str()); +} + +class AutomationProxyTest2 : public AutomationProxyVisibleTest { + protected: + AutomationProxyTest2() { + document1_ = test_data_directory_; + file_util::AppendToPath(&document1_, L"title1.html"); + + document2_ = test_data_directory_; + file_util::AppendToPath(&document2_, L"title2.html"); + launch_arguments_ = document1_ + L" " + document2_; + } + + std::wstring document1_; + std::wstring document2_; +}; + +TEST_F(AutomationProxyTest2, GetActiveTabIndex) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + int active_tab_index = -1; + ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index)); + int tab_count; + ASSERT_TRUE(window->GetTabCount(&tab_count)); + ASSERT_EQ(0, active_tab_index); + int at_index = 1; + ASSERT_TRUE(window->ActivateTab(at_index)); + ASSERT_TRUE(window->GetActiveTabIndex(&active_tab_index)); + ASSERT_EQ(at_index, active_tab_index); +} + +TEST_F(AutomationProxyTest2, GetTabTitle) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + std::wstring title; + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"title1.html", title.c_str()); + + tab.reset(window->GetTab(1)); + ASSERT_TRUE(tab.get()); + ASSERT_TRUE(tab->GetTabTitle(&title)); + ASSERT_STREQ(L"Title Of Awesomeness", title.c_str()); +} + +TEST_F(AutomationProxyTest, Cookies) { + GURL url(L"http://mojo.jojo.google.com"); + std::string value_result; + + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + // test setting the cookie: + ASSERT_TRUE(tab->SetCookie(url, "foo=baz")); + + ASSERT_TRUE(tab->GetCookieByName(url, "foo", &value_result)); + ASSERT_FALSE(value_result.empty()); + ASSERT_STREQ("baz", value_result.c_str()); + + // test clearing the cookie: + ASSERT_TRUE(tab->SetCookie(url, "foo=")); + + ASSERT_TRUE(tab->GetCookieByName(url, "foo", &value_result)); + ASSERT_TRUE(value_result.empty()); + + // now, test that we can get multiple cookies: + ASSERT_TRUE(tab->SetCookie(url, "foo1=baz1")); + ASSERT_TRUE(tab->SetCookie(url, "foo2=baz2")); + + ASSERT_TRUE(tab->GetCookies(url, &value_result)); + ASSERT_FALSE(value_result.empty()); + EXPECT_TRUE(value_result.find("foo1=baz1") != std::string::npos); + EXPECT_TRUE(value_result.find("foo2=baz2") != std::string::npos); +} + +TEST_F(AutomationProxyTest, GetHWND) { + scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + scoped_ptr<WindowProxy> window( + automation()->GetWindowForBrowser(browser.get())); + ASSERT_TRUE(window.get()); + + HWND handle; + ASSERT_TRUE(window->GetHWND(&handle)); + ASSERT_TRUE(handle); +} + +TEST_F(AutomationProxyTest, NavigateToURLAsync) { + AutomationProxy* automation_object = automation(); + scoped_ptr<BrowserProxy> window(automation_object->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring filename(test_data_directory_); + file_util::AppendToPath(&filename, L"cookie1.html"); + GURL newurl = net_util::FilePathToFileURL(filename); + + ASSERT_TRUE(tab->NavigateToURLAsync(newurl)); + std::string value = WaitUntilCookieNonEmpty(tab.get(), newurl, + "foo", 250, 5*1000); + ASSERT_STREQ("baz", value.c_str()); +} + +TEST_F(AutomationProxyTest, AcceleratorNewTab) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + + int old_tab_count = -1; + ASSERT_TRUE(window->GetTabCount(&old_tab_count)); + + ASSERT_TRUE(window->ApplyAccelerator(IDC_NEWTAB)); + int new_tab_count; + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + if (new_tab_count == -1) + FAIL(); + ASSERT_EQ(old_tab_count + 1, new_tab_count); + scoped_ptr<TabProxy> tab(window->GetTab(new_tab_count - 1)); + ASSERT_TRUE(tab.get()); + + std::wstring title; + int i; + for (i = 0; i < 10; ++i) { + Sleep(kWaitForActionMaxMsec / 10); + ASSERT_TRUE(tab->GetTabTitle(&title)); + if (title == L"Destinations" || title == L"New Tab") + break; + } + // If we got to 10, the new tab failed to open. + ASSERT_NE(10, i); +} + +class AutomationProxyTest4 : public UITest { + protected: + AutomationProxyTest4() : UITest() { + dom_automation_enabled_ = true; + } +}; + +std::wstring SynthesizeJSURL(const std::wstring& value) { + std::wstring jscript; + SStringPrintf(&jscript, + L"javascript:void(window.domAutomationController.send(%s));", value.c_str()); + return jscript; +} + +TEST_F(AutomationProxyTest4, StringValueIsEchoedByDomAutomationController) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring expected(L"string"); + std::wstring jscript = SynthesizeJSURL(L"\"" + expected + L"\""); + std::wstring actual; + ASSERT_TRUE(tab->ExecuteAndExtractString(L"", jscript, &actual)); + ASSERT_STREQ(expected.c_str(), actual.c_str()); +} + +std::wstring BooleanToString(bool bool_value) { + Value* value = Value::CreateBooleanValue(bool_value); + std::string json_string; + JSONStringValueSerializer serializer(&json_string); + serializer.Serialize(*value); + return UTF8ToWide(json_string); +} + +TEST_F(AutomationProxyTest4, BooleanValueIsEchoedByDomAutomationController) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + bool expected = true; + std::wstring jscript = SynthesizeJSURL(BooleanToString(expected)); + bool actual = false; + ASSERT_TRUE(tab->ExecuteAndExtractBool(L"", jscript, &actual)); + ASSERT_EQ(expected, actual); +} + +TEST_F(AutomationProxyTest4, NumberValueIsEchoedByDomAutomationController) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + int expected = 1; + int actual = 0; + std::wstring expected_string; + SStringPrintf(&expected_string, L"%d", expected); + std::wstring jscript = SynthesizeJSURL(expected_string); + ASSERT_TRUE(tab->ExecuteAndExtractInt(L"", jscript, &actual)); + ASSERT_EQ(expected, actual); +} + +// TODO(vibhor): Add a test for ExecuteAndExtractValue() for JSON Dictionary +// type value + +class AutomationProxyTest3 : public UITest { + protected: + AutomationProxyTest3() : UITest() { + document1_ = test_data_directory_; + file_util::AppendToPath(&document1_, L"frame_dom_access"); + file_util::AppendToPath(&document1_, L"frame_dom_access.html"); + + dom_automation_enabled_ = true; + launch_arguments_ = document1_; + } + + std::wstring document1_; +}; + +std::wstring SynthesizeJSURLForDOMQuery(const std::wstring& id) { + std::wstring jscript; + SStringPrintf(&jscript, + L"javascript:void(window.domAutomationController)"); + StringAppendF(&jscript, L".send(document.getElementById('%s').nodeName);", + id.c_str()); + return jscript; +} + +TEST_F(AutomationProxyTest3, FrameDocumentCanBeAccessed) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + scoped_ptr<TabProxy> tab(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring actual; + std::wstring xpath1 = L""; // top level frame + std::wstring jscript1 = SynthesizeJSURLForDOMQuery(L"myinput"); + ASSERT_TRUE(tab->ExecuteAndExtractString(xpath1, jscript1, &actual)); + ASSERT_EQ(L"INPUT", actual); + + std::wstring xpath2 = L"/html/body/iframe"; + std::wstring jscript2 = SynthesizeJSURLForDOMQuery(L"myspan"); + ASSERT_TRUE(tab->ExecuteAndExtractString(xpath2, jscript2, &actual)); + ASSERT_EQ(L"SPAN", actual); + + std::wstring xpath3 = L"/html/body/iframe\n/html/body/iframe"; + std::wstring jscript3 = SynthesizeJSURLForDOMQuery(L"mydiv"); + ASSERT_TRUE(tab->ExecuteAndExtractString(xpath3, jscript3, &actual)); + ASSERT_EQ(L"DIV", actual); + + // TODO(evanm): fix or remove this. + // This part of the test appears to verify that executing JS fails + // non-HTML pages, but the new tab is now HTML so this test isn't + // correct. +#if 0 + // Open a new Destinations tab to execute script inside. + window->ApplyAccelerator(IDC_NEWTAB); + tab.reset(window->GetTab(1)); + ASSERT_TRUE(tab.get()); + ASSERT_TRUE(window->ActivateTab(1)); + + std::wstring title; + int i; + for (i = 0; i < 10; ++i) { + Sleep(kWaitForActionMaxMsec / 10); + ASSERT_TRUE(tab->GetTabTitle(&title)); + if (title == L"Destinations") + break; + } + // If we got to 10, the new tab failed to open. + ASSERT_NE(10, i); + ASSERT_FALSE(tab->ExecuteAndExtractString(xpath1, jscript1, &actual)); +#endif +} + +TEST_F(AutomationProxyTest, ConstrainedWindowTest) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + scoped_ptr<TabProxy> tab(window->GetTab(0)); + tab.reset(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring filename(test_data_directory_); + file_util::AppendToPath(&filename, L"constrained_files"); + file_util::AppendToPath(&filename, L"constrained_window.html"); + + ASSERT_TRUE(tab->NavigateToURL(net_util::FilePathToFileURL(filename))); + + int count; + ASSERT_TRUE(tab->WaitForChildWindowCountToChange(0, &count, 5000)); + + ASSERT_EQ(2, count); + + ConstrainedWindowProxy* cwindow = tab->GetConstrainedWindow(0); + ASSERT_TRUE(cwindow); + + std::wstring title; + ASSERT_TRUE(cwindow->GetTitle(&title)); + ASSERT_STREQ(L"Constrained Window 0 - Google Chrome", title.c_str()); + delete cwindow; + + cwindow = tab->GetConstrainedWindow(1); + ASSERT_TRUE(cwindow); + ASSERT_TRUE(cwindow->GetTitle(&title)); + ASSERT_STREQ(L"Constrained Window 1 - Google Chrome", title.c_str()); + delete cwindow; +} + +TEST_F(AutomationProxyTest, CantEscapeByOnloadMoveto) { + scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + scoped_ptr<TabProxy> tab(window->GetTab(0)); + tab.reset(window->GetTab(0)); + ASSERT_TRUE(tab.get()); + + std::wstring filename(test_data_directory_); + file_util::AppendToPath(&filename, L"constrained_files"); + file_util::AppendToPath(&filename, L"constrained_window_onload_moveto.html"); + + ASSERT_TRUE(tab->NavigateToURL(net_util::FilePathToFileURL(filename))); + + int count; + ASSERT_TRUE(tab->WaitForChildWindowCountToChange(0, &count, 5000)); + + ASSERT_EQ(1, count); + + ConstrainedWindowProxy* cwindow = tab->GetConstrainedWindow(0); + ASSERT_TRUE(cwindow); + + gfx::Rect rect; + bool is_timeout = false; + ASSERT_TRUE(cwindow->GetBoundsWithTimeout(&rect, 1000, &is_timeout)); + ASSERT_FALSE(is_timeout); + ASSERT_NE(20, rect.x()); + ASSERT_NE(20, rect.y()); +} + +bool ExternalTabHandler(HWND external_tab_window) { + static const wchar_t class_name[] = L"External_Tab_UI_Test_Class"; + static const wchar_t window_title[] = L"External Tab Tester"; + + WNDCLASSEX wnd_class = {0}; + wnd_class.cbSize = sizeof(wnd_class); + wnd_class.style = CS_HREDRAW | CS_VREDRAW; + wnd_class.lpfnWndProc = DefWindowProc; + wnd_class.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wnd_class.lpszClassName = class_name; + ATOM result = RegisterClassEx(&wnd_class); + if (0 == result) { + return false; + } + + unsigned long style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN; + HWND external_tab_ui_parent = CreateWindow(class_name, window_title, + style, CW_USEDEFAULT, 0, + CW_USEDEFAULT, 0, NULL, NULL, + NULL, NULL); + style = GetWindowLong(external_tab_window, GWL_STYLE); + style |= WS_CHILD; + style &= ~WS_POPUP; + SetWindowLong(external_tab_window, GWL_STYLE, style); + SetParent(external_tab_window, external_tab_ui_parent); + RECT client_rect = {0}; + GetClientRect(external_tab_ui_parent, &client_rect); + SetWindowPos(external_tab_window, NULL, 0, 0, client_rect.right, + client_rect.bottom, SWP_NOZORDER); + ShowWindow(external_tab_window, SW_SHOW); + ShowWindow(external_tab_ui_parent, SW_SHOW); + + // Allow the renderers to connect. + Sleep(1000); + DestroyWindow(external_tab_ui_parent); + return true; +} + +TEST_F(AutomationProxyVisibleTest, CreateExternalTab) { + HWND external_tab_container = NULL; + scoped_ptr<TabProxy> tab(automation()->CreateExternalTab( + &external_tab_container)); + EXPECT_TRUE(tab != NULL); + EXPECT_NE(FALSE, ::IsWindow(external_tab_container)); + if (tab != NULL) { + tab->NavigateInExternalTab(GURL(L"http://www.google.com")); + EXPECT_EQ(true, ExternalTabHandler(external_tab_container)); + // Since the tab goes away lazily, wait a bit + Sleep(1000); + EXPECT_FALSE(tab->is_valid()); + } +} + +TEST_F(AutomationProxyTest, AutocompleteGetSetText) { + scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + scoped_ptr<AutocompleteEditProxy> edit( + automation()->GetAutocompleteEditForBrowser(browser.get())); + ASSERT_TRUE(edit.get()); + EXPECT_TRUE(edit->is_valid()); + const std::wstring text_to_set = L"Lollerskates"; + std::wstring actual_text; + EXPECT_TRUE(edit->SetText(text_to_set)); + EXPECT_TRUE(edit->GetText(&actual_text)); + EXPECT_EQ(text_to_set, actual_text); + scoped_ptr<AutocompleteEditProxy> edit2( + automation()->GetAutocompleteEditForBrowser(browser.get())); + EXPECT_TRUE(edit2->GetText(&actual_text)); + EXPECT_EQ(text_to_set, actual_text); +} + +TEST_F(AutomationProxyTest, AutocompleteParallelProxy) +{ + scoped_ptr<BrowserProxy> browser1(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser1.get()); + scoped_ptr<AutocompleteEditProxy> edit1( + automation()->GetAutocompleteEditForBrowser(browser1.get())); + ASSERT_TRUE(edit1.get()); + EXPECT_TRUE(browser1->ApplyAccelerator(IDC_DUPLICATE)); + scoped_ptr<BrowserProxy> browser2(automation()->GetBrowserWindow(1)); + ASSERT_TRUE(browser2.get()); + scoped_ptr<AutocompleteEditProxy> edit2( + automation()->GetAutocompleteEditForBrowser(browser2.get())); + ASSERT_TRUE(edit2.get()); + EXPECT_TRUE(browser2->GetTab(0)->WaitForTabToBeRestored()); + const std::wstring text_to_set1 = L"Lollerskates"; + const std::wstring text_to_set2 = L"Roflcopter"; + std::wstring actual_text1, actual_text2; + EXPECT_TRUE(edit1->SetText(text_to_set1)); + EXPECT_TRUE(edit2->SetText(text_to_set2)); + EXPECT_TRUE(edit1->GetText(&actual_text1)); + EXPECT_TRUE(edit2->GetText(&actual_text2)); + EXPECT_EQ(text_to_set1, actual_text1); + EXPECT_EQ(text_to_set2, actual_text2); +} + +TEST_F(AutomationProxyVisibleTest, AutocompleteMatchesTest) { + scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + scoped_ptr<AutocompleteEditProxy> edit( + automation()->GetAutocompleteEditForBrowser(browser.get())); + ASSERT_TRUE(edit.get()); + EXPECT_TRUE(browser->ApplyAccelerator(IDC_FOCUS_LOCATION)); + EXPECT_TRUE(edit->is_valid()); + EXPECT_TRUE(edit->SetText(L"Roflcopter")); + EXPECT_TRUE(edit->WaitForQuery(30000)); + bool query_in_progress; + EXPECT_TRUE(edit->IsQueryInProgress(&query_in_progress)); + EXPECT_FALSE(query_in_progress); + std::vector<AutocompleteMatchData> matches; + EXPECT_TRUE(edit->GetAutocompleteMatches(&matches)); + EXPECT_FALSE(matches.empty()); +} diff --git a/chrome/test/automation/browser_proxy.cc b/chrome/test/automation/browser_proxy.cc new file mode 100644 index 0000000..81b8900 --- /dev/null +++ b/chrome/test/automation/browser_proxy.cc @@ -0,0 +1,348 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/automation/browser_proxy.h" + +#include <vector> + +#include "base/logging.h" +#include "base/time.h" +#include "chrome/test/automation/automation_constants.h" +#include "chrome/test/automation/automation_messages.h" +#include "chrome/test/automation/automation_proxy.h" +#include "chrome/test/automation/tab_proxy.h" + +bool BrowserProxy::ActivateTab(int tab_index) { + return ActivateTabWithTimeout(tab_index, INFINITE, NULL); +} + +bool BrowserProxy::ActivateTabWithTimeout(int tab_index, uint32 timeout_ms, + bool* is_timeout) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_ActivateTabRequest(0, handle_, tab_index), &response, + AutomationMsg_ActivateTabResponse::ID, timeout_ms, is_timeout); + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return false; + + void* iter = NULL; + int activate_tab_response = -1; + if (response->ReadInt(&iter, &activate_tab_response) && + (activate_tab_response >= 0)) { + succeeded = true; + } else { + succeeded = false; + } + + return succeeded; +} + +bool BrowserProxy::BringToFront() { + return BringToFrontWithTimeout(INFINITE, NULL); +} + +bool BrowserProxy::BringToFrontWithTimeout(uint32 timeout_ms, + bool* is_timeout) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_BringBrowserToFront(0, handle_), &response, + AutomationMsg_BringBrowserToFrontResponse::ID, timeout_ms, is_timeout); + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return false; + + void* iter = NULL; + if (!response->ReadBool(&iter, &succeeded)) + succeeded = false; + + return succeeded; +} + +bool BrowserProxy::IsPageMenuCommandEnabledWithTimeout(int id, + uint32 timeout_ms, + bool* is_timeout) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_IsPageMenuCommandEnabled(0, handle_, id), &response, + AutomationMsg_IsPageMenuCommandEnabledResponse::ID, timeout_ms, is_timeout); + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return false; + + void* iter = NULL; + if (!response->ReadBool(&iter, &succeeded)) + succeeded = false; + + return succeeded; +} + +bool BrowserProxy::AppendTab(const GURL& tab_url) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_AppendTabRequest(0, handle_, tab_url), &response, + AutomationMsg_AppendTabResponse::ID); + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return false; + + void* iter = NULL; + int append_tab_response = -1; + if (response->ReadInt(&iter, &append_tab_response) && + (append_tab_response >= 0)) { + succeeded = true; + } else { + succeeded = false; + } + + return succeeded; +} + +bool BrowserProxy::GetActiveTabIndex(int* active_tab_index) const { + return GetActiveTabIndexWithTimeout(active_tab_index, INFINITE, NULL); +} + +bool BrowserProxy::GetActiveTabIndexWithTimeout(int* active_tab_index, + uint32 timeout_ms, + bool* is_timeout) const { + if (!is_valid()) + return false; + + if (!active_tab_index) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_ActiveTabIndexRequest(0, handle_), &response, + AutomationMsg_ActiveTabIndexResponse::ID, timeout_ms, is_timeout); + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return false; + + void* iter = NULL; + int active_tab_index_response = -1; + if (response->ReadInt(&iter, &active_tab_index_response) && + (active_tab_index_response >= 0)) { + *active_tab_index = active_tab_index_response; + } else { + succeeded = false; + } + + return succeeded; +} + +TabProxy* BrowserProxy::GetTab(int tab_index) const { + if (!is_valid()) + return NULL; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_TabRequest(0, handle_, tab_index), &response, + AutomationMsg_TabResponse::ID); + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return NULL; + + void* iter = NULL; + int handle; + + if (!response->ReadInt(&iter, &handle) || (handle == 0)) + return NULL; + return new TabProxy(sender_, tracker_, handle); +} + +TabProxy* BrowserProxy::GetActiveTab() const { + return GetActiveTabWithTimeout(INFINITE, NULL); +} + +TabProxy* BrowserProxy::GetActiveTabWithTimeout(uint32 timeout_ms, + bool* is_timeout) const { + int active_tab_index; + if (!GetActiveTabIndexWithTimeout(&active_tab_index, timeout_ms, is_timeout)) + return NULL; + return GetTab(active_tab_index); +} + +bool BrowserProxy::GetTabCount(int* num_tabs) const { + return GetTabCountWithTimeout(num_tabs, INFINITE, NULL); +} + +bool BrowserProxy::GetTabCountWithTimeout(int* num_tabs, uint32 timeout_ms, + bool* is_timeout) const { + if (!is_valid()) + return false; + + if (!num_tabs) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_TabCountRequest(0, handle_), &response, + AutomationMsg_TabCountResponse::ID, timeout_ms, is_timeout); + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return false; + + void* iter = NULL; + int tab_count_response = -1; + if (response->ReadInt(&iter, &tab_count_response) && + (tab_count_response >= 0)) { + *num_tabs = tab_count_response; + } else { + succeeded = false; + } + + return succeeded; +} + +bool BrowserProxy::ApplyAccelerator(int id) { + if (!is_valid()) + return false; + + return sender_->Send( + new AutomationMsg_ApplyAcceleratorRequest(0, handle_, id)); +} + +bool BrowserProxy::SimulateDrag(const POINT& start, + const POINT& end, + int flags) { + return SimulateDragWithTimeout(start, end, flags, INFINITE, NULL); +} + +bool BrowserProxy::SimulateDragWithTimeout(const POINT& start, + const POINT& end, + int flags, + uint32 timeout_ms, + bool* is_timeout) { + if (!is_valid()) + return false; + + std::vector<POINT> drag_path; + drag_path.push_back(start); + drag_path.push_back(end); + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_WindowDragRequest(0, handle_, drag_path, flags), + &response, AutomationMsg_WindowDragResponse::ID, timeout_ms, is_timeout); + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return false; + + void* iter = NULL; + if (!response->ReadBool(&iter, &succeeded)) + succeeded = false; + + return succeeded; +} + +bool BrowserProxy::WaitForTabCountToChange(int count, int* new_count, + int wait_timeout) { + const TimeTicks start = TimeTicks::Now(); + const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout); + while (TimeTicks::Now() - start < timeout) { + Sleep(automation::kSleepTime); + bool is_timeout; + bool succeeded = GetTabCountWithTimeout(new_count, wait_timeout, + &is_timeout); + if (!succeeded) + return false; + if (count != *new_count) + return true; + } + // If we get here, the tab count hasn't changed. + return false; +} + +bool BrowserProxy::WaitForTabToBecomeActive(int tab, + int wait_timeout) { + const TimeTicks start = TimeTicks::Now(); + const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout); + while (TimeTicks::Now() - start < timeout) { + Sleep(automation::kSleepTime); + int active_tab; + if (GetActiveTabIndex(&active_tab) && active_tab == tab) + return true; + } + // If we get here, the active tab hasn't changed. + return false; +} + +bool BrowserProxy::GetHWND(HWND* handle) const { + if (!is_valid()) + return false; + + if (!handle) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_WindowHWNDRequest(0, handle_), &response, + AutomationMsg_WindowHWNDResponse::ID); + + scoped_ptr<IPC::Message> response_deleter(response); // Delete on return. + if (!succeeded) + return false; + + HWND hwnd_response; + if (AutomationMsg_WindowHWNDResponse::Read(response, &hwnd_response) && + hwnd_response) { + *handle = hwnd_response; + } else { + succeeded = false; + } + + return succeeded; +} diff --git a/chrome/test/automation/browser_proxy.h b/chrome/test/automation/browser_proxy.h new file mode 100644 index 0000000..469b377 --- /dev/null +++ b/chrome/test/automation/browser_proxy.h @@ -0,0 +1,164 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATION_BROWSER_PROXY_H__ +#define CHROME_TEST_AUTOMATION_BROWSER_PROXY_H__ + +#include <string> +#include <windows.h> +#include "chrome/test/automation/automation_handle_tracker.h" + +class GURL; +class TabProxy; + +namespace gfx { + class Rect; +} + +// This class presents the interface to actions that can be performed on +// a given browser window. Note that this object can be invalidated at any +// time if the corresponding browser window in the app is closed. In that case, +// any subsequent calls will return false immediately. +class BrowserProxy : public AutomationResourceProxy { + public: + BrowserProxy(AutomationMessageSender* sender, + AutomationHandleTracker* tracker, + int handle) + : AutomationResourceProxy(tracker, sender, handle) {} + virtual ~BrowserProxy() {} + + // Activates the tab corresponding to (zero-based) tab_index. Returns true if + // successful. + bool ActivateTab(int tab_index); + + // Like ActivateTab, but returns false if response is not received before + // the specified timeout. + bool ActivateTabWithTimeout(int tab_index, uint32 timeout_ms, + bool* is_timeout); + + // Bring the browser window to the front, activating it. Returns true on + // success. + bool BringToFront(); + + // Like BringToFront, but returns false if action is not completed before + // the specified timeout. + bool BringToFrontWithTimeout(uint32 timeout_ms, bool* is_timeout); + + // Checks to see if a navigation command is active or not. Can also + // return false if action is not completed before the specified + // timeout; is_timeout will be set in those cases. + bool IsPageMenuCommandEnabledWithTimeout(int id, uint32 timeout_ms, + bool* is_timeout); + + // Append a new tab to the TabStrip. The new tab is selected. + // The new tab navigates to the given tab_url. + // Returns true if successful. + // TODO(mpcomplete): If the navigation results in an auth challenge, the + // TabProxy we attach won't know about it. See bug 666730. + bool AppendTab(const GURL& tab_url); + + // Gets the (zero-based) index of the currently active tab. Returns true if + // successful. + bool GetActiveTabIndex(int* active_tab_index) const; + + // Like GetActiveTabIndex, but returns false if active tab is not received + // before the specified timeout. + bool GetActiveTabIndexWithTimeout(int* active_tab_index, uint32 timeout_ms, + bool* is_timeout) const; + + // Returns the number of tabs in the given window. Returns true if + // the call was successful. + bool GetTabCount(int* num_tabs) const; + + // Like GetTabCount, but returns false if tab count is not received within the + // before timeout. + bool GetTabCountWithTimeout(int* num_tabs, uint32 timeout_ms, + bool* is_timeout) const; + + // Returns the TabProxy for the tab at the given index, transferring + // ownership of the pointer to the caller. On failure, returns NULL. + // + // Use GetTabCount to see how many windows you can ask for. Tab numbers + // are 0-based. + TabProxy* GetTab(int tab_index) const; + + // Returns the TabProxy for the currently active tab, transferring + // ownership of the pointer to the caller. On failure, returns NULL. + TabProxy* GetActiveTab() const; + + // Like GetActiveTab, but returns NULL if no response is received before + // the specified timout. + TabProxy* GetActiveTabWithTimeout(uint32 timeout_ms, bool* is_timeout) const; + + // Apply the accelerator with given id (IDC_BACK, IDC_NEWTAB ...) + // Returns true if the call was successful. + // + // The alternate way to test the accelerators is to use the Windows messaging + // system to send the actual keyboard events (ui_controls.h) A precondition + // to using this system is that the target window should have the keyboard + // focus. This leads to a flaky test behavior in circumstances when the + // desktop screen is locked or the test is being executed over a remote + // desktop. + bool ApplyAccelerator(int id); + + // Performs a drag operation between the start and end points (both defined + // in window coordinates). |flags| specifies which buttons are pressed for + // the drag, as defined in chrome/views/event.h. + virtual bool SimulateDrag(const POINT& start, const POINT& end, int flags); + + // Like SimulateDrag, but returns false if response is not received before + // the specified timeout. + virtual bool SimulateDragWithTimeout(const POINT& start, const POINT& end, + int flags, uint32 timeout_ms, + bool* is_timeout); + + // Block the thread until the tab count changes. + // |count| is the original tab count. + // |new_count| is updated with the number of new tabs. + // |wait_timeout| is the timeout, in milliseconds, for waiting. + // Returns false if the tab count does not change. + bool WaitForTabCountToChange(int count, int* new_count, int wait_timeout); + + // Block the thread until the specified tab is the active tab. + // |wait_timeout| is the timeout, in milliseconds, for waiting. + // Returns false if the tab does not become active. + bool WaitForTabToBecomeActive(int tab, int wait_timeout); + + // Gets the outermost HWND that corresponds to the given browser. + // Returns true if the call was successful. + // Note that ideally this should go and the version of WindowProxy should be + // used instead. We have to keep it for start_up_tests that test against a + // reference build. + bool GetHWND(HWND* handle) const; + + private: + DISALLOW_EVIL_CONSTRUCTORS(BrowserProxy); +}; + +#endif // #define CHROME_TEST_AUTOMATION_BROWSER_PROXY_H__ diff --git a/chrome/test/automation/constrained_window_proxy.cc b/chrome/test/automation/constrained_window_proxy.cc new file mode 100644 index 0000000..03fae09 --- /dev/null +++ b/chrome/test/automation/constrained_window_proxy.cc @@ -0,0 +1,92 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "constrained_window_proxy.h" + +#include "chrome/test/automation/automation_messages.h" +#include "chrome/test/automation/automation_proxy.h" + +bool ConstrainedWindowProxy::GetTitle(std::wstring* title) const { + if (!is_valid()) + return false; + + if (!title) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_ConstrainedTitleRequest(0, handle_), &response, + AutomationMsg_ConstrainedTitleResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + int title_size_response = -1; + if (response->ReadInt(&iter, &title_size_response) && + (title_size_response >= 0)) { + response->ReadWString(&iter, title); + } else { + succeeded = false; + } + + delete response; + return succeeded; +} + +bool ConstrainedWindowProxy::GetBoundsWithTimeout(gfx::Rect* bounds, + uint32 timeout_ms, + bool* is_timeout) { + if (!is_valid()) + return false; + + if (!bounds) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_ConstrainedWindowBoundsRequest(0, handle_), + &response, + AutomationMsg_ConstrainedWindowBoundsResponse::ID, + timeout_ms, + is_timeout); + scoped_ptr<IPC::Message> responseDeleter(response); + if (!succeeded) + return false; + + Tuple2<bool, gfx::Rect> result; + AutomationMsg_WindowViewBoundsResponse::Read(response, &result); + + *bounds = result.b; + return result.a; +} diff --git a/chrome/test/automation/constrained_window_proxy.h b/chrome/test/automation/constrained_window_proxy.h new file mode 100644 index 0000000..f3dcb6c --- /dev/null +++ b/chrome/test/automation/constrained_window_proxy.h @@ -0,0 +1,59 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATION_CONSTRAINED_WINDOW_PROXY_H__ +#define CHROME_TEST_AUTOMATION_CONSTRAINED_WINDOW_PROXY_H__ + +#include <string> + +#include "chrome/test/automation/automation_handle_tracker.h" + +namespace gfx { +class Rect; +} + +class ConstrainedWindowProxy : public AutomationResourceProxy { +public: + ConstrainedWindowProxy(AutomationMessageSender* sender, + AutomationHandleTracker* tracker, + int handle) + : AutomationResourceProxy(tracker, sender, handle) {} + + virtual ~ConstrainedWindowProxy() {} + + bool GetTitle(std::wstring* title) const; + bool GetBoundsWithTimeout(gfx::Rect* bounds, + uint32 timeout_ms, + bool* is_timeout); + +private: + DISALLOW_EVIL_CONSTRUCTORS(ConstrainedWindowProxy); +}; + +#endif // CHROME_TEST_AUTOMATION_CONSTRAINED_WINDOW_PROXY_H__
\ No newline at end of file diff --git a/chrome/test/automation/tab_proxy.cc b/chrome/test/automation/tab_proxy.cc new file mode 100644 index 0000000..4fb4432 --- /dev/null +++ b/chrome/test/automation/tab_proxy.cc @@ -0,0 +1,920 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/automation/tab_proxy.h" + +#include <algorithm> + +#include "base/logging.h" +#include "chrome/common/json_value_serializer.h" +#include "chrome/test/automation/automation_constants.h" +#include "chrome/test/automation/automation_messages.h" +#include "chrome/test/automation/automation_proxy.h" +#include "chrome/test/automation/constrained_window_proxy.h" +#include "googleurl/src/gurl.h" + +bool TabProxy::GetTabTitle(std::wstring* title) const { + if (!is_valid()) + return false; + + if (!title) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_TabTitleRequest(0, handle_), &response, + AutomationMsg_TabTitleResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + int tab_title_size_response = -1; + if (response->ReadInt(&iter, &tab_title_size_response) && + (tab_title_size_response >= 0)) { + response->ReadWString(&iter, title); + } else { + succeeded = false; + } + + delete response; + return succeeded; +} + +bool TabProxy::IsShelfVisible(bool* is_visible) { + if (!is_valid()) + return false; + + if (!is_visible) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_ShelfVisibilityRequest(0, handle_), + &response, + AutomationMsg_ShelfVisibilityResponse::ID); + if (!succeeded) + return false; + + void* iter = NULL; + response->ReadBool(&iter, is_visible); + delete response; + return true; +} + +int TabProxy::FindInPage(const std::wstring& search_string, + FindInPageDirection forward, + FindInPageCase match_case) { + if (!is_valid()) + return -1; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_FindInPageRequest(0, handle_, search_string, + forward, match_case), + &response, + AutomationMsg_FindInPageResponse::ID); + if (!succeeded) + return -1; + + void* iter = NULL; + int matches_found; + AutomationMsg_FindInPageResponse::Read(response, &matches_found); + + return matches_found; +} + +int TabProxy::NavigateToURL(const GURL& url) { + return NavigateToURLWithTimeout(url, INFINITE, NULL); +} + +int TabProxy::NavigateToURLWithTimeout(const GURL& url, + uint32 timeout_ms, + bool* is_timeout) { + if (!is_valid()) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_NavigateToURLRequest(0, handle_, url), &response, + AutomationMsg_NavigateToURLResponse::ID, timeout_ms, is_timeout); + + if (!succeeded) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + void* iter = NULL; + int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR; + response->ReadInt(&iter, &navigate_response); + + delete response; + return navigate_response; +} + +int TabProxy::NavigateInExternalTab(const GURL& url) { + if (!is_valid()) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + IPC::Message* response = NULL; + bool is_timeout = false; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_NavigateInExternalTabRequest(0, handle_, url), &response, + AutomationMsg_NavigateInExternalTabResponse::ID, INFINITE, &is_timeout); + + if (!succeeded) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + void* iter = NULL; + int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR; + response->ReadInt(&iter, &navigate_response); + + delete response; + return navigate_response; +} + +bool TabProxy::SetAuth(const std::wstring& username, + const std::wstring& password) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_SetAuthRequest(0, handle_, username, password), &response, + AutomationMsg_SetAuthResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + int navigate_response = -1; + succeeded = (response->ReadInt(&iter, &navigate_response) && + navigate_response >= 0); + + delete response; + return succeeded; +} + +bool TabProxy::CancelAuth() { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_CancelAuthRequest(0, handle_), &response, + AutomationMsg_CancelAuthResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + int navigate_response = -1; + succeeded = (response->ReadInt(&iter, &navigate_response) && + navigate_response >= 0); + + delete response; + return succeeded; +} + +bool TabProxy::NeedsAuth() const { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_NeedsAuthRequest(0, handle_), &response, + AutomationMsg_NeedsAuthResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + bool needs_auth = false; + response->ReadBool(&iter, &needs_auth); + + delete response; + return needs_auth; +} + +int TabProxy::GoBack() { + if (!is_valid()) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_GoBackRequest(0, handle_), &response, + AutomationMsg_GoBackResponse::ID); + + if (!succeeded) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + void* iter = NULL; + int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR; + response->ReadInt(&iter, &navigate_response); + + delete response; + return navigate_response; +} + +int TabProxy::GoForward() { + if (!is_valid()) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_GoForwardRequest(0, handle_), &response, + AutomationMsg_GoForwardResponse::ID); + + if (!succeeded) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + void* iter = NULL; + int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR; + response->ReadInt(&iter, &navigate_response); + + delete response; + return navigate_response; +} + +int TabProxy::Reload() { + if (!is_valid()) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_ReloadRequest(0, handle_), &response, + AutomationMsg_ReloadResponse::ID); + + if (!succeeded) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + void* iter = NULL; + int navigate_response = AUTOMATION_MSG_NAVIGATION_ERROR; + response->ReadInt(&iter, &navigate_response); + + delete response; + return navigate_response; +} + +bool TabProxy::GetRedirectsFrom(const GURL& source_url, + std::vector<GURL>* redirects) { + std::vector<GURL> output; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_RedirectsFromRequest(0, handle_, source_url), &response, + AutomationMsg_RedirectsFromResponse::ID); + if (!succeeded) + return false; + scoped_ptr<IPC::Message> auto_deleter(response); + + void* iter = NULL; + int num_redirects; + if (!response->ReadInt(&iter, &num_redirects)) + return false; + if (num_redirects < 0) + return false; // Negative redirect counts indicate failure. + + for (int i = 0; i < num_redirects; i++) { + GURL cur; + if (!IPC::ParamTraits<GURL>::Read(response, &iter, &cur)) + return false; + output.push_back(cur); + } + redirects->swap(output); + return true; +} + +bool TabProxy::GetCurrentURL(GURL* url) const { + if (!is_valid()) + return false; + + if (!url) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_TabURLRequest(0, handle_), &response, + AutomationMsg_TabURLResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + bool tab_url_success = false; + if (response->ReadBool(&iter, &tab_url_success) && tab_url_success) { + if (!IPC::ParamTraits<GURL>::Read(response, &iter, url)) + succeeded = false; + } else { + succeeded = false; + } + + delete response; + return succeeded; +} + +bool TabProxy::NavigateToURLAsync(const GURL& url) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_NavigationAsyncRequest(0, handle_, url), &response, + AutomationMsg_NavigationAsyncResponse::ID); + + if (!succeeded) + return false; + + bool status; + if (AutomationMsg_NavigationAsyncResponse::Read(response, &status) && + status) { + succeeded = true; + } + + delete response; + return succeeded; +} + +bool TabProxy::GetHWND(HWND* hwnd) const { + if (!is_valid()) + return false; + if (!hwnd) { + NOTREACHED(); + return false; + } + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_TabHWNDRequest(0, handle_), &response, + AutomationMsg_TabHWNDResponse::ID); + if (!succeeded) + return false; + void* iter = NULL; + HWND tab_hwnd = NULL; + if (AutomationMsg_TabHWNDResponse::Read(response, &tab_hwnd) && tab_hwnd) { + *hwnd = tab_hwnd; + } else { + succeeded = false; + } + + delete response; + return succeeded; +} + +bool TabProxy::GetProcessID(int* process_id) const { + if (!is_valid()) + return false; + + if (!process_id) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_TabProcessIDRequest(0, handle_), &response, + AutomationMsg_TabProcessIDResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + int pid; + if (AutomationMsg_TabProcessIDResponse::Read(response, &pid) && (pid >= 0)) { + *process_id = pid; + } else { + succeeded = false; + } + + delete response; + return succeeded; +} + +bool TabProxy::ExecuteAndExtractString(const std::wstring& frame_xpath, + const std::wstring& jscript, + std::wstring* string_value) { + Value* root = NULL; + bool succeeded = ExecuteAndExtractValue(frame_xpath, jscript, &root); + if (!succeeded) + return false; + + std::wstring read_value; + DCHECK(root->IsType(Value::TYPE_LIST)); + Value* value = NULL; + succeeded = static_cast<ListValue*>(root)->Get(0, &value); + if (succeeded) { + succeeded = value->GetAsString(&read_value); + if (succeeded) { + string_value->swap(read_value); + } + } + + delete root; + return succeeded; +} + +bool TabProxy::ExecuteAndExtractBool(const std::wstring& frame_xpath, + const std::wstring& jscript, + bool* bool_value) { + Value* root = NULL; + bool succeeded = ExecuteAndExtractValue(frame_xpath, jscript, &root); + if (!succeeded) + return false; + + bool read_value = false; + DCHECK(root->IsType(Value::TYPE_LIST)); + Value* value = NULL; + succeeded = static_cast<ListValue*>(root)->Get(0, &value); + if (succeeded) { + succeeded = value->GetAsBoolean(&read_value); + if (succeeded) { + *bool_value = read_value; + } + } + + delete value; + return succeeded; +} + +bool TabProxy::ExecuteAndExtractInt(const std::wstring& frame_xpath, + const std::wstring& jscript, + int* int_value) { + Value* root = NULL; + bool succeeded = ExecuteAndExtractValue(frame_xpath, jscript, &root); + if (!succeeded) + return false; + + int read_value = 0; + DCHECK(root->IsType(Value::TYPE_LIST)); + Value* value = NULL; + succeeded = static_cast<ListValue*>(root)->Get(0, &value); + if (succeeded) { + succeeded = value->GetAsInteger(&read_value); + if (succeeded) { + *int_value = read_value; + } + } + + delete value; + return succeeded; +} + +bool TabProxy::ExecuteAndExtractValue(const std::wstring& frame_xpath, + const std::wstring& jscript, + Value** value) { + if (!is_valid()) + return false; + + if (!value) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_DomOperationRequest(0, handle_, frame_xpath, jscript), + &response, AutomationMsg_DomOperationResponse::ID); + + void* iter = NULL; + std::string json; + succeeded = response->ReadString(&iter, &json); + if (!succeeded) { + delete response; + return false; + } + // Wrap |json| in an array before deserializing because valid JSON has an + // array or an object as the root. + json.insert(0, "["); + json.append("]"); + + JSONStringValueSerializer deserializer(json); + succeeded = deserializer.Deserialize(value); + + delete response; + return succeeded; +} + +bool TabProxy::GetConstrainedWindowCount(int* count) const { + if (!is_valid()) + return false; + + if (!count) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_ConstrainedWindowCountRequest(0, handle_), + &response, AutomationMsg_ConstrainedWindowCountResponse::ID); + + void* iter = NULL; + int count_response = -1; + if (response->ReadInt(&iter, &count_response) && + (count_response >= 0)) { + *count = count_response; + } else { + succeeded = false; + } + + delete response; + return succeeded; +} + +ConstrainedWindowProxy* TabProxy::GetConstrainedWindow( + int window_index) const { + if (!is_valid()) + return NULL; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_ConstrainedWindowRequest(0, handle_, window_index), + &response, AutomationMsg_ConstrainedWindowResponse::ID); + if (!succeeded) + return NULL; + + void* iter = NULL; + int handle; + + scoped_ptr<IPC::Message> response_deleter(response); // Ensure deleted. + if (response->ReadInt(&iter, &handle) && (handle != 0)) + return new ConstrainedWindowProxy(sender_, tracker_, handle); + return NULL; +} + +bool TabProxy::WaitForChildWindowCountToChange(int count, int* new_count, + int wait_timeout) { + int intervals = std::min(wait_timeout/automation::kSleepTime, 1); + for (int i = 0; i < intervals; ++i) { + Sleep(automation::kSleepTime); + bool succeeded = GetConstrainedWindowCount(new_count); + if (!succeeded) return false; + if (count != *new_count) return true; + } + // Constrained Window count did not change, return false. + return false; +} + +bool TabProxy::GetCookies(const GURL& url, std::string* cookies) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_GetCookiesRequest(0, url, handle_), &response, + AutomationMsg_GetCookiesResponse::ID); + + if (succeeded) { + void* iter = NULL; + int size; + std::string local_value; + + if (response->ReadInt(&iter, &size) && size >=0) { + if (!response->ReadString(&iter, cookies)) { + succeeded = false; + } + } else { + succeeded = false; + } + } + + delete response; + return succeeded; +} + +bool TabProxy::GetCookieByName(const GURL& url, + const std::string& name, + std::string* cookie) { + std::string cookies; + if (!GetCookies(url, &cookies)) + return false; + + std::string namestr = name + "="; + std::string::size_type idx = cookies.find(namestr); + if (idx != std::string::npos) { + cookies.erase(0, idx + namestr.length()); + *cookie = cookies.substr(0, cookies.find(";")); + } else { + cookie->clear(); + } + + return true; +} + +bool TabProxy::SetCookie(const GURL& url, const std::string& value) { + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_SetCookieRequest(0, url, value, handle_), &response, + AutomationMsg_SetCookieResponse::ID); + if (!succeeded) + return false; + + void* iter = NULL; + int response_value; + + if (!response->ReadInt(&iter, &response_value) || response_value < 0) { + succeeded = false; + } + + delete response; + return succeeded; +} + +int TabProxy::InspectElement(int x, int y) { + if (!is_valid()) + return -1; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_InspectElementRequest(0, handle_, x, y), + &response, AutomationMsg_InspectElementResponse::ID); + if (!succeeded) + return -1; + + int ret; + AutomationMsg_InspectElementResponse::Read(response, &ret); + return ret; +} + +bool TabProxy::GetDownloadDirectory(std::wstring* download_directory) { + DCHECK(download_directory); + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = + sender_->SendAndWaitForResponse( + new AutomationMsg_DownloadDirectoryRequest(0, handle_), + &response, + AutomationMsg_DownloadDirectoryResponse::ID); + if (!succeeded) + return false; + + void* iter = NULL; + response->ReadWString(&iter, download_directory); + delete response; + return true; +} + +bool TabProxy::ShowInterstitialPage(const std::string& html_text) { + if (!is_valid()) + return false; + + const int kTimeout = 2000; + bool is_timeout = false; + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_ShowInterstitialPageRequest(0, handle_, html_text), + &response, + AutomationMsg_ShowInterstitialPageResponse::ID, kTimeout, &is_timeout); + + if (!succeeded || !is_timeout) + return false; + + void* iter = NULL; + bool result = true; + response->ReadBool(&iter, &result); + + delete response; + return result; +} + +bool TabProxy::HideInterstitialPage() { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = + sender_->SendAndWaitForResponse( + new AutomationMsg_HideInterstitialPageRequest(0, handle_), + &response, + AutomationMsg_HideInterstitialPageResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + bool result = true; + response->ReadBool(&iter, &result); + + delete response; + return result; +} + +bool TabProxy::Close() { + return Close(false); +} + +bool TabProxy::Close(bool wait_until_closed) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = + sender_->SendAndWaitForResponse( + new AutomationMsg_CloseTabRequest(0, handle_, wait_until_closed), + &response, + AutomationMsg_CloseTabResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + bool result = true; + response->ReadBool(&iter, &result); + + delete response; + return result; +} + +bool TabProxy::SetAccelerators(HACCEL accel_table, + int accel_table_entry_count) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool is_timeout = false; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_SetAcceleratorsForTab(0, handle_, accel_table, + accel_table_entry_count), + &response, + AutomationMsg_SetAcceleratorsForTabResponse::ID, INFINITE, &is_timeout); + + if (!succeeded) + return AUTOMATION_MSG_NAVIGATION_ERROR; + + void* iter = NULL; + bool set_accel_response = false; + response->ReadBool(&iter, &set_accel_response); + + delete response; + return set_accel_response; +} + +bool TabProxy::ProcessUnhandledAccelerator(const MSG& msg) { + if (!is_valid()) + return false; + return sender_->Send( + new AutomationMsg_ProcessUnhandledAccelerator(0, handle_, msg)); + // This message expects no response +} + +bool TabProxy::WaitForTabToBeRestored() { + if (!is_valid()) + return false; + IPC::Message* response = NULL; + return sender_->SendAndWaitForResponse( + new AutomationMsg_WaitForTabToBeRestored(0, handle_), &response, + AutomationMsg_TabFinishedRestoring::ID); +} + +bool TabProxy::GetSecurityState(SecurityStyle* security_style, + int* ssl_cert_status, + int* mixed_content_state) { + DCHECK(security_style && ssl_cert_status && mixed_content_state); + + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool is_timeout = false; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_GetSecurityState(0, handle_), + &response, + AutomationMsg_GetSecurityStateResponse::ID, INFINITE, &is_timeout); + scoped_ptr<IPC::Message> auto_deleter(response); + + if (!succeeded) + return false; + + void* iter = NULL; + int value; + + response->ReadBool(&iter, &succeeded); + if (!succeeded) + return false; + response->ReadInt(&iter, &value); + *security_style = static_cast<SecurityStyle>(value); + response->ReadInt(&iter, ssl_cert_status); + response->ReadInt(&iter, mixed_content_state); + + return true; +} + +bool TabProxy::GetPageType(NavigationEntry::PageType* page_type) { + DCHECK(page_type); + + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool is_timeout = false; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_GetPageType(0, handle_), + &response, + AutomationMsg_GetPageTypeResponse::ID, INFINITE, &is_timeout); + scoped_ptr<IPC::Message> auto_deleter(response); + + if (!succeeded) + return false; + + void* iter = NULL; + int value; + response->ReadBool(&iter, &succeeded); + if (!succeeded) + return false; + response->ReadInt(&iter, &value); + *page_type = static_cast<NavigationEntry::PageType>(value); + return true; +} + +bool TabProxy::TakeActionOnSSLBlockingPage(bool proceed) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool is_timeout = false; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_ActionOnSSLBlockingPage(0, handle_, proceed), + &response, + AutomationMsg_ActionOnSSLBlockingPageResponse::ID, INFINITE, &is_timeout); + scoped_ptr<IPC::Message> auto_deleter(response); + + if (!succeeded) + return false; + + void* iter = NULL; + bool status = false; + response->ReadBool(&iter, &status); + + return status; +} + +bool TabProxy::PrintNow() { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_PrintNowRequest(0, handle_), &response, + AutomationMsg_PrintNowResponse::ID); + scoped_ptr<IPC::Message> auto_deleter(response); + if (!succeeded) + return false; + + void* iter = NULL; + succeeded = false; + return response->ReadBool(&iter, &succeeded) && succeeded; +} + +bool TabProxy::SavePage(const std::wstring& file_name, + const std::wstring& dir_path, + SavePackage::SavePackageType type) { + if (!is_valid()) + return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_SavePageRequest(0, handle_, file_name, + dir_path, static_cast<int>(type)), + &response, + AutomationMsg_SavePageResponse::ID); + + if (!succeeded) + return false; + + void* iter = NULL; + response->ReadBool(&iter, &succeeded); + delete response; + + return succeeded; +} diff --git a/chrome/test/automation/tab_proxy.h b/chrome/test/automation/tab_proxy.h new file mode 100644 index 0000000..712ab9c --- /dev/null +++ b/chrome/test/automation/tab_proxy.h @@ -0,0 +1,266 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATION_TAB_PROXY_H__ +#define CHROME_TEST_AUTOMATION_TAB_PROXY_H__ + +#include <wtypes.h> +#include <string> +#include <vector> + +#include "chrome/browser/security_style.h" +#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/save_package.h" +#include "chrome/test/automation/automation_handle_tracker.h" + +class ConstrainedWindowProxy; +class GURL; +class Value; + +typedef enum FindInPageDirection { BACK = 0, FWD = 1 }; +typedef enum FindInPageCase { IGNORE_CASE = 0, CASE_SENSITIVE = 1 }; + +class TabProxy : public AutomationResourceProxy { + public: + TabProxy(AutomationMessageSender* sender, + AutomationHandleTracker* tracker, + int handle) + : AutomationResourceProxy(tracker, sender, handle) {} + + virtual ~TabProxy() {} + + // Gets the current url of the tab. + bool GetCurrentURL(GURL* url) const; + + // Gets the title of the tab. + bool GetTabTitle(std::wstring* title) const; + + // Gets the number of constrained window for this tab. + bool GetConstrainedWindowCount(int* count) const; + + // Gets the proxy object for constrained window within this tab. Ownership + // for the returned object is transfered to the caller. Returns NULL on + // failure. + ConstrainedWindowProxy* GetConstrainedWindow(int window_index) const; + + // Execute a javascript in a frame's context whose xpath + // is provided as the first parameter and extract + // the values from the resulting json string. + // Example: + // jscript = "window.domAutomationController.send('string');" + // will result in value = "string" + // jscript = "window.domAutomationController.send(24);" + // will result in value = 24 + bool ExecuteAndExtractString(const std::wstring& frame_xpath, + const std::wstring& jscript, + std::wstring* value); + bool ExecuteAndExtractBool(const std::wstring& frame_xpath, + const std::wstring& jscript, + bool* value); + bool ExecuteAndExtractInt(const std::wstring& frame_xpath, + const std::wstring& jscript, + int* value); + bool ExecuteAndExtractValue(const std::wstring& frame_xpath, + const std::wstring& jscript, + Value** value); + + // Navigates to a url. This method accepts the same kinds of URL input that + // can be passed to Chrome on the command line. This is a synchronous call and + // hence blocks until the navigation completes. + // Returns a status from AutomationMsg_NavigationResponseValues. + int NavigateToURL(const GURL& url); + + // Navigates to a url. This is same as NavigateToURL with a timeout option. + // The function returns until the navigation completes or timeout (in + // milliseconds) occurs. If return after timeout, is_timeout is set to true. + int NavigateToURLWithTimeout(const GURL& url, uint32 timeout_ms, + bool* is_timeout); + + // Navigates to a url in an externally hosted tab. + // This method accepts the same kinds of URL input that + // can be passed to Chrome on the command line. This is a synchronous call and + // hence blocks until the navigation completes. + // Returns a status from AutomationMsg_NavigationResponseValues. + int NavigateInExternalTab(const GURL& url); + + // Navigates to a url. This is an asynchronous version of NavigateToURL. + // The function returns immediately after sending the LoadURL notification + // to the browser. + // TODO(vibhor): Add a callback if needed in future. + // TODO(mpcomplete): If the navigation results in an auth challenge, the + // TabProxy we attach won't know about it. See bug 666730. + bool NavigateToURLAsync(const GURL& url); + + // Replaces a vector contents with the redirect chain out of the given URL. + // Returns true on success. Failure may be due to being unable to send the + // message, parse the response, or a failure of the history system in the + // browser. + bool GetRedirectsFrom(const GURL& source_url, std::vector<GURL>* redirects); + + // Equivalent to hitting the Back button. This is a synchronous call and + // hence blocks until the navigation completes. + int GoBack(); + + // Equivalent to hitting the Forward button. This is a synchronous call and + // hence blocks until the navigation completes. + // Returns a status from AutomationMsg_NavigationResponseValues. + int GoForward(); + + // Equivalent to hitting the Reload button. This is a synchronous call and + // hence blocks until the navigation completes. + int Reload(); + + // Closes the tab. This is synchronous, but does NOT block until the tab has + // closed, rather it blocks until the browser has initiated the close. Use + // Close(true) if you need to block until tab completely closes. + // + // Note that this proxy is invalid after this call. + bool Close(); + + // Variant of close that allows you to specify whether you want to block + // until the tab has completely closed (wait_until_closed == true) or block + // until the browser has initiated the close (wait_until_closed = false). + // + // When a tab is closed the browser does additional work via invoke later + // and may wait for messages from the renderer. Supplying a value of true to + // this method waits until all processing is done. Be careful with this, + // when closing the last tab it is possible for the browser to shutdown BEFORE + // the tab has completely closed. In other words, this may NOT be sent for + // the last tab. + bool Close(bool wait_until_closed); + + // Gets the HWND that corresponds to the content area of this tab. + // Returns true if the call was successful. + // Returns a status from AutomationMsg_NavigationResponseValues. + bool GetHWND(HWND* hwnd) const; + + // Gets the process ID that corresponds to the content area of this tab. + // Returns true if the call was successful. If the specified tab has no + // separate process for rendering its content, the return value is true but + // the process_id is 0. + bool GetProcessID(int* process_id) const; + + // Supply or cancel authentication to a login prompt. These are synchronous + // calls and hence block until the load finishes (or another login prompt + // appears, in the case of invalid login info). + bool SetAuth(const std::wstring& username, const std::wstring& password); + bool CancelAuth(); + + // Checks if this tab has a login prompt waiting for auth. This will be + // true if a navigation results in a login prompt, and if an attempted login + // fails. + // Note that this is only valid if you've done a navigation on this same + // object; different TabProxy objects can refer to the same Tab. Calls + // that can set this are NavigateToURL, GoBack, and GoForward. + // TODO(mpcomplete): we have no way of knowing if auth is needed after either + // NavigateToURLAsync, or after appending a tab with an URL that triggers + // auth. + bool NeedsAuth() const; + + // Fills |*is_visible| with whether the tab's download shelf is currently + // visible. The return value indicates success. On failure, |*is_visible| is + // unchanged. + bool IsShelfVisible(bool* is_visible); + + // Starts a search within the current tab. The parameter 'search_string' + // specifies what string to search for, 'forward' specifies whether to search + // in forward direction, and 'match_case' specifies case sensitivity + // (true=case sensitive). A return value of -1 indicates failure. + int FindInPage(const std::wstring& search_string, FindInPageDirection forward, + FindInPageCase match_case); + + bool GetCookies(const GURL& url, std::string* cookies); + bool GetCookieByName(const GURL& url, + const std::string& name, + std::string* cookies); + bool SetCookie(const GURL& url, const std::string& value); + + // Sends a InspectElement message for the current tab. |x| and |y| are the + // coordinates that we want to simulate that the user is trying to inspect. + int InspectElement(int x, int y); + + // Block the thread until the constrained(child) window count changes. + // First parameter is the original child window count + // The second parameter is updated with the number of new child windows. + // The third parameter specifies the timeout length for the wait loop. + // Returns false if the count does not change. + bool WaitForChildWindowCountToChange(int count, int* new_count, + int wait_timeout); + + bool GetDownloadDirectory(std::wstring* download_directory); + + // Shows an interstitial page. Blocks until the interstitial page + // has been loaded. Return false if a failure happens.3 + bool ShowInterstitialPage(const std::string& html_text); + + // Hides the currently shown interstitial page. Blocks until the interstitial + // page has been hidden. Return false if a failure happens. + bool HideInterstitialPage(); + + // This sets the keyboard accelerators to be used by an externally + // hosted tab. This call is not valid on a regular tab hosted within + // Chrome. + bool SetAccelerators(HACCEL accel_table, int accel_table_entry_count); + + // The container of an externally hosted tab calls this to reflect any + // accelerator keys that it did not process. This gives the tab a chance + // to handle the keys + bool ProcessUnhandledAccelerator(const MSG& msg); + + bool WaitForTabToBeRestored(); + + // Retrieves the different security states for the current tab. + bool GetSecurityState(SecurityStyle* security_style, + int* ssl_cert_status, + int* mixed_content_state); + + // Returns the type of the page currently showing (normal, interstitial, + // error). + bool GetPageType(NavigationEntry::PageType* page_type); + + // Simulates the user action on the SSL blocking page. if |proceed| is true, + // this is equivalent to clicking the 'Proceed' button, if false to 'Take me + // out of there' button. + bool TakeActionOnSSLBlockingPage(bool proceed); + + // Prints the current page without user intervention. + bool PrintNow(); + + // Save the current web page. |file_name| is the HTML file name, and + // |dir_path| is the directory for saving resource files. |type| indicates + // which type we're saving as: HTML only or the complete web page. + bool SavePage(const std::wstring& file_name, + const std::wstring& dir_path, + SavePackage::SavePackageType type); + + private: + DISALLOW_EVIL_CONSTRUCTORS(TabProxy); +}; + +#endif // CHROME_TEST_AUTOMATION_TAB_PROXY_H__ diff --git a/chrome/test/automation/ui_controls.cc b/chrome/test/automation/ui_controls.cc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/automation/ui_controls.cc diff --git a/chrome/test/automation/ui_controls.h b/chrome/test/automation/ui_controls.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/automation/ui_controls.h diff --git a/chrome/test/automation/window_proxy.cc b/chrome/test/automation/window_proxy.cc new file mode 100644 index 0000000..5f647d2 --- /dev/null +++ b/chrome/test/automation/window_proxy.cc @@ -0,0 +1,187 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/automation/window_proxy.h" + +#include <vector> +#include <algorithm> + +#include "base/gfx/rect.h" +#include "base/logging.h" +#include "chrome/test/automation/automation_constants.h" +#include "chrome/test/automation/automation_messages.h" +#include "chrome/test/automation/automation_proxy.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "googleurl/src/gurl.h" + +bool WindowProxy::GetHWND(HWND* handle) const { + if (!is_valid()) return false; + + if (!handle) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_WindowHWNDRequest(0, handle_), &response, + AutomationMsg_WindowHWNDResponse::ID); + if (!succeeded) + return false; + + HWND hwnd_response; + if (AutomationMsg_WindowHWNDResponse::Read(response, &hwnd_response) && + hwnd_response) { + *handle = hwnd_response; + } else { + succeeded = false; + } + + delete response; + return succeeded; +} + +bool WindowProxy::SimulateOSClick(const POINT& click, int flags) { + if (!is_valid()) return false; + + return sender_->Send( + new AutomationMsg_WindowClickRequest(0, handle_, click, flags)); +} + +bool WindowProxy::SimulateOSKeyPress(wchar_t key, int flags) { + if (!is_valid()) return false; + + return sender_->Send( + new AutomationMsg_WindowKeyPressRequest(0, handle_, key, flags)); +} + +bool WindowProxy::SetVisible(bool visible) { + if (!is_valid()) return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_SetWindowVisibleRequest(0, handle_, visible), + &response, AutomationMsg_SetWindowVisibleResponse::ID); + + scoped_ptr<IPC::Message> response_deleter(response); // Ensure deleted. + if (!succeeded) + return false; + + void* iter = NULL; + if (!response->ReadBool(&iter, &succeeded)) + succeeded = false; + + return succeeded; +} + +bool WindowProxy::IsActive(bool* active) { + if (!is_valid()) return false; + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_IsWindowActiveRequest(0, handle_), + &response, AutomationMsg_IsWindowActiveResponse::ID); + + scoped_ptr<IPC::Message> response_deleter(response); // Ensure deleted. + if (!succeeded) + return false; + + void* iter = NULL; + if (!response->ReadBool(&iter, &succeeded) || !succeeded) + return false; + + if (!response->ReadBool(&iter, active)) + return false; + + return true; +} + +bool WindowProxy::Activate() { + if (!is_valid()) return false; + + return sender_->Send(new AutomationMsg_ActivateWindow(0, handle_)); +} + +bool WindowProxy::GetViewBounds(int view_id, gfx::Rect* bounds, + bool screen_coordinates) { + return GetViewBoundsWithTimeout(view_id, bounds, screen_coordinates, + INFINITE, NULL); +} + +bool WindowProxy::GetViewBoundsWithTimeout(int view_id, gfx::Rect* bounds, + bool screen_coordinates, + uint32 timeout_ms, + bool* is_timeout) { + if (!is_valid()) return false; + + if (!bounds) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponseWithTimeout( + new AutomationMsg_WindowViewBoundsRequest(0, handle_, view_id, + screen_coordinates), + &response, + AutomationMsg_WindowViewBoundsResponse::ID, + timeout_ms, + is_timeout); + if (!succeeded) + return false; + + Tuple2<bool, gfx::Rect> result; + AutomationMsg_WindowViewBoundsResponse::Read(response, &result); + + *bounds = result.b; + return result.a; +} + +bool WindowProxy::GetFocusedViewID(int* view_id) { + if (!is_valid()) return false; + + if (!view_id) { + NOTREACHED(); + return false; + } + + IPC::Message* response = NULL; + bool succeeded = sender_->SendAndWaitForResponse( + new AutomationMsg_GetFocusedViewIDRequest(0, handle_), + &response, + AutomationMsg_GetFocusedViewIDResponse::ID); + + *view_id = -1; + if (succeeded && + AutomationMsg_GetFocusedViewIDResponse::Read(response, view_id)) + return true; + + return false; +}
\ No newline at end of file diff --git a/chrome/test/automation/window_proxy.h b/chrome/test/automation/window_proxy.h new file mode 100644 index 0000000..9fe7740 --- /dev/null +++ b/chrome/test/automation/window_proxy.h @@ -0,0 +1,106 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_AUTOMATION_WINDOW_PROXY_H__ +#define CHROME_TEST_AUTOMATION_WINDOW_PROXY_H__ + +#include <string> +#include "base/thread.h" +#include "chrome/test/automation/automation_handle_tracker.h" + +class GURL; +class BrowserProxy; +class TabProxy; +class WindowProxy; + +namespace gfx { + class Rect; +} + +// This class presents the interface to actions that can be performed on a given +// window. Note that this object can be invalidated at any time if the +// corresponding window in the app is closed. In that case, any subsequent +// calls will return false immediately. +class WindowProxy : public AutomationResourceProxy { + public: + WindowProxy(AutomationMessageSender* sender, + AutomationHandleTracker* tracker, + int handle) + : AutomationResourceProxy(tracker, sender, handle) {} + virtual ~WindowProxy() {} + + // Gets the outermost HWND that corresponds to the given window. + // Returns true if the call was successful. + bool GetHWND(HWND* handle) const; + + // Simulates a click at the OS level. |click| is in the window's coordinates + // and |flags| specifies which buttons are pressed (as defined in + // chrome/views/event.h). Note that this is equivalent to the user moving + // the mouse and pressing the button. So if there is a window on top of this + // window, the top window is clicked. + bool SimulateOSClick(const POINT& click, int flags); + + // Simulates a key press at the OS level. |key| is the key pressed and + // |flags| specifies which modifiers keys are also pressed (as defined in + // chrome/views/event.h). Note that this actually sends the event to the + // window that has focus. + bool SimulateOSKeyPress(wchar_t key, int flags); + + // Shows/hides the window and as a result makes it active/inactive. + // Returns true if the call was successful. + bool SetVisible(bool visible); + + // Sets |active| to true if this view is currently the active window. + // Returns true if the call was successful. + bool IsActive(bool* active); + + // Make this window the active window. + // Returns true if the call was successful. + bool Activate(); + + // Gets the bounds (in window coordinates) that correspond to the view with + // the given ID in this window. Returns true if bounds could be obtained. + // If |screen_coordinates| is true, the bounds are returned in the coordinates + // of the screen, if false in the coordinates of the browser. + bool GetViewBounds(int view_id, gfx::Rect* bounds, bool screen_coordinates); + + // Like GetViewBounds except returns false if timeout occurs before view + // bounds are obtained, and sets is_timeout accordingly. + bool GetViewBoundsWithTimeout(int view_id, gfx::Rect* bounds, + bool screen_coordinates, uint32 timeout_ms, + bool* is_timeout); + // Gets the id of the view that currently has focus. Returns true if the id + // was retrieved. + bool GetFocusedViewID(int* view_id); + + private: + DISALLOW_EVIL_CONSTRUCTORS(WindowProxy); +}; + +#endif // CHROME_TEST_AUTOMATION_WINDOW_PROXY_H__ diff --git a/chrome/test/chrome_plugin/SConscript b/chrome/test/chrome_plugin/SConscript new file mode 100644 index 0000000..af55a6d --- /dev/null +++ b/chrome/test/chrome_plugin/SConscript @@ -0,0 +1,98 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env')
+
+env = env.Clone()
+
+
+env.Prepend(
+ CPPPATH = [
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+
+ '/MANIFEST',
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+
+ '/DEBUG',
+ ],
+ LIBS = [
+ 'winmm.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+#/MANIFESTFILE:"C:\src\trunk-vs\chrome\Debug\obj\test_chrome_plugin\test_chrome_plugin.dll.intermediate.manifest"
+#/PDB:"c:\src\trunk-vs\chrome\Debug\test_chrome_plugin.pdb"
+
+input_files = [
+ 'test_chrome_plugin.cc',
+ 'test_chrome_plugin.def',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$BASE_DIR/base.lib',
+]
+
+dll = env.SharedLibrary('test_chrome_plugin', input_files + libs)
+
+i = env.Install('$TARGET_ROOT', dll)
+env.Alias('chrome', i)
diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.cc b/chrome/test/chrome_plugin/test_chrome_plugin.cc new file mode 100644 index 0000000..3264287 --- /dev/null +++ b/chrome/test/chrome_plugin/test_chrome_plugin.cc @@ -0,0 +1,401 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/chrome_plugin/test_chrome_plugin.h" + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "chrome/common/chrome_plugin_api.h" + +static CPID g_cpid; +static CPBrowserFuncs g_cpbrowser_funcs; +static CPRequestFuncs g_cprequest_funcs; +static CPResponseFuncs g_cpresponse_funcs; +static TestFuncParams::BrowserFuncs g_cptest_funcs; + +const TestResponsePayload* FindPayload(const char* url) { + for (int i = 0; i < arraysize(kChromeTestPluginPayloads); ++i) { + if (strcmp(kChromeTestPluginPayloads[i].url, url) == 0) + return &kChromeTestPluginPayloads[i]; + } + return NULL; +} + +std::string GetPayloadHeaders(const TestResponsePayload* payload) { + return StringPrintf( + "HTTP/1.1 200 OK%c" + "Content-type: %s%c" + "%c", 0, payload->mime_type, 0, 0); +} + +void STDCALL InvokeLaterCallback(void* data) { + Task* task = static_cast<Task*>(data); + task->Run(); + delete task; +} + +// ResponseStream: Manages the streaming of the payload data. + +class ResponseStream : public base::RefCounted<ResponseStream> { +public: + ResponseStream(const TestResponsePayload* payload, CPRequest* request); + ~ResponseStream() { + request_->pdata = NULL; + } + + void Init(); + int GetResponseInfo(CPResponseInfoType type, void* buf, uint32 buf_size); + int ReadData(void* buf, uint32 buf_size); + +private: + // Called asynchronously via InvokeLater. + void ResponseStarted(); + int ReadCompleted(void* buf, uint32 buf_size); + + enum ReadyStates { + READY_INVALID = 0, + READY_WAITING = 1, + READY_GOT_HEADERS = 2, + READY_GOT_DATA = 3, + }; + const TestResponsePayload* payload_; + uint32 offset_; + int ready_state_; + CPRequest* request_; +}; + +ResponseStream::ResponseStream(const TestResponsePayload* payload, + CPRequest* request) + : payload_(payload), offset_(0), request_(request), + ready_state_(READY_INVALID) { +} + +void ResponseStream::Init() { + if (payload_->async) { + // simulate an asynchronous start complete + ready_state_ = READY_WAITING; + g_cptest_funcs.invoke_later( + InvokeLaterCallback, + // downcast to Task before void, since we upcast from void to Task. + static_cast<Task*>( + NewRunnableMethod(this, &ResponseStream::ResponseStarted)), + 500); + } else { + ready_state_ = READY_GOT_DATA; + } +} + +int ResponseStream::GetResponseInfo(CPResponseInfoType type, void* buf, + uint32 buf_size) { + if (ready_state_ < READY_GOT_HEADERS) + return CPERR_FAILURE; + + switch (type) { + case CPRESPONSEINFO_HTTP_STATUS: + if (buf) { + int status = payload_->status; + memcpy(buf, &payload_->status, buf_size); + } + break; + case CPRESPONSEINFO_HTTP_RAW_HEADERS: { + std::string headers = GetPayloadHeaders(payload_); + if (buf_size < headers.size()+1) + return static_cast<int>(headers.size()+1); + if (buf) + memcpy(buf, headers.c_str(), headers.size()+1); + break; + } + default: + return CPERR_INVALID_VERSION; + } + + return CPERR_SUCCESS; +} + +int ResponseStream::ReadData(void* buf, uint32 buf_size) { + if (ready_state_ < READY_GOT_DATA) { + // simulate an asynchronous read complete + g_cptest_funcs.invoke_later( + InvokeLaterCallback, + // downcast to Task before void, since we upcast from void to Task. + static_cast<Task*>( + NewRunnableMethod(this, &ResponseStream::ReadCompleted, + buf, buf_size)), + 500); + return CPERR_IO_PENDING; + } + + // synchronously complete the read + return ReadCompleted(buf, buf_size); +} + +void ResponseStream::ResponseStarted() { + ready_state_ = READY_GOT_HEADERS; + g_cpresponse_funcs.start_completed(request_, CPERR_SUCCESS); +} + +int ResponseStream::ReadCompleted(void* buf, uint32 buf_size) { + uint32 size = static_cast<uint32>(strlen(payload_->body)); + uint32 avail = size - offset_; + uint32 count = buf_size; + if (count > avail) + count = avail; + + if (count) { + memcpy(buf, payload_->body + offset_, count); + } + + offset_ += count; + + if (ready_state_ < READY_GOT_DATA) { + ready_state_ = READY_GOT_DATA; + g_cpresponse_funcs.read_completed(request_, static_cast<int>(count)); + } + + return count; +} + +// CPP Funcs + +CPError STDCALL CPP_Shutdown() { + return CPERR_SUCCESS; +} + +CPBool STDCALL CPP_ShouldInterceptRequest(CPRequest* request) { + DCHECK(StrNCaseCmp(request->url, kChromeTestPluginProtocol, + arraysize(kChromeTestPluginProtocol) - 1) == 0); + return FindPayload(request->url) != NULL; +} + +CPError STDCALL CPR_StartRequest(CPRequest* request) { + const TestResponsePayload* payload = FindPayload(request->url); + DCHECK(payload); + ResponseStream* stream = new ResponseStream(payload, request); + stream->AddRef(); // Released in CPR_EndRequest + stream->Init(); + request->pdata = stream; + return payload->async ? CPERR_IO_PENDING : CPERR_SUCCESS; +} + +void STDCALL CPR_EndRequest(CPRequest* request, CPError reason) { + ResponseStream* stream = static_cast<ResponseStream*>(request->pdata); + request->pdata = NULL; + stream->Release(); // balances AddRef in CPR_StartRequest +} + +void STDCALL CPR_SetExtraRequestHeaders(CPRequest* request, + const char* headers) { + // doesn't affect us +} + +void STDCALL CPR_SetRequestLoadFlags(CPRequest* request, uint32 flags) { + // doesn't affect us +} + +void STDCALL CPR_AppendDataToUpload(CPRequest* request, const char* bytes, + int bytes_len) { + // doesn't affect us +} + +CPError STDCALL CPR_AppendFileToUpload(CPRequest* request, const char* filepath, + uint64 offset, uint64 length) { + // doesn't affect us + return CPERR_FAILURE; +} + +int STDCALL CPR_GetResponseInfo(CPRequest* request, CPResponseInfoType type, + void* buf, uint32 buf_size) { + ResponseStream* stream = static_cast<ResponseStream*>(request->pdata); + return stream->GetResponseInfo(type, buf, buf_size); +} + +int STDCALL CPR_Read(CPRequest* request, void* buf, uint32 buf_size) { + ResponseStream* stream = static_cast<ResponseStream*>(request->pdata); + return stream->ReadData(buf, buf_size); +} + +// RequestResponse: manages the retrieval of response data from the host + +class RequestResponse { +public: + RequestResponse(const std::string& raw_headers) + : raw_headers_(raw_headers), offset_(0) {} + void StartReading(CPRequest* request); + void ReadCompleted(CPRequest* request, int bytes_read); + +private: + std::string raw_headers_; + std::string body_; + int offset_; +}; + +void RequestResponse::StartReading(CPRequest* request) { + int rv = 0; + const uint32 kReadSize = 4096; + do { + body_.resize(offset_ + kReadSize); + rv = g_cprequest_funcs.read(request, &body_[offset_], kReadSize); + if (rv > 0) + offset_ += rv; + } while (rv > 0); + + if (rv != CPERR_IO_PENDING) { + // Either an error occurred, or we are done. + ReadCompleted(request, rv); + } +} + +void RequestResponse::ReadCompleted(CPRequest* request, int bytes_read) { + if (bytes_read > 0) { + offset_ += bytes_read; + StartReading(request); + return; + } + + body_.resize(offset_); + bool success = (bytes_read == 0); + g_cptest_funcs.test_complete(request, success, raw_headers_, body_); + g_cprequest_funcs.end_request(request, CPERR_CANCELLED); + delete this; +} + +void STDCALL CPRR_ReceivedRedirect(CPRequest* request, const char* new_url) { +} + +void STDCALL CPRR_StartCompleted(CPRequest* request, CPError result) { + DCHECK(!request->pdata); + + std::string raw_headers; + int size = g_cprequest_funcs.get_response_info( + request, CPRESPONSEINFO_HTTP_RAW_HEADERS, NULL, 0); + int rv = size < 0 ? size : g_cprequest_funcs.get_response_info( + request, CPRESPONSEINFO_HTTP_RAW_HEADERS, + WriteInto(&raw_headers, size+1), size); + if (rv != CPERR_SUCCESS) { + g_cptest_funcs.test_complete(request, false, std::string(), std::string()); + g_cprequest_funcs.end_request(request, CPERR_CANCELLED); + return; + } + + RequestResponse* response = new RequestResponse(raw_headers); + request->pdata = response; + response->StartReading(request); +} + +void STDCALL CPRR_ReadCompleted(CPRequest* request, int bytes_read) { + RequestResponse* response = + reinterpret_cast<RequestResponse*>(request->pdata); + response->ReadCompleted(request, bytes_read); +} + +int STDCALL CPT_MakeRequest(const char* method, const GURL& url) { + CPRequest* request = NULL; + if (g_cpbrowser_funcs.create_request(g_cpid, NULL, method, url.spec().c_str(), + &request) != CPERR_SUCCESS || + !request) { + return CPERR_FAILURE; + } + + g_cprequest_funcs.set_request_load_flags(request, + CPREQUESTLOAD_DISABLE_INTERCEPT); + + if (strcmp(method, "POST") == 0) { + g_cprequest_funcs.set_extra_request_headers( + request, "Content-Type: text/plain"); + g_cprequest_funcs.append_data_to_upload( + request, kChromeTestPluginPostData, + arraysize(kChromeTestPluginPostData) - 1); + } + + int rv = g_cprequest_funcs.start_request(request); + if (rv == CPERR_SUCCESS) { + CPRR_StartCompleted(request, CPERR_SUCCESS); + } else if (rv != CPERR_IO_PENDING) { + g_cprequest_funcs.end_request(request, CPERR_CANCELLED); + return CPERR_FAILURE; + } + + return CPERR_SUCCESS; +} + +// DLL entry points + +CPError STDCALL CP_Initialize(CPID id, const CPBrowserFuncs* bfuncs, + CPPluginFuncs* pfuncs) { + if (bfuncs == NULL || pfuncs == NULL) + return CPERR_FAILURE; + + if (CP_GET_MAJOR_VERSION(bfuncs->version) > CP_MAJOR_VERSION) + return CPERR_INVALID_VERSION; + + if (bfuncs->size < sizeof(CPBrowserFuncs) || + pfuncs->size < sizeof(CPPluginFuncs)) + return CPERR_INVALID_VERSION; + + pfuncs->version = CP_VERSION; + pfuncs->shutdown = CPP_Shutdown; + pfuncs->should_intercept_request = CPP_ShouldInterceptRequest; + + static CPRequestFuncs request_funcs; + request_funcs.start_request = CPR_StartRequest; + request_funcs.end_request = CPR_EndRequest; + request_funcs.set_extra_request_headers = CPR_SetExtraRequestHeaders; + request_funcs.set_request_load_flags = CPR_SetRequestLoadFlags; + request_funcs.append_data_to_upload = CPR_AppendDataToUpload; + request_funcs.get_response_info = CPR_GetResponseInfo; + request_funcs.read = CPR_Read; + request_funcs.append_file_to_upload = CPR_AppendFileToUpload; + pfuncs->request_funcs = &request_funcs; + + static CPResponseFuncs response_funcs; + response_funcs.received_redirect = CPRR_ReceivedRedirect; + response_funcs.start_completed = CPRR_StartCompleted; + response_funcs.read_completed = CPRR_ReadCompleted; + pfuncs->response_funcs = &response_funcs; + + g_cpid = id; + g_cpbrowser_funcs = *bfuncs; + g_cprequest_funcs = *bfuncs->request_funcs; + g_cpresponse_funcs = *bfuncs->response_funcs; + g_cpbrowser_funcs = *bfuncs; + + const char* protocols[] = {kChromeTestPluginProtocol}; + g_cpbrowser_funcs.enable_request_intercept(g_cpid, protocols, 1); + return CPERR_SUCCESS; +} + +int STDCALL CP_Test(void* vparam) { + TestFuncParams* param = reinterpret_cast<TestFuncParams*>(vparam); + param->pfuncs.test_make_request = CPT_MakeRequest; + + g_cptest_funcs = param->bfuncs; + return CPERR_SUCCESS; +} diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.def b/chrome/test/chrome_plugin/test_chrome_plugin.def new file mode 100644 index 0000000..18a26cb --- /dev/null +++ b/chrome/test/chrome_plugin/test_chrome_plugin.def @@ -0,0 +1,4 @@ +EXPORTS + CP_Initialize @1 + CP_Test @2 + diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.h b/chrome/test/chrome_plugin/test_chrome_plugin.h new file mode 100644 index 0000000..3f3f1c5 --- /dev/null +++ b/chrome/test/chrome_plugin/test_chrome_plugin.h @@ -0,0 +1,92 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Shared by the plugin DLL and the unittest code. + +#ifndef CHROME_TEST_CHROME_PLUGIN_TEST_CHROME_PLUGIN_H__ +#define CHROME_TEST_CHROME_PLUGIN_TEST_CHROME_PLUGIN_H__ + +#include "base/basictypes.h" +#include "chrome/common/chrome_plugin_api.h" +#include "googleurl/src/gurl.h" + +struct TestResponsePayload { + const char* url; + bool async; + int status; + const char* mime_type; + const char* body; +}; + +const char kChromeTestPluginProtocol[] = "cptest"; + +const TestResponsePayload kChromeTestPluginPayloads[] = { + { + "cptest:sync", + false, + 200, + "text/html", + "<head><title>cptest:sync</title></head><body>SUCCESS</body>" + }, + { + "cptest:async", + true, + 200, + "text/plain", + "<head><title>cptest:async</title></head><body>SUCCESS</body>" + }, + { + "cptest:blank", + false, + 200, + "text/plain", + "" + }, +}; + +struct TestFuncParams { + typedef void (STDCALL *CallbackFunc)(void* data); + + struct PluginFuncs { + int (STDCALL *test_make_request)(const char* method, const GURL& url); + }; + PluginFuncs pfuncs; + + struct BrowserFuncs { + void (STDCALL *test_complete)(CPRequest* request, bool success, + const std::string& raw_headers, + const std::string& body); + void (STDCALL *invoke_later)(CallbackFunc callback, void* callback_data, + int delay_ms); + }; + BrowserFuncs bfuncs; +}; + +const char kChromeTestPluginPostData[] = "Test Data"; + +#endif // CHROME_TEST_CHROME_PLUGIN_TEST_CHROME_PLUGIN_H__ diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.vcproj b/chrome/test/chrome_plugin/test_chrome_plugin.vcproj new file mode 100644 index 0000000..243c494 --- /dev/null +++ b/chrome/test/chrome_plugin/test_chrome_plugin.vcproj @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="test_chrome_plugin" + ProjectGUID="{7F0A70F6-BE3F-4C19-B435-956AB8F30BA4}" + RootNamespace="startup_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="2" + InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\test_chrome_plugin.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="2" + InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\test_chrome_plugin.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath=".\test_chrome_plugin.cc" + > + </File> + <File + RelativePath=".\test_chrome_plugin.def" + > + </File> + <File + RelativePath=".\test_chrome_plugin.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/chrome_plugin/test_chrome_plugin.vsprops b/chrome/test/chrome_plugin/test_chrome_plugin.vsprops new file mode 100644 index 0000000..d3d0829 --- /dev/null +++ b/chrome/test/chrome_plugin/test_chrome_plugin.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="test_chrome_plugin" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops" + > + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + ModuleDefinitionFile="test_chrome_plugin.def" + /> +</VisualStudioPropertySheet> diff --git a/chrome/test/data/animate1.gif b/chrome/test/data/animate1.gif Binary files differnew file mode 100644 index 0000000..2de64b0 --- /dev/null +++ b/chrome/test/data/animate1.gif diff --git a/chrome/test/data/animate2.gif b/chrome/test/data/animate2.gif Binary files differnew file mode 100644 index 0000000..2a4233d --- /dev/null +++ b/chrome/test/data/animate2.gif diff --git a/chrome/test/data/animate3.gif b/chrome/test/data/animate3.gif Binary files differnew file mode 100644 index 0000000..21f9c05 --- /dev/null +++ b/chrome/test/data/animate3.gif diff --git a/chrome/test/data/animated-gifs.html b/chrome/test/data/animated-gifs.html new file mode 100644 index 0000000..98b2f1c --- /dev/null +++ b/chrome/test/data/animated-gifs.html @@ -0,0 +1,8 @@ +<html> +<head><title>animated gif test</title></head> +<body> +<img src="animate1.gif"> +<img src="animate2.gif"> +<img src="animate3.gif"> +</body> +</html> diff --git a/chrome/test/data/cancelled_redirect_test.html b/chrome/test/data/cancelled_redirect_test.html new file mode 100644 index 0000000..633db40 --- /dev/null +++ b/chrome/test/data/cancelled_redirect_test.html @@ -0,0 +1,28 @@ +<!--Test file for ClientCancelled redirect_uitest. This tests that a location change when a pending +client redirect exists (in this case a meta-refresh) isn't flagged as a client redirect. The timeout +for the meta-refresh is large so that it can't happen during this test; we just want it to be scheduled. +We can't use a body onload to do the location change, because this will end up firing before the +meta-refresh timer is scheduled, so we use a non-zero timeout of 1msec for this. --> +<html> + <head> + <meta http-equiv="refresh" content="20000"> + <script> + // Function to simulate a user clicking on the button, so + // the anchor navigation is not flagged as a redirect. + function clickButton() { + var node = document.getElementById("mybutton"); + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, + false, false, false, false, 0, null); + node.dispatchEvent(evt) + } + function changeLocAfterTimeout() { + setTimeout("clickButton()", 1); + } + </script> + </head> + <body onload="changeLocAfterTimeout()"> + <input type="button" id="mybutton" onclick="document.location='#myanchor'"/> + <a name="myanchor">Anchor</a><br/> + </body> +</html> diff --git a/chrome/test/data/columns.html b/chrome/test/data/columns.html new file mode 100644 index 0000000..84b688d --- /dev/null +++ b/chrome/test/data/columns.html @@ -0,0 +1,23 @@ +<html><head><title>Column test</title></head><body> +<h1>Column test</h1> + +<p>This tests that we do multi-column layout and don't crash. The issue is +that WebKit creates a NULL platform graphics context pointer, and expects +GraphicsContext to work with it, disabling paint.</p> + +<div style="border: 2px solid rgb(34, 136, 17); -webkit-column-count: 2; +-moz-column-count: 2; -webkit-column-rule: 2px solid rgb(34, 136, 17); +-moz-column-rule: 4px solid rgb(34, 136, 17)">WebKit now has some very basic +support for multiple columns from CSS3. In fact, if you’re reading this +blog entry, you will see that it has been broken up into two columns in the +latest WebKit nightly and in Firefox.<br /> + +<div style="margin: 1em 0">The properties supported at this time are columns, +column-gap, column-count and column-width. Column rules are not yet supported +and neither are column breaks.</div> At this time any stacking context children +like relative positioned content or content that uses opacity will position +impoperly (as though the column didn’t exist. If you decide to use this +feature, watch out for that.<br /> <div style="margin-top:1em"><b>Update</b>: +Column rules are now supported. This blog entry now has one!</div> + +</body></html> diff --git a/chrome/test/data/constrained_files/constrained_window.html b/chrome/test/data/constrained_files/constrained_window.html new file mode 100644 index 0000000..1f4810a --- /dev/null +++ b/chrome/test/data/constrained_files/constrained_window.html @@ -0,0 +1,17 @@ +<HTML> + <HEAD> + <TITLE> + Parent Window + </TITLE> +<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript"> +<!-- Begin +function enter(url, x, y) { + window.open(url,'','height=320,width=300,left='+x+',top='+y); +} +// End --> +</SCRIPT> + + <BODY + onload="enter('target0.html', 10, 10); enter('target1.html', 100, 100)"> + </BODY> + </HTML> diff --git a/chrome/test/data/constrained_files/constrained_window_onload_moveto.html b/chrome/test/data/constrained_files/constrained_window_onload_moveto.html new file mode 100644 index 0000000..9da3aa6 --- /dev/null +++ b/chrome/test/data/constrained_files/constrained_window_onload_moveto.html @@ -0,0 +1,17 @@ +<HTML> + <HEAD> + <TITLE> + Parent Window + </TITLE> +<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript"> +<!-- Begin +function enter(url, x, y) { + window.open(url,'','height=320,width=300,left='+x+',top='+y); +} +// End --> +</SCRIPT> + + <BODY + onload="enter('target_onload_moveto.html', 100, 100);"> + </BODY> + </HTML> diff --git a/chrome/test/data/constrained_files/constrained_window_onload_resizeto.html b/chrome/test/data/constrained_files/constrained_window_onload_resizeto.html new file mode 100644 index 0000000..e1990f3 --- /dev/null +++ b/chrome/test/data/constrained_files/constrained_window_onload_resizeto.html @@ -0,0 +1,17 @@ +<HTML> + <HEAD> + <TITLE> + Parent Window + </TITLE> +<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript"> +<!-- Begin +function enter(url, x, y) { + window.open(url,'','height=320,width=300,left='+x+',top='+y); +} +// End --> +</SCRIPT> + + <BODY onClick="enter('target_onload_resizeto.html', 100, 100);"> + + </BODY> +</HTML> diff --git a/chrome/test/data/constrained_files/target0.html b/chrome/test/data/constrained_files/target0.html new file mode 100644 index 0000000..8185d9d --- /dev/null +++ b/chrome/test/data/constrained_files/target0.html @@ -0,0 +1,8 @@ +<HTML> + <HEAD> + <TITLE> Constrained Window 0 </TITLE> + </HEAD> + <BODY> + This page should be used to pop up a constrained window. + </BODY> +</HTML> diff --git a/chrome/test/data/constrained_files/target1.html b/chrome/test/data/constrained_files/target1.html new file mode 100644 index 0000000..d4c2dba --- /dev/null +++ b/chrome/test/data/constrained_files/target1.html @@ -0,0 +1,6 @@ + +<HTML> + <HEAD> + <TITLE> Constrained Window 1 </TITLE> + </HEAD> +</HTML> diff --git a/chrome/test/data/constrained_files/target_onload_moveto.html b/chrome/test/data/constrained_files/target_onload_moveto.html new file mode 100644 index 0000000..02ade91 --- /dev/null +++ b/chrome/test/data/constrained_files/target_onload_moveto.html @@ -0,0 +1,8 @@ +<HTML> + <HEAD> + <TITLE> window.moveTo() Test </TITLE> + </HEAD> + <BODY onLoad="window.opener.focus(); window.moveTo(20, 20);"> + This page shouldn't be able to force its own display by moving itself after creation. + </BODY> +</HTML> diff --git a/chrome/test/data/constrained_files/target_onload_resizeto.html b/chrome/test/data/constrained_files/target_onload_resizeto.html new file mode 100644 index 0000000..e19f144 --- /dev/null +++ b/chrome/test/data/constrained_files/target_onload_resizeto.html @@ -0,0 +1,9 @@ +<HTML> + <HEAD> + <TITLE> window.resizeTo() Test </TITLE> + </HEAD> + <BODY onClick="window.opener.focus(); window.resizeTo(200, 200);"> + This page's content bounds should start at 320, 300 because that's hat it was opeend with. + After click, the window's bounds should be equal to 200, 200 and the content bounds smaller then that. + </BODY> +</HTML> diff --git a/chrome/test/data/content-disposition-empty.html b/chrome/test/data/content-disposition-empty.html new file mode 100644 index 0000000..7dd9c0f --- /dev/null +++ b/chrome/test/data/content-disposition-empty.html @@ -0,0 +1,4 @@ +<html> +<head><title>success</title></head> +<body>this page should be displayed instead of downloaded</body> +</html> diff --git a/chrome/test/data/content-disposition-empty.html.mock-http-headers b/chrome/test/data/content-disposition-empty.html.mock-http-headers new file mode 100644 index 0000000..1d114d5 --- /dev/null +++ b/chrome/test/data/content-disposition-empty.html.mock-http-headers @@ -0,0 +1,6 @@ +HTTP/1.1 200 OK +Content-Type: text/html +Content-Length: 116 +Content-Disposition: filename="foo.html" +Date: Mon, 13 Nov 2006 21:38:09 GMT +Expires: Tue, 14 Nov 2006 19:23:58 GMT diff --git a/chrome/test/data/content-disposition-inline.html b/chrome/test/data/content-disposition-inline.html new file mode 100644 index 0000000..7dd9c0f --- /dev/null +++ b/chrome/test/data/content-disposition-inline.html @@ -0,0 +1,4 @@ +<html> +<head><title>success</title></head> +<body>this page should be displayed instead of downloaded</body> +</html> diff --git a/chrome/test/data/content-disposition-inline.html.mock-http-headers b/chrome/test/data/content-disposition-inline.html.mock-http-headers new file mode 100644 index 0000000..6846a51 --- /dev/null +++ b/chrome/test/data/content-disposition-inline.html.mock-http-headers @@ -0,0 +1,6 @@ +HTTP/1.1 200 OK +Content-Type: text/html +Content-Length: 116 +Content-Disposition: inline; filename="foo.html" +Date: Mon, 13 Nov 2006 21:38:09 GMT +Expires: Tue, 14 Nov 2006 19:23:58 GMT diff --git a/chrome/test/data/content-sniffer-test0.html b/chrome/test/data/content-sniffer-test0.html new file mode 100644 index 0000000..597a51b --- /dev/null +++ b/chrome/test/data/content-sniffer-test0.html @@ -0,0 +1,4 @@ +<html> +<head><title>Content Sniffer Test 0</title></head> +<body>We should sniff this content as HTML.</body> +</html> diff --git a/chrome/test/data/content-sniffer-test0.html.mock-http-headers b/chrome/test/data/content-sniffer-test0.html.mock-http-headers new file mode 100644 index 0000000..0e1e649 --- /dev/null +++ b/chrome/test/data/content-sniffer-test0.html.mock-http-headers @@ -0,0 +1,4 @@ +HTTP/1.1 200 OK +Content-Length: 121 +Date: Mon, 13 Nov 2006 21:38:09 GMT +Expires: Tue, 14 Nov 2006 19:23:58 GMT diff --git a/chrome/test/data/content-sniffer-test1.html b/chrome/test/data/content-sniffer-test1.html new file mode 100644 index 0000000..c3bfc9b --- /dev/null +++ b/chrome/test/data/content-sniffer-test1.html @@ -0,0 +1,4 @@ +<html> +<head><title>Content Sniffer Test 1</title></head> +<body>We should not sniff this content as HTML.</body> +</html> diff --git a/chrome/test/data/content-sniffer-test1.html.mock-http-headers b/chrome/test/data/content-sniffer-test1.html.mock-http-headers new file mode 100644 index 0000000..bbc82cdf --- /dev/null +++ b/chrome/test/data/content-sniffer-test1.html.mock-http-headers @@ -0,0 +1,5 @@ +HTTP/1.1 200 OK +Content-Type: text/plain; charset=utf-8 +Content-Length: 125 +Date: Mon, 13 Nov 2006 21:38:09 GMT +Expires: Tue, 14 Nov 2006 19:23:58 GMT diff --git a/chrome/test/data/content-sniffer-test2.html b/chrome/test/data/content-sniffer-test2.html new file mode 100644 index 0000000..c4b99f8 --- /dev/null +++ b/chrome/test/data/content-sniffer-test2.html @@ -0,0 +1,4 @@ +<html> +<head><title>Content Sniffer Test 2</title></head> +<body>We should not sniff this as HTML as server says its a GIF.</body> +</html> diff --git a/chrome/test/data/content-sniffer-test2.html.mock-http-headers b/chrome/test/data/content-sniffer-test2.html.mock-http-headers new file mode 100644 index 0000000..081626d --- /dev/null +++ b/chrome/test/data/content-sniffer-test2.html.mock-http-headers @@ -0,0 +1,5 @@ +HTTP/1.1 200 OK +Content-Type: image/gif +Content-Length: 142 +Date: Mon, 13 Nov 2006 21:38:09 GMT +Expires: Tue, 14 Nov 2006 19:23:58 GMT diff --git a/chrome/test/data/content-sniffer-test3-frame.txt b/chrome/test/data/content-sniffer-test3-frame.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/content-sniffer-test3-frame.txt diff --git a/chrome/test/data/content-sniffer-test3-frame.txt.mock-http-headers b/chrome/test/data/content-sniffer-test3-frame.txt.mock-http-headers new file mode 100644 index 0000000..7ad4001 --- /dev/null +++ b/chrome/test/data/content-sniffer-test3-frame.txt.mock-http-headers @@ -0,0 +1,3 @@ +HTTP/1.1 200 OK +Content-Length: 0 +Date: Tue, 22 Apr 2008 22:56:55 GMT diff --git a/chrome/test/data/content-sniffer-test3.html b/chrome/test/data/content-sniffer-test3.html new file mode 100644 index 0000000..67046e8 --- /dev/null +++ b/chrome/test/data/content-sniffer-test3.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> +<title>Content Sniffer Test 3</title> +</head> +<body> +<script id="sc"> +var iframe = document.createElement('iframe'); +iframe.frameBorder = iframe.width = iframe.height = 0; +iframe.src = "http://mock.http/content-sniffer-test3-frame.txt"; +document.body.appendChild(iframe); +</script> +<pre>Do NOT download!!</pre> +</body> +</html>
\ No newline at end of file diff --git a/chrome/test/data/content-sniffer-test3.html.mock-http-headers b/chrome/test/data/content-sniffer-test3.html.mock-http-headers new file mode 100644 index 0000000..a2e08d5 --- /dev/null +++ b/chrome/test/data/content-sniffer-test3.html.mock-http-headers @@ -0,0 +1,5 @@ +HTTP/1.1 200 OK +Content-Length: 487 +Date: Tue, 22 Apr 2008 22:56:55 GMT +Content-Length: 333 +Content-Type: text/html diff --git a/chrome/test/data/cookie1.html b/chrome/test/data/cookie1.html new file mode 100644 index 0000000..3c7dccf --- /dev/null +++ b/chrome/test/data/cookie1.html @@ -0,0 +1,11 @@ +<html> +<head> +<script> +function setCookie() { + document.cookie = 'foo=baz'; +} +</script> +</head> +<body onload="setCookie();"> +</body> +</html> diff --git a/chrome/test/data/download-test1.lib b/chrome/test/data/download-test1.lib Binary files differnew file mode 100644 index 0000000..9d22027 --- /dev/null +++ b/chrome/test/data/download-test1.lib diff --git a/chrome/test/data/download-test1.lib.mock-http-headers b/chrome/test/data/download-test1.lib.mock-http-headers new file mode 100644 index 0000000..63aef68 --- /dev/null +++ b/chrome/test/data/download-test1.lib.mock-http-headers @@ -0,0 +1,5 @@ +HTTP/1.1 200 OK +Content-Type: application/octet-stream; charset=utf-8 +Content-Length: 271920 +Date: Mon, 13 Nov 2006 21:38:09 GMT +Expires: Tue, 14 Nov 2006 19:23:58 GMT diff --git a/chrome/test/data/download-test2.html b/chrome/test/data/download-test2.html new file mode 100644 index 0000000..1a6714e --- /dev/null +++ b/chrome/test/data/download-test2.html @@ -0,0 +1,4 @@ +<html> +<head><title>Download Test #2</title></head> +<body>This file should not actually download.</body> +</html> diff --git a/chrome/test/data/download-test2.html.mock-http-headers b/chrome/test/data/download-test2.html.mock-http-headers new file mode 100644 index 0000000..fa7ff58 --- /dev/null +++ b/chrome/test/data/download-test2.html.mock-http-headers @@ -0,0 +1,5 @@ +HTTP/1.1 200 OK +Content-Type: text/html; charset=utf-8 +Content-Length: 113 +Date: Mon, 13 Nov 2006 21:38:09 GMT +Expires: Tue, 14 Nov 2006 19:23:58 GMT diff --git a/chrome/test/data/download-test3.html b/chrome/test/data/download-test3.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/download-test3.html diff --git a/chrome/test/data/download-test3.html.mock-http-headers b/chrome/test/data/download-test3.html.mock-http-headers new file mode 100644 index 0000000..3a2e781 --- /dev/null +++ b/chrome/test/data/download-test3.html.mock-http-headers @@ -0,0 +1,6 @@ +HTTP/1.1 200 OK +Content-Type: text/html; charset=utf-8 +Content-Disposition: attachment; filename="download-test3-attachment.html" +Content-Length: 0 +Date: Mon, 13 Nov 2006 21:38:09 GMT +Expires: Tue, 14 Nov 2006 19:23:58 GMT diff --git a/chrome/test/data/empty.html b/chrome/test/data/empty.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/empty.html diff --git a/chrome/test/data/file_client_redirect.html b/chrome/test/data/file_client_redirect.html new file mode 100644 index 0000000..61dc261 --- /dev/null +++ b/chrome/test/data/file_client_redirect.html @@ -0,0 +1,8 @@ +<!-- +Test file for empty referrer client redirects, e.g https>http, file>http. +See ClientEmptyReferrerRedirectTest in redirect_uitest.cc +--> +<html> +<head></head> +<body onload="document.location='http://localhost:1337'"></body> +</html> diff --git a/chrome/test/data/find_in_page/framedata_general.html b/chrome/test/data/find_in_page/framedata_general.html new file mode 100644 index 0000000..8e8a82d --- /dev/null +++ b/chrome/test/data/find_in_page/framedata_general.html @@ -0,0 +1,13 @@ +<html> +<head> +<title>Frames</title> +</head> + +<body> + +horse <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +goat<br> +goat<br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<input type="text"/> +</body> +</html>
\ No newline at end of file diff --git a/chrome/test/data/find_in_page/framedata_left.html b/chrome/test/data/find_in_page/framedata_left.html new file mode 100644 index 0000000..794c6cf --- /dev/null +++ b/chrome/test/data/find_in_page/framedata_left.html @@ -0,0 +1,21 @@ +<html> +<head> +<title>Frames</title> +</head> + +<body> + +cat <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +dog <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<input type="text" value="text in box"><br> + +g <br> +go <br> +goo <br> +google <br> +goog <br> +googl <br> +<br> +Hreggviður +</body> +</html>
\ No newline at end of file diff --git a/chrome/test/data/find_in_page/frames.html b/chrome/test/data/find_in_page/frames.html new file mode 100644 index 0000000..f89c6e5 --- /dev/null +++ b/chrome/test/data/find_in_page/frames.html @@ -0,0 +1,12 @@ +<html> + +<frameset cols="25%,25%,25%,25%"> + + <frame src="framedata_left.html"> + <frame src="framedata_general.html"> + <frame src="framedata_general.html"> + <frame src="framedata_general.html"> + +</frameset> + +</html> diff --git a/chrome/test/data/find_in_page/user-select.html b/chrome/test/data/find_in_page/user-select.html new file mode 100644 index 0000000..fccceb4 --- /dev/null +++ b/chrome/test/data/find_in_page/user-select.html @@ -0,0 +1,6 @@ +<html><head></head> +<body style="-webkit-user-select: none;"> +This is some un-selectable text. Try finding a character in it +and verify that we don't crash. +</body> +</html> diff --git a/chrome/test/data/firefox2_nss/README b/chrome/test/data/firefox2_nss/README new file mode 100644 index 0000000..745832e --- /dev/null +++ b/chrome/test/data/firefox2_nss/README @@ -0,0 +1,7 @@ +The NSPR and NSS DLLs in this directory (freebl3.dll, nspr4.dll, nss3.dll, +plc4.dll, plds4.dll, and softokn3.dll) come from the Firefox 2.0.0.x +distribution for Windows. + +The source code of NSPR and NSS, which you may use, modify, and distribute, is +available to you free-of-charge from www.mozilla.org under the Mozilla Public +License and other open source software licenses. diff --git a/chrome/test/data/firefox2_nss/freebl3.dll b/chrome/test/data/firefox2_nss/freebl3.dll Binary files differnew file mode 100644 index 0000000..6e562d8 --- /dev/null +++ b/chrome/test/data/firefox2_nss/freebl3.dll diff --git a/chrome/test/data/firefox2_nss/nspr4.dll b/chrome/test/data/firefox2_nss/nspr4.dll Binary files differnew file mode 100644 index 0000000..5ff4cc5 --- /dev/null +++ b/chrome/test/data/firefox2_nss/nspr4.dll diff --git a/chrome/test/data/firefox2_nss/nss3.dll b/chrome/test/data/firefox2_nss/nss3.dll Binary files differnew file mode 100644 index 0000000..c7d0546 --- /dev/null +++ b/chrome/test/data/firefox2_nss/nss3.dll diff --git a/chrome/test/data/firefox2_nss/plc4.dll b/chrome/test/data/firefox2_nss/plc4.dll Binary files differnew file mode 100644 index 0000000..c4492c8 --- /dev/null +++ b/chrome/test/data/firefox2_nss/plc4.dll diff --git a/chrome/test/data/firefox2_nss/plds4.dll b/chrome/test/data/firefox2_nss/plds4.dll Binary files differnew file mode 100644 index 0000000..e10c683 --- /dev/null +++ b/chrome/test/data/firefox2_nss/plds4.dll diff --git a/chrome/test/data/firefox2_nss/softokn3.dll b/chrome/test/data/firefox2_nss/softokn3.dll Binary files differnew file mode 100644 index 0000000..159957c --- /dev/null +++ b/chrome/test/data/firefox2_nss/softokn3.dll diff --git a/chrome/test/data/firefox2_profile/bookmarks.html b/chrome/test/data/firefox2_profile/bookmarks.html new file mode 100644 index 0000000..84020ad --- /dev/null +++ b/chrome/test/data/firefox2_profile/bookmarks.html @@ -0,0 +1,37 @@ +<!DOCTYPE NETSCAPE-Bookmark-file-1> +<!-- This is an automatically generated file. + It will be read and overwritten. + DO NOT EDIT! --> +<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> +<TITLE>Bookmarks</TITLE> +<H1 LAST_MODIFIED="1206681701">Bookmarks</H1> + +<DL><p> + <DT><H3 LAST_MODIFIED="1206681655" PERSONAL_TOOLBAR_FOLDER="true" ID="rdf:#$FvPhC3">Bookmarks Toolbar Folder</H3> +<DD>Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar + <DL><p> + <DT><H3 ADD_DATE="1206681467" LAST_MODIFIED="1206681524" ID="rdf:#$F2zO.2">Folder</H3> +<DD>This folder will be displayed on toolbar. + <DL><p> + <DT><A HREF="http://on.toolbar/bookmark/folder" ADD_DATE="1206681362" LAST_MODIFIED="1206681414" ID="rdf:#$E2zO.2">On Toolbar's Subfolder</A> + </DL><p> + <DT><A HREF="http://on.toolbar/bookmark" ADD_DATE="1206681362" LAST_MODIFIED="1206681414" ID="rdf:#$E2zO.2">On Bookmark Toolbar</A> + </DL><p> + <HR> + <DT><H3 ADD_DATE="1206681467" LAST_MODIFIED="1206681701" ID="rdf:#$H2zO.2">Folder</H3> + <DL><p> + <DT><A HREF="http://domain/" ADD_DATE="1206681681" LAST_MODIFIED="1206681699" ID="rdf:#$I2zO.2">New Bookmark</A> + </DL><p> + <DT><A HREF="http://domain.com/q?a=%22er%22&b=< >" ADD_DATE="1205904876" LAST_MODIFIED="1206681294" ID="rdf:#$3XrQI1"><Name></A> + <DT><A HREF="http://www.google.com/" ADD_DATE="1206681298" LAST_MODIFIED="1206681734" SHORTCUTURL="google" WEB_PANEL="true" ID="rdf:#$D2zO.2">Google Home Page</A> +<DD>Google Home Page + <DT><A HREF="http://chinese.site.cn/path?query=1#ref" ADD_DATE="1206681555" LAST_MODIFIED="1206681598" ID="rdf:#$G2zO.2">中文</A> + <DT><H3 ADD_DATE="1207558707" LAST_MODIFIED="1207558746" ID="rdf:#$guhL42">< > & " ' \ /</H3> +<DD>< > & " ' \ / + <DL><p> + <DT><A HREF="http://g.cn/" ADD_DATE="1207558728" LAST_MODIFIED="1207558736" SHORTCUTURL="< > & " ' \ /" ID="rdf:#$huhL42">< > & " ' \ /</A> +<DD>< > & " ' \ / + </DL><p> + <DT><A HREF="http://localhost:8080/test/hello.html" ADD_DATE="1212447159" LAST_VISIT="1212447251" LAST_MODIFIED="1212447248" SHORTCUTURL="post" ICON="data:" POST_DATA="lname%3D%25s" LAST_CHARSET="UTF-8" ID="rdf:#$weKaR3">Test Post keyword</A> + <DT><A HREF="mailto:username@host" ADD_DATE="1213257065" LAST_MODIFIED="1213257105" ID="rdf:#$U8bjH1">mail</A> +</DL><p> diff --git a/chrome/test/data/firefox2_profile/cert8.db b/chrome/test/data/firefox2_profile/cert8.db Binary files differnew file mode 100644 index 0000000..ac40a33 --- /dev/null +++ b/chrome/test/data/firefox2_profile/cert8.db diff --git a/chrome/test/data/firefox2_profile/cookies.txt b/chrome/test/data/firefox2_profile/cookies.txt new file mode 100644 index 0000000..2a7249f --- /dev/null +++ b/chrome/test/data/firefox2_profile/cookies.txt @@ -0,0 +1,10 @@ +# HTTP Cookie File +# http://www.netscape.com/newsref/std/cookie_spec.html +# This is a generated file! Do not edit. +# To delete cookies, use the Cookie Manager. + +www.google.com FALSE /calendar/ FALSE 1237629519 S dasher_cpanel=sRewracv:calendar=_9TWj_US +.domain TRUE /path/sub_path/ FALSE 1221083160 name value +#HttpOnly_.en.site.com TRUE / FALSE 1269432000 KEY KEY=KEY +.~~local~~ TRUE /C:/code-chrome-new/data/page_cycler/intl1/fc2.com/ FALSE 1490482342 cnt_7081_nv 1 + FALSE /C:/Documents%20and%20Settings/filecookie/ FALSE 1211314466 AAA2 ZZZZZZZZZZZZ diff --git a/chrome/test/data/firefox2_profile/history.dat b/chrome/test/data/firefox2_profile/history.dat new file mode 100644 index 0000000..b2f6a83 --- /dev/null +++ b/chrome/test/data/firefox2_profile/history.dat @@ -0,0 +1,16 @@ +// <!-- <mdb:mork:z v="1.4"/> -->
+< <(a=c)> // (f=iso-8859-1)
+ (8A=Typed)(8B=LastPageVisited)(8C=ByteOrder)
+ (80=ns:history:db:row:scope:history:all)
+ (81=ns:history:db:table:kind:history)(82=URL)(83=Referrer)
+ (84=LastVisitDate)(85=FirstVisitDate)(86=VisitCount)(87=Name)
+ (88=Hostname)(89=Hidden)>
+
+<(80=LE)(81=http://en-us.www.mozilla.com/)
+ (82=1205364946314923)(83=en-us.www.mozilla.com)(84
+ =F$00i$00r$00e$00f$00o$00x$00 $00U$00p$00d$00a$00t$00e$00d$00)>
+{1:^80 {(k^81:c)(s=9)[1(^8C=LE)]}
+ [2(^82^81)(^84^82)(^85^82)(^88^83)(^87^84)]}
+
+@$${2{@
+@$$}2}@
\ No newline at end of file diff --git a/chrome/test/data/firefox2_profile/key3.db b/chrome/test/data/firefox2_profile/key3.db Binary files differnew file mode 100644 index 0000000..2e3b9f4 --- /dev/null +++ b/chrome/test/data/firefox2_profile/key3.db diff --git a/chrome/test/data/firefox2_profile/prefs.js b/chrome/test/data/firefox2_profile/prefs.js new file mode 100644 index 0000000..1ed35e3 --- /dev/null +++ b/chrome/test/data/firefox2_profile/prefs.js @@ -0,0 +1,209 @@ +# Mozilla User Preferences + +/* Do not edit this file. + * + * If you make changes to this file while the application is running, + * the changes will be overwritten when the application exits. + * + * To make a manual change to preferences, you can visit the URL about:config + * For more information, see http://www.mozilla.org/unix/customizing.html#prefs + */ + +user_pref("accessibility.typeaheadfind.flashBar", 0); +user_pref("app.update.lastUpdateTime.addon-background-update-timer", 1210196026); +user_pref("app.update.lastUpdateTime.background-update-timer", 1210196626); +user_pref("app.update.lastUpdateTime.blocklist-background-update-timer", 1210194826); +user_pref("app.update.lastUpdateTime.microsummary-generator-update-timer", 1196114739); +user_pref("app.update.lastUpdateTime.restart-nag-timer", 1208477359); +user_pref("app.update.lastUpdateTime.search-engine-update-timer", 1210227671); +user_pref("browser.download.dir", "C:\\Downloads"); +user_pref("browser.download.downloadDir", "C:\\Downloads"); +user_pref("browser.download.folderList", 2); +user_pref("browser.download.lastDir", "C:\\Documents and Settings\\jcampan\\Desktop"); +user_pref("browser.download.manager.alertOnEXEOpen", true); +user_pref("browser.download.manager.showWhenStarting", false); +user_pref("browser.download.save_converter_index", 0); +user_pref("browser.feeds.showFirstRunUI", false); +user_pref("browser.history_expire_days.mirror", 9); +user_pref("browser.migration.version", 1); +user_pref("browser.places.createdDefaultQueries", true); +user_pref("browser.places.createdSmartBookmarks", true); +user_pref("browser.places.importBookmarksHTML", false); +user_pref("browser.places.importDefaults", false); +user_pref("browser.places.migratePostDataAnnotations", false); +user_pref("browser.places.updateRecentTagsUri", false); +user_pref("browser.preferences.advanced.selectedTabIndex", 0); +user_pref("browser.preferences.privacy.selectedTabIndex", 0); +user_pref("browser.search.defaultenginename", "Google"); +user_pref("browser.search.defaulturl", "http://www.google.com/search?lr=&ie=UTF-8&oe=UTF-8&q="); +user_pref("browser.search.selectedEngine", "Webster"); +user_pref("browser.search.useDBForOrder", true); +user_pref("browser.shell.checkDefaultBrowser", false); +user_pref("browser.startup.homepage", "http://www.google.com/"); +user_pref("browser.startup.homepage_override.mstone", "rv:1.9b5"); +user_pref("browser.startup.page", 3); +user_pref("extensions.adblockplus.checkedadblockinstalled", true); +user_pref("extensions.adblockplus.checkedtoolbar", true); +user_pref("extensions.adblockplus.showsubscriptions", false); +user_pref("extensions.enabledItems", "{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}:0.7.5.4,{77b819fa-95ad-4f2c-ac7c-486b356188a9}:1.5.20080310,{c45c406e-ab73-11d8-be73-000a95be3b12}:1.1.5,{972ce4c6-7e08-4474-a285-3208198ce6fd}:2.0"); +user_pref("extensions.lastAppVersion", "3.0b5"); +user_pref("extensions.piclens.InstanceId", "8A6zSIlUX0q0VBf/iJvL/Q=="); +user_pref("extensions.piclens.UpdateInfo", "H4sIAAAAAAAAC+1WwWoCMRT8m1wqZbVQ6GEPVtqTgtTFHmQPcTN1g9mk5GXd+vdNdkWqYi+lUkvY20xe3rzMDjxyxkLMHHc0hyVpdHrPqHmBFrCwgagpHTBdV2Ne66IEpQkjD09hpQmV1mWyQtq/HfSTwR1ukuSBOeO4mspiDE0tm4QbJkYgs1yTdL4RdeBQZGVdLUdKFusdNCu5xTMglrxYfyWeNF8qnBzdNdrjBG6D0sdttn1Hukh6B1/O8CGdZydwpRFHfM4Kox20G5Vcr3D+2EaiCawfasflzPlZj7GGKzUs2onP3HUsrzp8p5OqnKnWiw6mfSdSUmDeyeomX3zX6KyA3p+v8mX/dbKc8c1qFpwMwfmRkb2LyY6dfvZjxve7vFNt0MaGi5izmLPo1C/m7I1LBRGiFheTa15MCAqFg3j1G21cM6/dzSa6eP0ufgI#"); +user_pref("extensions.piclens.Version", "1.6.2.1605"); +user_pref("extensions.update.notifyUser", false); +user_pref("google.toolbar.AUTOFILL_Preferences", "highlight\ntrue\nfullName\n\nemail\n\ndefaultPhone\n\nalternativePhone\n\naddressLine1\n\naddressLine2\n\naddressLine3\n\ncity\n\nstate\n\nzipcode\n\ncountry\n\ndefaultPhoneAll\n\nalternativePhoneAll\n\nworkPhoneAll\n\nhomePhoneAll\n\ncellPhoneAll\n\nfirstName\n\nmiddleName\n\nmiddleInit\n\nlastName\n\nfirstLastName\n\naddress\n\naddressFull\n\nzipshort\n\ndefaultPhoneWork\nfalse\nalternativePhoneWork\nfalse\ndefaultPhoneHome\nfalse\nalternativePhoneHome\nfalse\ndefaultPhoneCell\nfalse\nalternativePhoneCell\nfalse"); +user_pref("google.toolbar.auto_translate", false); +user_pref("google.toolbar.button_option.gtbAutoFill", true); +user_pref("google.toolbar.button_option.gtbAutoLink", true); +user_pref("google.toolbar.button_option.gtbCustomButtonGmail", false); +user_pref("google.toolbar.button_option.gtbSpellCheck", true); +user_pref("google.toolbar.button_option.safebrowsing.advancedprotection.default", true); +user_pref("google.toolbar.button_option.safebrowsing.hasrun", true); +user_pref("google.toolbar.button_option.safebrowsing.tableversion.goog-sandbox-text", "1.5"); +user_pref("google.toolbar.button_option.safebrowsing.tableversion.goog-white-domain", "1.17"); +user_pref("google.toolbar.button_option.safebrowsing.tableversion.goog-white-url", "1.371"); +user_pref("google.toolbar.google_home", "www.google.com"); +user_pref("google.toolbar.install_id", "SnZA7ajGeiCa1tXwUT57CRjfrDqrmIzz46FGau14DDL9"); +user_pref("google.toolbar.install_ping_acked", true); +user_pref("google.toolbar.install_ping_retires", 1); +user_pref("google.toolbar.last_ping_attempt", "1160396718343"); +user_pref("google.toolbar.opted_into_advanced_features_1", true); +user_pref("google.toolbar.rlz", "1B2GGGL_enIN176"); +user_pref("google.toolbar.search_box_history", ""); +user_pref("google.toolbar.search_box_use_suggest", true); +user_pref("google.toolbar.sent", "1"); +user_pref("google.toolbar.spell_check.dictionary.words", ""); +user_pref("google.toolbar.spell_check.lang", "en"); +user_pref("google.toolbar.spell_check.last_lang", "en"); +user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.desc", "Read subscriptions with Firefox Live Bookmarks"); +user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.id", "LiveBookmarks"); +user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.order", "2"); +user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.title", "Firefox Live Bookmarks"); +user_pref("google.toolbar.subscribe.aggregators.LiveBookmarks.url", "LiveBookmarksUrl"); +user_pref("google.toolbar.subscribe.aggregators.bloglines.desc", "Personal page loaded with the freshest news about the things you love"); +user_pref("google.toolbar.subscribe.aggregators.bloglines.id", "bloglines"); +user_pref("google.toolbar.subscribe.aggregators.bloglines.order", "1"); +user_pref("google.toolbar.subscribe.aggregators.bloglines.title", "Bloglines"); +user_pref("google.toolbar.subscribe.aggregators.bloglines.url", "http://www.bloglines.com/sub/%feed%"); +user_pref("google.toolbar.subscribe.aggregators.iGoogle.desc", "Personalized Home"); +user_pref("google.toolbar.subscribe.aggregators.iGoogle.id", "iGoogle"); +user_pref("google.toolbar.subscribe.aggregators.iGoogle.order", "0"); +user_pref("google.toolbar.subscribe.aggregators.iGoogle.title", "Google personalized home"); +user_pref("google.toolbar.subscribe.aggregators.iGoogle.url", "http://fusion.google.com/add?feedurl=%feed%&client=firetools&hl=en"); +user_pref("google.toolbar.subscribe.aggregators.myyahoo.desc", "My Yahoo!"); +user_pref("google.toolbar.subscribe.aggregators.myyahoo.id", "myyahoo"); +user_pref("google.toolbar.subscribe.aggregators.myyahoo.order", "3"); +user_pref("google.toolbar.subscribe.aggregators.myyahoo.title", "My Yahoo"); +user_pref("google.toolbar.subscribe.aggregators.myyahoo.url", "http://add.my.yahoo.com/rss?url=%feed%"); +user_pref("google.toolbar.subscribe.aggregators.newsgator.desc", "NewsGator Online"); +user_pref("google.toolbar.subscribe.aggregators.newsgator.id", "newsgator"); +user_pref("google.toolbar.subscribe.aggregators.newsgator.order", "4"); +user_pref("google.toolbar.subscribe.aggregators.newsgator.title", "NewsGator"); +user_pref("google.toolbar.subscribe.aggregators.newsgator.url", "http://www.newsgator.com/ngs/subscriber/subext.aspx?url=%feed%"); +user_pref("google.toolbar.subscribe.aggregators.pluck.desc", "Pluck personal web information center"); +user_pref("google.toolbar.subscribe.aggregators.pluck.id", "pluck"); +user_pref("google.toolbar.subscribe.aggregators.pluck.order", "5"); +user_pref("google.toolbar.subscribe.aggregators.pluck.title", "Pluck"); +user_pref("google.toolbar.subscribe.aggregators.pluck.url", "http://client.pluck.com/pluckit/prompt.aspx?GCID=C12286x053&a=%feed%"); +user_pref("google.toolbar.subscribe.defaultid", "iGoogle"); +user_pref("google.toolbar.subscribe.lastrefreshed", "Mon Oct 09 2006 13:25:18 GMT+0100 (GMT Daylight Time)"); +user_pref("intl.charsetmenu.browser.cache", "ISO-8859-2, UTF-16LE, us-ascii, UTF-8, ISO-8859-15"); +user_pref("network.cookie.prefsMigrated", true); +user_pref("pref.browser.homepage.disable_button.current_page", false); +user_pref("pref.privacy.disable_button.clear_cache", false); +user_pref("print.print_printer", "Microsoft Office Document Image Writer"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_bgcolor", false); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_bgimages", false); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_command", ""); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_downloadfonts", true); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_evenpages", true); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_footercenter", ""); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_footerleft", "&PT"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_footerright", "&D"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_headercenter", ""); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_headerleft", "&T"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_headerright", "&U"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_in_color", true); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_margin_bottom", "0.5"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_margin_left", "0.5"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_margin_right", "0.5"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_margin_top", "0.5"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_oddpages", true); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_orientation", 0); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_pagedelay", 500); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_data", 1); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_height", " 11.00"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_size", 4259897); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_size_type", 0); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_size_unit", 0); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_paper_width", " 8.50"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_reversed", false); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_scaling", " 1.00"); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_shrink_to_fit", true); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_to_file", false); +user_pref("print.printer_Microsoft_Office_Document_Image_Writer.print_to_filename", ""); +user_pref("security.warn_viewing_mixed", false); +user_pref("spellchecker.dictionary", "en-US"); +user_pref("urlclassifier.keyupdatetime.https://sb-ssl.google.com/safebrowsing/getkey?client=navclient-auto-ffox2.0.0.1&", 1181234396); +user_pref("urlclassifier.keyupdatetime.https://sb-ssl.google.com/safebrowsing/newkey", 1212860951); +user_pref("urlclassifier.tableversion.goog-black-enchash", "1.50318"); +user_pref("urlclassifier.tableversion.goog-black-url", "1.20750"); +user_pref("urlclassifier.tableversion.goog-white-domain", "1.30"); +user_pref("urlclassifier.tableversion.goog-white-url", "1.371"); +user_pref("webdeveloper.custom.1.color", "#ff0000"); +user_pref("webdeveloper.custom.2.color", "#33ff33"); +user_pref("webdeveloper.custom.3.color", "#3333ff"); +user_pref("webdeveloper.custom.4.color", "#ff0000"); +user_pref("webdeveloper.custom.5.color", "#33ff33"); +user_pref("webdeveloper.dashboard.position", "bottom"); +user_pref("webdeveloper.disable.styles.key", "S"); +user_pref("webdeveloper.display.element.information.key", "F"); +user_pref("webdeveloper.edit.color.background", "#ffffff"); +user_pref("webdeveloper.edit.color.text", "#000000"); +user_pref("webdeveloper.edit.css.key", "E"); +user_pref("webdeveloper.edit.font.size", 12); +user_pref("webdeveloper.edit.update.frequency", 2000); +user_pref("webdeveloper.error.console.key", "J"); +user_pref("webdeveloper.feature.tooltip.color.background", "#ffff99"); +user_pref("webdeveloper.feature.tooltip.color.border", "#ffcc66"); +user_pref("webdeveloper.feature.tooltip.color.text", "#000000"); +user_pref("webdeveloper.feature.tooltip.opacity", "0.9"); +user_pref("webdeveloper.generated.content.font.size", 12); +user_pref("webdeveloper.information.tidy", true); +user_pref("webdeveloper.java.console.key", "O"); +user_pref("webdeveloper.line.guides.color", "#000000"); +user_pref("webdeveloper.magnification.level", "2"); +user_pref("webdeveloper.open.tabs", true); +user_pref("webdeveloper.populate.form.fields.email", "example@example.com"); +user_pref("webdeveloper.resize.1.description", "800x600"); +user_pref("webdeveloper.resize.1.height", 600); +user_pref("webdeveloper.resize.1.width", 800); +user_pref("webdeveloper.resize.count", 1); +user_pref("webdeveloper.style.information.dashboard", true); +user_pref("webdeveloper.tool.1.description", "Validate CSS"); +user_pref("webdeveloper.tool.1.url", "http://jigsaw.w3.org/css-validator/validator?profile=css21&warning=0&uri="); +user_pref("webdeveloper.tool.2.description", "Validate Feed"); +user_pref("webdeveloper.tool.2.url", "http://validator.w3.org/feed/check.cgi?url="); +user_pref("webdeveloper.tool.3.description", "Validate HTML"); +user_pref("webdeveloper.tool.3.key", "H"); +user_pref("webdeveloper.tool.3.url", "http://validator.w3.org/check?verbose=1&uri="); +user_pref("webdeveloper.tool.4.description", "Validate Links"); +user_pref("webdeveloper.tool.4.url", "http://validator.w3.org/checklink?check=Check&hide_type=all&summary=on&uri="); +user_pref("webdeveloper.tool.5.description", "Validate Section 508"); +user_pref("webdeveloper.tool.5.url", "http://www.cynthiasays.com/mynewtester/cynthia.exe?rptmode=-1&url1="); +user_pref("webdeveloper.tool.6.description", "Validate WAI"); +user_pref("webdeveloper.tool.6.url", "http://www.cynthiasays.com/mynewtester/cynthia.exe?rptmode=2&url1="); +user_pref("webdeveloper.tool.count", 6); +user_pref("webdeveloper.toolbar.key", "B"); +user_pref("webdeveloper.validate.local.accessibility.section508", true); +user_pref("webdeveloper.validate.local.accessibility.wai.priority1", true); +user_pref("webdeveloper.validate.local.css.profile", "css21"); +user_pref("webdeveloper.validate.local.html.key", "A"); +user_pref("webdeveloper.version", "1.15"); +user_pref("webdeveloper.view.css.key", "C"); +user_pref("webdeveloper.view.source.key", "U"); +user_pref("webdeveloper.view.style.information.key", "Y"); +user_pref("webdeveloper.zoom.in.key", "Z"); +user_pref("webdeveloper.zoom.out.key", "X"); +user_pref("xpinstall.whitelist.add", ""); +user_pref("xpinstall.whitelist.add.103", ""); diff --git a/chrome/test/data/firefox2_profile/signons2.txt b/chrome/test/data/firefox2_profile/signons2.txt new file mode 100644 index 0000000..cd587d4 --- /dev/null +++ b/chrome/test/data/firefox2_profile/signons2.txt @@ -0,0 +1,29 @@ +#2d +https://www.google.com +. +localhost:8080 (corp.google.com) + +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECGWa5u4oyD30BAjVjHehzmI1FQ== +* +MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECIzNoDayvlg8BBDyGwwPHVf4+H5ECFVHSFF7 + +. +http://localhost:8080 +loginuser +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECEFtzZ3poEPfBAhfSWTBcn8uAQ== +*loginpass +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECGRF97w1/HhvBAjcYnNUNjWcgA== +http://localhost:8080 +loginuser +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECNp5fZWsPu6KBAhiRy4Ma1F9/g== +*loginpass +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECGkvYFh0bA7JBAiPYfjWR04V8g== +http://localhost:8080 +. +http://localhost +loginuser +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECBJM63MpT9rtBAjMCm7qo/EhlA== +* +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECH1iF2yH/PbDBAjKtt50MebjIA== + +. diff --git a/chrome/test/data/firefox3_nss/README b/chrome/test/data/firefox3_nss/README new file mode 100644 index 0000000..b54a99e --- /dev/null +++ b/chrome/test/data/firefox3_nss/README @@ -0,0 +1,13 @@ +The NSPR and NSS DLLs in this directory (mozcrt19.dll, nss3.dll, nssutil3.dll +plds4.dll, sqlite3.dll, freebl3.dll, nspr4.dll, nssdbm3.dll, plc4.dll, and +softokn3.dll) come from the Firefox 3.0 distribution for Windows. + +The source code of NSPR and NSS, which you may use, modify, and distribute, is +available to you free-of-charge from www.mozilla.org under the Mozilla Public +License and other open source software licenses. + +The source code of sqlite3.dll is in the public domain. + +mozcrt19.dll is the Mozilla Custom C Runtime, in which Mozilla replaced the +default allocator with jemalloc. mozcrt19.dll is distributed in the object +code form only and as part of the NSPR and NSS DLLs. diff --git a/chrome/test/data/firefox3_nss/freebl3.dll b/chrome/test/data/firefox3_nss/freebl3.dll Binary files differnew file mode 100644 index 0000000..cd9a4f9 --- /dev/null +++ b/chrome/test/data/firefox3_nss/freebl3.dll diff --git a/chrome/test/data/firefox3_nss/mozcrt19.dll b/chrome/test/data/firefox3_nss/mozcrt19.dll Binary files differnew file mode 100644 index 0000000..c6c2fb1 --- /dev/null +++ b/chrome/test/data/firefox3_nss/mozcrt19.dll diff --git a/chrome/test/data/firefox3_nss/nspr4.dll b/chrome/test/data/firefox3_nss/nspr4.dll Binary files differnew file mode 100644 index 0000000..156e23a --- /dev/null +++ b/chrome/test/data/firefox3_nss/nspr4.dll diff --git a/chrome/test/data/firefox3_nss/nss3.dll b/chrome/test/data/firefox3_nss/nss3.dll Binary files differnew file mode 100644 index 0000000..e1e23e1 --- /dev/null +++ b/chrome/test/data/firefox3_nss/nss3.dll diff --git a/chrome/test/data/firefox3_nss/nssdbm3.dll b/chrome/test/data/firefox3_nss/nssdbm3.dll Binary files differnew file mode 100644 index 0000000..d7b9ab8 --- /dev/null +++ b/chrome/test/data/firefox3_nss/nssdbm3.dll diff --git a/chrome/test/data/firefox3_nss/nssutil3.dll b/chrome/test/data/firefox3_nss/nssutil3.dll Binary files differnew file mode 100644 index 0000000..41d5cf7 --- /dev/null +++ b/chrome/test/data/firefox3_nss/nssutil3.dll diff --git a/chrome/test/data/firefox3_nss/plc4.dll b/chrome/test/data/firefox3_nss/plc4.dll Binary files differnew file mode 100644 index 0000000..2e11cbc --- /dev/null +++ b/chrome/test/data/firefox3_nss/plc4.dll diff --git a/chrome/test/data/firefox3_nss/plds4.dll b/chrome/test/data/firefox3_nss/plds4.dll Binary files differnew file mode 100644 index 0000000..2e93aed --- /dev/null +++ b/chrome/test/data/firefox3_nss/plds4.dll diff --git a/chrome/test/data/firefox3_nss/softokn3.dll b/chrome/test/data/firefox3_nss/softokn3.dll Binary files differnew file mode 100644 index 0000000..e29e42d --- /dev/null +++ b/chrome/test/data/firefox3_nss/softokn3.dll diff --git a/chrome/test/data/firefox3_nss/sqlite3.dll b/chrome/test/data/firefox3_nss/sqlite3.dll Binary files differnew file mode 100644 index 0000000..5262876 --- /dev/null +++ b/chrome/test/data/firefox3_nss/sqlite3.dll diff --git a/chrome/test/data/firefox3_profile/cert8.db b/chrome/test/data/firefox3_profile/cert8.db Binary files differnew file mode 100644 index 0000000..ac40a33 --- /dev/null +++ b/chrome/test/data/firefox3_profile/cert8.db diff --git a/chrome/test/data/firefox3_profile/cookies.sqlite b/chrome/test/data/firefox3_profile/cookies.sqlite Binary files differnew file mode 100644 index 0000000..f9ec2f5 --- /dev/null +++ b/chrome/test/data/firefox3_profile/cookies.sqlite diff --git a/chrome/test/data/firefox3_profile/key3.db b/chrome/test/data/firefox3_profile/key3.db Binary files differnew file mode 100644 index 0000000..6788cae --- /dev/null +++ b/chrome/test/data/firefox3_profile/key3.db diff --git a/chrome/test/data/firefox3_profile/places.sqlite b/chrome/test/data/firefox3_profile/places.sqlite Binary files differnew file mode 100644 index 0000000..9540a3e --- /dev/null +++ b/chrome/test/data/firefox3_profile/places.sqlite diff --git a/chrome/test/data/firefox3_profile/prefs.js b/chrome/test/data/firefox3_profile/prefs.js new file mode 100644 index 0000000..c65a9be2 --- /dev/null +++ b/chrome/test/data/firefox3_profile/prefs.js @@ -0,0 +1,32 @@ +# Mozilla User Preferences + +/* Do not edit this file. + * + * If you make changes to this file while the application is running, + * the changes will be overwritten when the application exits. + * + * To make a manual change to preferences, you can visit the URL about:config + * For more information, see http://www.mozilla.org/unix/customizing.html#prefs + */ + +user_pref("app.update.lastUpdateTime.addon-background-update-timer", 1211306768); +user_pref("app.update.lastUpdateTime.background-update-timer", 1211306767); +user_pref("app.update.lastUpdateTime.blocklist-background-update-timer", 1211306767); +user_pref("app.update.lastUpdateTime.microsummary-generator-update-timer", 1211306768); +user_pref("app.update.lastUpdateTime.search-engine-update-timer", 1211306768); +user_pref("browser.migration.version", 1); +user_pref("browser.places.importBookmarksHTML", false); +user_pref("browser.places.importDefaults", false); +user_pref("browser.places.leftPaneFolderId", -1); +user_pref("browser.places.migratePostDataAnnotations", false); +user_pref("browser.places.smartBookmarksVersion", 1); +user_pref("browser.places.updateRecentTagsUri", false); +user_pref("browser.search.selectedEngine", "IMDB"); +user_pref("browser.search.useDBForOrder", true); +user_pref("browser.sessionstore.resume_session_once", true); +user_pref("browser.startup.homepage_override.mstone", "rv:1.9"); +user_pref("extensions.enabledItems", "{972ce4c6-7e08-4474-a285-3208198ce6fd}:3.0"); +user_pref("extensions.lastAppVersion", "3.0"); +user_pref("intl.charsetmenu.browser.cache", "UTF-8"); +user_pref("network.cookie.prefsMigrated", true); +user_pref("urlclassifier.keyupdatetime.https://sb-ssl.google.com/safebrowsing/newkey", 1213898771); diff --git a/chrome/test/data/firefox3_profile/search.sqlite b/chrome/test/data/firefox3_profile/search.sqlite Binary files differnew file mode 100644 index 0000000..55d45cb --- /dev/null +++ b/chrome/test/data/firefox3_profile/search.sqlite diff --git a/chrome/test/data/firefox3_profile/secmod.db b/chrome/test/data/firefox3_profile/secmod.db Binary files differnew file mode 100644 index 0000000..cb8cc20 --- /dev/null +++ b/chrome/test/data/firefox3_profile/secmod.db diff --git a/chrome/test/data/firefox3_profile/signons3.txt b/chrome/test/data/firefox3_profile/signons3.txt new file mode 100644 index 0000000..62cf2c8 --- /dev/null +++ b/chrome/test/data/firefox3_profile/signons3.txt @@ -0,0 +1,18 @@ +#2e +. +http://localhost:8080 +loginuser +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECCZ75mS/2HwhBAj+/bq+5rbwnA== +*loginpass +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECBLe/6FaBaeiBAhSpECjLu7u0Q== +http://localhost:8080 +--- +. +http://localhost:8080 (localhost) + +MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECE6NmWUq+BITBAhvbI1J3RKb6Q== +* +MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECFckjT05RJ8uBBCWqEqv8ciEPf+Q8Fpgbtpf + +--- +. diff --git a/chrome/test/data/focus/page_steals_focus.html b/chrome/test/data/focus/page_steals_focus.html new file mode 100644 index 0000000..46963a0 --- /dev/null +++ b/chrome/test/data/focus/page_steals_focus.html @@ -0,0 +1,55 @@ +<html> + + <head> +<title>This page steals the focus</title> +</head> +<body onload="onLoad()"> + +<script language="javascript" type="text/javascript"> +<!-- + +var count = 1; + +function onLoad() { + updateText(); + setTimeout("loop()", 1000); +} + +function updateText() { + var text_div = document.getElementById("main_text"); + text_div.innerHTML = "I will steal the focus in " + count + " seconds"; +} + + +function loop() { + count--; + if (count == 0) { + var text_div = document.getElementById("main_text"); + text_div.innerHTML = "Focus stolen!"; + stealFocus(); + } else { + updateText(); + setTimeout("loop()", 1000); + } +} + + +function stealFocus() { + var textField = document.getElementById("text_edit"); + textField.focus(); +} + +// --> +</script> + +<h1>Welcome to Focus Taker!</h1> + +<div id="main_text"></div> + +<form href="nowhere.html"> + <input name="SearchText" type="text" id="text_edit"></input> + <input name="SearchButton" type="button" value="Search" onclick="popitup('http://www.google.com');"></input> +</form> +<br> + +</html> diff --git a/chrome/test/data/focus/page_with_focus.html b/chrome/test/data/focus/page_with_focus.html new file mode 100644 index 0000000..62d5ee9 --- /dev/null +++ b/chrome/test/data/focus/page_with_focus.html @@ -0,0 +1,24 @@ +<html> +<head><title>A simple page with the focus on a text edit</title></head> + +<script> + function init() { + document.f.q.focus(); + } +</script> + +<body onload="init()"> + + <h1>Hello</h1> + Search: + <form name=f> + <input name=q size=55 title="Google Search" value=""><br> + <form> + + <a href="http://www.google.com">Google</a> + <a href="http://mail.google.com">GMail</a> + <a href="http://maps.google.com">GMap</a> +</body> + + +</html> diff --git a/chrome/test/data/focus/typical_page.html b/chrome/test/data/focus/typical_page.html new file mode 100644 index 0000000..15b97b0 --- /dev/null +++ b/chrome/test/data/focus/typical_page.html @@ -0,0 +1,47 @@ +<html> +<head><title>Your typical HTML page</title></head> + +<script> + var focused_elem = ""; + + function setFocusedElem(id) { + focused_elem = id; + updateLog(); + } + + function clearFocus() { + focused_elem = ""; + updateLog(); + } + + function getFocusedElement() { + return focused_elem; + } + + function updateLog() { + document.getElementById("log").innerHTML = "Focused element: " + focused_elem; + } + +</script> + +<body> + + <h1>Hello</h1> + Search: + <form name=f> + <input name=q size=55 title="Google Search" value="" id="textEdit" onfocus="setFocusedElem(this.id)" onblur="clearFocus()"><br> + <input type=button value="Search" id="searchButton" onfocus="setFocusedElem(this.id)" onblur="clearFocus()"> + <input type=button value="I am feeling lucky" id="luckyButton" onfocus="setFocusedElem(this.id)" onblur="clearFocus()"> + <form> + <br><br> + + <a href="http://www.google.com" id="googleLink" onfocus="setFocusedElem(this.id)" onblur="clearFocus()">Google</a> + <a href="http://mail.google.com" id="gmailLink" onfocus="setFocusedElem(this.id)" onblur="clearFocus()">GMail</a> + <a href="http://maps.google.com" id="gmapLink" onfocus="setFocusedElem(this.id)" onblur="clearFocus()">GMap</a> + + <br><br><br> + <div id="log"><div> +</body> + +</html> + diff --git a/chrome/test/data/frame_dom_access/frame_dom_access.html b/chrome/test/data/frame_dom_access/frame_dom_access.html new file mode 100644 index 0000000..931acf5 --- /dev/null +++ b/chrome/test/data/frame_dom_access/frame_dom_access.html @@ -0,0 +1,6 @@ +<HTML> + <BODY> + <INPUT id="myinput"> </INPUT> + <IFRAME src="frame_level_1.html"/> + </BODY> +</HTML> diff --git a/chrome/test/data/frame_dom_access/frame_level_1.html b/chrome/test/data/frame_dom_access/frame_level_1.html new file mode 100644 index 0000000..1dbeb9a --- /dev/null +++ b/chrome/test/data/frame_dom_access/frame_level_1.html @@ -0,0 +1,6 @@ +<HTML> + <BODY> + <span id="myspan"></span> + <iframe src="frame_level_2.html"/> + </BODY> +</HTML> diff --git a/chrome/test/data/frame_dom_access/frame_level_2.html b/chrome/test/data/frame_dom_access/frame_level_2.html new file mode 100644 index 0000000..afd7049 --- /dev/null +++ b/chrome/test/data/frame_dom_access/frame_level_2.html @@ -0,0 +1,5 @@ +<HTML> + <BODY> + <DIV id="mydiv"></DIV> + </BODY> +</HTML> diff --git a/chrome/test/data/google/google.html b/chrome/test/data/google/google.html new file mode 100644 index 0000000..6fda776 --- /dev/null +++ b/chrome/test/data/google/google.html @@ -0,0 +1,17 @@ +<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Google</title><style><!-- +body,td,a,p,.h{font-family:arial,sans-serif} +.h{font-size:20px} +.h{color:#3366cc} +.q{color:#00c} +--></style> +<script defer="defer"> +<!-- +function sf(){document.f.q.focus();} +window.rwt=function(b,d,f,j,k,g,l){var a=window.encodeURIComponent?encodeURIComponent:escape,h="",i="",c=b.href.split("#"),e="";if(d){h="&oi="+a(d)}if(f){i="&cad="+a(f)}if(g){e="&usg="+g}b.href="/url?sa=t"+h+i+"&ct="+a(j)+"&cd="+a(k)+"&url="+a(c[0]).replace(/\+/g,"%2B")+"&ei=qmSARdamFcf2YIrlwKoE"+e+l+(c[1]?"#"+c[1]:"");b.onmousedown="";return true};// --> +</script></head><body onload="sf()" topmargin="3" alink="#ff0000" bgcolor="#ffffff" link="#0000cc" marginheight="3" text="#000000" vlink="#551a8b"><center><div nowrap="" style="padding-bottom: 4px;" width="100%" align="right"><font size="-1"><b>yourmom@gmail.com</b> | <a href="http://www.google.com/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den&usg=__yvmOvIrk79QYmDkrJAeuYO8jTmo=" onmousedown="return rwt(this,'promos','hppphou:en_us','pro','1','__zxxGHEJmJoAKTnuqkUevLLYrO4g=','&sig2=81iEbSYzM_7fDQpy6xZaIg')">Personalized Home</a> | <a href="https://www.google.com/accounts/ManageAccount">My Account</a> | <a href="http://www.google.com/accounts/Logout?continue=http://www.google.com/">Sign out</a></font></div><img alt="Google" src="logo.gif" height="110" width="276"><br><br><form action="/search" name="f"><script defer="defer"><!-- +function qs(el){if(window.RegExp&&window.encodeURIComponent){var ue=el.href,qe=encodeURIComponent(document.f.q.value);if(ue.indexOf("q=")!=-1){el.href=ue.replace(new RegExp("q=[^&$]*"),"q="+qe);}else{el.href=ue+"&q="+qe;}}return 1;} +function togDisp(e){stopB(e);var elems=document.getElementsByName('more');for(var i=0;i<elems.length;i++){var obj=elems[i],dp="";if(obj.style.display==""){dp="none";}obj.style.display=dp;}return false;} +function stopB(e){if(!e)e=window.event;e.cancelBubble=true;} +document.onclick=function(event){var elems=document.getElementsByName('more');if(elems[0].style.display==""){togDisp(event);}} +//--> +</script><table border="0" cellpadding="4" cellspacing="0"><tbody><tr><td nowrap="nowrap"><font size="-1"><b>Web</b> <a class="q" href="http://images.google.com/imghp?ie=UTF-8&oe=UTF-8&hl=en&tab=wi" onclick="return qs(this);">Images</a> <a class="q" href="http://video.google.com/?ie=UTF-8&oe=UTF-8&hl=en&tab=wv" onclick="return qs(this);">Video</a> <a class="q" href="http://news.google.com/nwshp?ie=UTF-8&oe=UTF-8&hl=en&tab=wn" onclick="return qs(this);">News</a> <a class="q" href="http://www.google.com/maps?ie=UTF-8&oe=UTF-8&hl=en&tab=wl" onclick="return qs(this);">Maps</a> <!--"/*"/*--><font size="-1"><a class="q" onclick="return window.qs?qs(this):1" href="http://127.0.0.1:4664/&s=oTNhxyxrnKvgsKLBW5ECAV9apZw">Desktop</a></font> <font size="-1"><a class="q" href="http://search/">Moma</a></font> <b><a href="http://www.google.com/intl/en/options/" class="q" onclick="this.blur();return togDisp(event);">more »</a></b><span name="more" id="more" style="border: 1px solid rgb(51, 102, 153); margin: -0.5ex 2ex; padding: 0pt 0pt 0.5ex 0.8ex; background: rgb(255, 255, 255) none repeat scroll 0%; display: none; position: absolute; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 16ex; line-height: 1.9; z-index: 1000;" onclick="stopB(event);"><a href="#" onclick="return togDisp(event);"><img src="x2.gif" alt="Close menu" align="right" border="0" height="12" hspace="4" vspace="4" width="12"></a><a class="q" href="http://books.google.com/bkshp?ie=UTF-8&oe=UTF-8&hl=en&tab=wp" onclick="return qs(this);">Books</a><br><a class="q" href="http://froogle.google.com/frghp?ie=UTF-8&oe=UTF-8&hl=en&tab=wf" onclick="return qs(this);">Froogle</a><br><a class="q" href="http://groups.google.com/grphp?ie=UTF-8&oe=UTF-8&hl=en&tab=wg" onclick="return qs(this);">Groups</a><br><a class="q" href="http://scholar.google.com/schhp?ie=UTF-8&oe=UTF-8&hl=en&tab=ws" onclick="return qs(this);">Scholar</a><br><a href="http://www.google.com/intl/en/options/" class="q"><b>even more »</b></a></span></font></td></tr></tbody></table><table cellpadding="0" cellspacing="0"><tbody><tr valign="top"><td width="25%"> </td><td align="center" nowrap="nowrap"><input name="hl" value="en" type="hidden"><input maxlength="2048" name="q" size="55" title="Google Search" value=""><br><input name="btnG" value="Google Search" type="submit"><input name="btnI" value="I'm Feeling Lucky" type="submit"></td><td nowrap="nowrap" width="25%"><font size="-2"> <a href="http://www.google.com/advanced_search?hl=en">Advanced Search</a><br> <a href="http://www.google.com/preferences?hl=en">Preferences</a><br> <a href="http://www.google.com/language_tools?hl=en">Language Tools</a></font></td></tr></tbody></table></form><br><font size="-1"><a href="http://maps.google.com/maps?f=l" onmousedown="return rwt(this,'promos','hppweb:en_us','pro','1','__cRFkyGl8vmPJFLoVMwLVZG0r-Rs=','&sig2=y1UbGzpOnQEIuHK0FM2ztw')">Google Maps</a>: Find local stores and directions for holiday shopping.</font><br><br><br><font size="-1"><a href="http://www.google.com/intl/en/ads/">Advertising Programs</a> - <a href="http://www.google.com/services/">Business Solutions</a> - <a href="http://www.google.com/intl/en/about.html">About Google</a></font><p><font size="-2">©2006 Google</font></p></center></body></html>
\ No newline at end of file diff --git a/chrome/test/data/google/logo.gif b/chrome/test/data/google/logo.gif Binary files differnew file mode 100644 index 0000000..afa22bc --- /dev/null +++ b/chrome/test/data/google/logo.gif diff --git a/chrome/test/data/google/x2.gif b/chrome/test/data/google/x2.gif Binary files differnew file mode 100644 index 0000000..552b769 --- /dev/null +++ b/chrome/test/data/google/x2.gif diff --git a/chrome/test/data/http_to_file.html b/chrome/test/data/http_to_file.html new file mode 100644 index 0000000..c3062e4 --- /dev/null +++ b/chrome/test/data/http_to_file.html @@ -0,0 +1,5 @@ +<!-- Test used by RedirectTest.NoHttpToFile to make sure we don't crash +and that we don't perform redirections from http to file. See bug 1139823 --> +<html><head><title>File!</title></head> +<body></body> +</html> diff --git a/chrome/test/data/icon_util/128_X_128_icon.ico b/chrome/test/data/icon_util/128_X_128_icon.ico Binary files differnew file mode 100644 index 0000000..a5d72fe --- /dev/null +++ b/chrome/test/data/icon_util/128_X_128_icon.ico diff --git a/chrome/test/data/icon_util/16_X_16_icon.ico b/chrome/test/data/icon_util/16_X_16_icon.ico Binary files differnew file mode 100644 index 0000000..0e524f1 --- /dev/null +++ b/chrome/test/data/icon_util/16_X_16_icon.ico diff --git a/chrome/test/data/ie@cookie[1].txt b/chrome/test/data/ie@cookie[1].txt new file mode 100644 index 0000000..84c1df4 --- /dev/null +++ b/chrome/test/data/ie@cookie[1].txt @@ -0,0 +1,69 @@ +City +010 +cookie.com/ +1536 +616982400 +29918725 +2476228016 +29918054 +* +ID +0CB7D340F6B05B750CAAD871BA598529 +cookie.com/path/ +1536 +2967774592 +32084998 +910020000 +29880625 +* +Security +1 +cookie.com/dir/sub_dir/ +1 +2189574144 +32107986 +2663222448 +29909387 +* +z2 +dogs! +~~local~~/C:/Documents%20and%20Settings/filecookie/ +1088 +2189574144 +32107986 +3575890080 +29928395 +* +WITHPATH +B +boink.example.com/~happy +1600 +2189574144 +32107986 +1637792944 +29932061 +* +HTTPONLY +yarz +boink.example.com/~happy/ +9728 +2189574144 +32107986 +3893915648 +29932062 +* +invalid_case1 +empty_host + +1536 +2319892480 +30251495 +2028928160 +29884415 +* +broken +cookie +shold +not +be +parsed diff --git a/chrome/test/data/iframe.html b/chrome/test/data/iframe.html new file mode 100644 index 0000000..a08e34b --- /dev/null +++ b/chrome/test/data/iframe.html @@ -0,0 +1,4 @@ +<html><head><title>iframe test</title></head> +<body> +<iframe src="title1.html"/> +</body></html>
\ No newline at end of file diff --git a/chrome/test/data/iframe_in_empty_frame.html b/chrome/test/data/iframe_in_empty_frame.html new file mode 100644 index 0000000..854cd1c --- /dev/null +++ b/chrome/test/data/iframe_in_empty_frame.html @@ -0,0 +1,18 @@ +<html><head><title>iframe test</title></head> + <script type="text/javascript"> +function createStruct(wnd,viewer,popup){ + iframe=wnd.document.createElement('iframe'); + viewer.appendChild(iframe); + iframe.contentWindow.document.write('<SCRIPT src=\"iframe_in_empty_frame.js\"></SCR'+'IPT>'); +} + +wndname = "_blank"; +wnd = window.open("", wndname, 'width=780,height=572,scrollbars=no,resizeable=no,statusbar=no,status=no,left = '+((screen.width / 2) - 780 / 2)+', var top = '+((screen.height / 2) - 572 / 2)+''); +if(wnd) { + wnd.document.open(); + wnd.document.write('<html><body onload="finished();"><script>function finished() {if (window.opener) {window.opener.createStruct(this,document.getElementById("viewer"),true);}}</scr'+'ipt><div id="viewer"></div></body></html>'); + wnd.document.close(); +} + +</script> +</html> diff --git a/chrome/test/data/iframe_in_empty_frame.js b/chrome/test/data/iframe_in_empty_frame.js new file mode 100644 index 0000000..110f514 --- /dev/null +++ b/chrome/test/data/iframe_in_empty_frame.js @@ -0,0 +1,3 @@ +document.write(''); +document.location.href="http://www.google.com/" +document.write(''); diff --git a/chrome/test/data/inspector/dummy.js b/chrome/test/data/inspector/dummy.js new file mode 100644 index 0000000..f84383e --- /dev/null +++ b/chrome/test/data/inspector/dummy.js @@ -0,0 +1,3 @@ +function setCookie() { + document.cookie = 'viewsource_cookie=foo'; +} diff --git a/chrome/test/data/inspector/test1.html b/chrome/test/data/inspector/test1.html new file mode 100644 index 0000000..a9cf12d --- /dev/null +++ b/chrome/test/data/inspector/test1.html @@ -0,0 +1,4 @@ +<html> +<body></body> +This file exists to test that one resource get loaded in Chrome inspector. +</html>
\ No newline at end of file diff --git a/chrome/test/data/inspector/test2.html b/chrome/test/data/inspector/test2.html new file mode 100644 index 0000000..21de21b --- /dev/null +++ b/chrome/test/data/inspector/test2.html @@ -0,0 +1,5 @@ +<html> +<head><script src="dummy.js"></script></head> +<body onload="setCookie();"></body> +This file exists to test that two resources get loaded in Chrome inspector. +</html>
\ No newline at end of file diff --git a/chrome/test/data/interstitial_page/google.html b/chrome/test/data/interstitial_page/google.html new file mode 100644 index 0000000..6fda776 --- /dev/null +++ b/chrome/test/data/interstitial_page/google.html @@ -0,0 +1,17 @@ +<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Google</title><style><!-- +body,td,a,p,.h{font-family:arial,sans-serif} +.h{font-size:20px} +.h{color:#3366cc} +.q{color:#00c} +--></style> +<script defer="defer"> +<!-- +function sf(){document.f.q.focus();} +window.rwt=function(b,d,f,j,k,g,l){var a=window.encodeURIComponent?encodeURIComponent:escape,h="",i="",c=b.href.split("#"),e="";if(d){h="&oi="+a(d)}if(f){i="&cad="+a(f)}if(g){e="&usg="+g}b.href="/url?sa=t"+h+i+"&ct="+a(j)+"&cd="+a(k)+"&url="+a(c[0]).replace(/\+/g,"%2B")+"&ei=qmSARdamFcf2YIrlwKoE"+e+l+(c[1]?"#"+c[1]:"");b.onmousedown="";return true};// --> +</script></head><body onload="sf()" topmargin="3" alink="#ff0000" bgcolor="#ffffff" link="#0000cc" marginheight="3" text="#000000" vlink="#551a8b"><center><div nowrap="" style="padding-bottom: 4px;" width="100%" align="right"><font size="-1"><b>yourmom@gmail.com</b> | <a href="http://www.google.com/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den&usg=__yvmOvIrk79QYmDkrJAeuYO8jTmo=" onmousedown="return rwt(this,'promos','hppphou:en_us','pro','1','__zxxGHEJmJoAKTnuqkUevLLYrO4g=','&sig2=81iEbSYzM_7fDQpy6xZaIg')">Personalized Home</a> | <a href="https://www.google.com/accounts/ManageAccount">My Account</a> | <a href="http://www.google.com/accounts/Logout?continue=http://www.google.com/">Sign out</a></font></div><img alt="Google" src="logo.gif" height="110" width="276"><br><br><form action="/search" name="f"><script defer="defer"><!-- +function qs(el){if(window.RegExp&&window.encodeURIComponent){var ue=el.href,qe=encodeURIComponent(document.f.q.value);if(ue.indexOf("q=")!=-1){el.href=ue.replace(new RegExp("q=[^&$]*"),"q="+qe);}else{el.href=ue+"&q="+qe;}}return 1;} +function togDisp(e){stopB(e);var elems=document.getElementsByName('more');for(var i=0;i<elems.length;i++){var obj=elems[i],dp="";if(obj.style.display==""){dp="none";}obj.style.display=dp;}return false;} +function stopB(e){if(!e)e=window.event;e.cancelBubble=true;} +document.onclick=function(event){var elems=document.getElementsByName('more');if(elems[0].style.display==""){togDisp(event);}} +//--> +</script><table border="0" cellpadding="4" cellspacing="0"><tbody><tr><td nowrap="nowrap"><font size="-1"><b>Web</b> <a class="q" href="http://images.google.com/imghp?ie=UTF-8&oe=UTF-8&hl=en&tab=wi" onclick="return qs(this);">Images</a> <a class="q" href="http://video.google.com/?ie=UTF-8&oe=UTF-8&hl=en&tab=wv" onclick="return qs(this);">Video</a> <a class="q" href="http://news.google.com/nwshp?ie=UTF-8&oe=UTF-8&hl=en&tab=wn" onclick="return qs(this);">News</a> <a class="q" href="http://www.google.com/maps?ie=UTF-8&oe=UTF-8&hl=en&tab=wl" onclick="return qs(this);">Maps</a> <!--"/*"/*--><font size="-1"><a class="q" onclick="return window.qs?qs(this):1" href="http://127.0.0.1:4664/&s=oTNhxyxrnKvgsKLBW5ECAV9apZw">Desktop</a></font> <font size="-1"><a class="q" href="http://search/">Moma</a></font> <b><a href="http://www.google.com/intl/en/options/" class="q" onclick="this.blur();return togDisp(event);">more »</a></b><span name="more" id="more" style="border: 1px solid rgb(51, 102, 153); margin: -0.5ex 2ex; padding: 0pt 0pt 0.5ex 0.8ex; background: rgb(255, 255, 255) none repeat scroll 0%; display: none; position: absolute; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 16ex; line-height: 1.9; z-index: 1000;" onclick="stopB(event);"><a href="#" onclick="return togDisp(event);"><img src="x2.gif" alt="Close menu" align="right" border="0" height="12" hspace="4" vspace="4" width="12"></a><a class="q" href="http://books.google.com/bkshp?ie=UTF-8&oe=UTF-8&hl=en&tab=wp" onclick="return qs(this);">Books</a><br><a class="q" href="http://froogle.google.com/frghp?ie=UTF-8&oe=UTF-8&hl=en&tab=wf" onclick="return qs(this);">Froogle</a><br><a class="q" href="http://groups.google.com/grphp?ie=UTF-8&oe=UTF-8&hl=en&tab=wg" onclick="return qs(this);">Groups</a><br><a class="q" href="http://scholar.google.com/schhp?ie=UTF-8&oe=UTF-8&hl=en&tab=ws" onclick="return qs(this);">Scholar</a><br><a href="http://www.google.com/intl/en/options/" class="q"><b>even more »</b></a></span></font></td></tr></tbody></table><table cellpadding="0" cellspacing="0"><tbody><tr valign="top"><td width="25%"> </td><td align="center" nowrap="nowrap"><input name="hl" value="en" type="hidden"><input maxlength="2048" name="q" size="55" title="Google Search" value=""><br><input name="btnG" value="Google Search" type="submit"><input name="btnI" value="I'm Feeling Lucky" type="submit"></td><td nowrap="nowrap" width="25%"><font size="-2"> <a href="http://www.google.com/advanced_search?hl=en">Advanced Search</a><br> <a href="http://www.google.com/preferences?hl=en">Preferences</a><br> <a href="http://www.google.com/language_tools?hl=en">Language Tools</a></font></td></tr></tbody></table></form><br><font size="-1"><a href="http://maps.google.com/maps?f=l" onmousedown="return rwt(this,'promos','hppweb:en_us','pro','1','__cRFkyGl8vmPJFLoVMwLVZG0r-Rs=','&sig2=y1UbGzpOnQEIuHK0FM2ztw')">Google Maps</a>: Find local stores and directions for holiday shopping.</font><br><br><br><font size="-1"><a href="http://www.google.com/intl/en/ads/">Advertising Programs</a> - <a href="http://www.google.com/services/">Business Solutions</a> - <a href="http://www.google.com/intl/en/about.html">About Google</a></font><p><font size="-2">©2006 Google</font></p></center></body></html>
\ No newline at end of file diff --git a/chrome/test/data/interstitial_page/interstitial.html b/chrome/test/data/interstitial_page/interstitial.html new file mode 100644 index 0000000..bc22ecf --- /dev/null +++ b/chrome/test/data/interstitial_page/interstitial.html @@ -0,0 +1,7 @@ +<html> +<head><title>Interstitial page</title></head> +<body> + <h1>This is a phony interstitial page</h1> + Hope you are enjoying it! +</body> +</html>
\ No newline at end of file diff --git a/chrome/test/data/interstitial_page/logo.gif b/chrome/test/data/interstitial_page/logo.gif Binary files differnew file mode 100644 index 0000000..afa22bc --- /dev/null +++ b/chrome/test/data/interstitial_page/logo.gif diff --git a/chrome/test/data/interstitial_page/shopping.html b/chrome/test/data/interstitial_page/shopping.html new file mode 100644 index 0000000..8cb250f --- /dev/null +++ b/chrome/test/data/interstitial_page/shopping.html @@ -0,0 +1,123 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html><head> + +<style type="text/css"> +<!-- +.productname { font-size: 20px; font-weight: bold; color: #1D46AA; font-family: arial,sans-serif} +--> +</style> + + + +<meta http-equiv="content-type" content="text/html; charset=utf-8"><title>Google Product Search</title> + +<script type="text/javascript"> +function sf(){document.f.q.focus();} +function c(p,l,e){var f=document.f;if (f.action && document.getElementById) {var hf=document.getElementById("hf");if (hf) {var t = "<input type=hidden name=tab value="+l+">";hf.innerHTML=t;}f.action = 'http://'+p;e.cancelBubble=true;f.submit();return false;}return true;} +function ss(w){window.status=w;return true;} +function cs(){window.status='';} +function ga(o,e){if (document.getElementById){a=o.id.substring(1); p = "";r = "";g = e.target;if (g) { t = g.id;f = g.parentNode;if (f) {p = f.id;h = f.parentNode;if (h) r = h.id;}} else{h = e.srcElement;f = h.parentNode;if (f) p = f.id;t = h.id;}if (t==a || p==a || r==a) return true;location.href=document.getElementById(a).href}} +function postAddToShoppingList(formId) { var elm = document.getElementById(formId); elm.submit(); } +</script> +<link type="text/css" rel="stylesheet" href="shopping_files/froogle.css"> +<style type="text/css"> +#q{width:22.5em} +</style> +<script>window.gbar={};(function(){function o(a,e,d){var b="on"+e;if(a.addEventListener){a.addEventListener(e,d,false)}else if(a.attachEvent){a.attachEvent(b,d)}else{var i=a[b];a[b]=function(){var f=i.apply(this,arguments),h=d.apply(this,arguments);return f==undefined?h:(h==undefined?f:h&&f)}}};var j=window.gbar,c,l,g;function m(a,e,d){a.display=a.display=="block"?"none":"block";a.left=e+"px";a.top=d+"px"}j.tg=function(a){var e=0,d,b,i,f=0,h=window.navExtra;!l&&(l=document.getElementById("gbar"));!g&&(g=l.getElementsByTagName("span"));(a||window.event).cancelBubble=true;if(!c){c=document.createElement(Array.every||window.createPopup?"iframe":"div");c.frameBorder="0";c.id="gbi";c.scrolling="no";c.src="javascript:''";document.body.appendChild(c);if(h&&g[8])for(var n in h){var k=document.createElement("span");k.appendChild(h[n]);k.className="gb2";g[0].parentNode.insertBefore(k,g[8])}o(document,"click",j.close)}for(;g[f];f++){b=g[f];i=b.className;if(i=="gb3"){d=b.offsetLeft;while(b=b.offsetParent)d+=b.offsetLeft;m(c.style,d,24)}else if(i=="gb2"){if(!(g[f].firstChild.tagName=="A")){b.style.padding=".2em .5em"}m(b.style,d+1,25+e);e+=20}}c.style.height=e+"px"};j.close=function(a){c&&c.style.display=="block"&&j.tg(a)};})();</script> +<style>#gbar{float:left;font-weight:bold;height:22px;padding-left:2px}#gbh{border-top:1px solid #c9d7f1;font-size:0;height:0;position:absolute;right:0;top:24px;width:200%}#gbi{background:#fff;border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;font-size:13px;top:24px;z-index:1000}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}}#gbi,.gb2{display:none;position:absolute;width:8em}.gb2{z-index:1001}#gbar a,#gbar a:active,#gbar a:visited{color:#00c;font-weight:normal}.gb2 a,.gb3 a{text-decoration:none}.gb2 a{display:block;padding:.2em .5em}#gbar .gb2 a:hover{background:#36c;color:#fff}</style> +<style type="text/css">#gbar .gbard b{padding:.2em .5em;}</style></head><noscript><meta http-equiv=refresh content="0; URL=/prdhp?tab=wf&output=html"></noscript><body onload="document.f.q.focus();" topmargin="3" alink="#ff0000" bgcolor="#ffffff" link="#0000cc" marginheight="3" text="#000000" vlink="#551a8b"> +<div id="gbar"><nobr><span class="gb1"><a href="http://www.google.com/webhp?tab=fw">Web</a></span> <span class="gb1"><a href="http://images.google.com/imghp?tab=fi">Images</a></span> <span class="gb1"><a href="http://maps.google.com/maps?tab=fl">Maps</a></span> <span class="gb1"><a href="http://news.google.com/nwshp?tab=fn">News</a></span> <span class="gb1">Shopping</span> <span class="gb1"><a href="http://mail.google.com/mail?tab=fm">Gmail</a></span> <span class="gb3"><a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return false"><u>more</u> <span style="font-size: 11px;">▼</span></a></span> <span class="gb2"><a href="http://blogsearch.google.com/?tab=fb">Blogs</a></span> <span class="gb2"><a href="http://books.google.com/bkshp?tab=fp">Books</a></span> <span class="gb2"><a href="http://www.google.com/calendar?tab=fc">Calendar</a></span> <span class="gb2"><a href="http://docs.google.com/?tab=fo">Documents</a></span> <span class="gb2"><a href="http://finance.google.com/finance?tab=fe">Finance</a></span> <span class="gb2"><a href="http://groups.google.com/grphp?tab=fg">Groups</a></span> <span class="gb2"><a href="http://picasaweb.google.com/home?tab=fq">Photos</a></span> <span class="gb2"><a href="http://www.google.com/reader?tab=fy">Reader</a></span> <span class="gb2"><a href="http://scholar.google.com/schhp?tab=fs">Scholar</a></span> <span class="gb2"><a href="http://video.google.com/?tab=fv">Video</a></span> <span class="gb2"><a href="http://www.youtube.com/?tab=f1">YouTube</a></span> <span class="gb2"><a href="http://www.google.com/intl/en/options/">even more »</a></span> </nobr></div><div id="gbh"></div> +<div align="right"> +<nobr><font size="-1"> +<a href="http://www.google.com/shoppinglist">My Shopping List</a></font></nobr> +</div> +<br> +<center> +<table border="0" cellpadding="0" cellspacing="0" width="100%"> +<tbody><tr> +<td align="center" valign="bottom"> +<table border="0" cellpadding="0" cellspacing="0"> +<tbody><tr> +<td align="right"><img src="shopping_files/hp0.gif" alt="Google Product Search" border="0"></td> +<td><img src="shopping_files/hp1.gif" border="0"></td> +<td align="left"><img src="shopping_files/hp2.gif" border="0"></td> +</tr><tr> +<td align="right" valign="top"><span class="productname"><b>Product Search</b></span></td> +<td valign="top"><img src="shopping_files/hp3.gif" border="0"></td> +<td valign="top"><font color="#6f6f6f" size="-1">BETA</font></td> +</tr> +</tbody></table> +<br> +<form name="f" action="/products"> +<table cellpadding="0" cellspacing="0"> +<tbody><tr valign="top"> +<td width="150"> </td> +<td align="center"> +<input maxlength="256" name="q" size="40" value=""> <input name="btnG" value="Search Products" type="submit"> +<span id="hf"> +</span> +</td> +<td align="left" nowrap="nowrap" valign="top" width="150"> +<font size="-2"> <a href="http://www.google.com/advanced_product_search">Advanced Product Search</a> +<br> <a href="http://www.google.com/preferences">Preferences</a> +</font> +</td> +</tr> +</tbody></table> +</form> +<h2 style="margin: 1em; font-size: 110%; color: rgb(29, 70, 166); font-weight: bold;">Search for stuff to buy.</h2> +<p></p><table align="center" cellpadding="3" cellspacing="0" width="630"> +<tbody><tr><td style="border-bottom: 1px solid rgb(51, 102, 204);" colspan="5"><font size="-1">A few of the items recently found with Google Product Search:</font></td></tr> +<tr> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=balloons&sampleq=1">balloons</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=buckwheat+pillow&sampleq=1">buckwheat pillow</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=miter+saw&sampleq=1">miter saw</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=firewood+rack&sampleq=1">firewood rack</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=nikon+coolpix&sampleq=1">nikon coolpix</a></font></nobr></td> +</tr> +<tr> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=high+chair&sampleq=1">high chair</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=sofa+set&sampleq=1">sofa set</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=bean+bag&sampleq=1">bean bag</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=wine+refrigerator&sampleq=1">wine refrigerator</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=chopsticks&sampleq=1">chopsticks</a></font></nobr></td> +</tr> +<tr> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=coffee+grinder&sampleq=1">coffee grinder</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=polk+audio&sampleq=1">polk audio</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=body+glove+wetsuit&sampleq=1">body glove wetsuit</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=grandfather+clocks&sampleq=1">grandfather clocks</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=milk+crate&sampleq=1">milk crate</a></font></nobr></td> +</tr> +<tr> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=belgian+chocolate&sampleq=1">belgian chocolate</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=measuring+cups&sampleq=1">measuring cups</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=backgammon&sampleq=1">backgammon</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=hawaiian+shirt&sampleq=1">hawaiian shirt</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=hip+flask&sampleq=1">hip flask</a></font></nobr></td> +</tr> +<tr> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=camera+case&sampleq=1">camera case</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=replaytv&sampleq=1">replaytv</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=dvd+camcorders&sampleq=1">dvd camcorders</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=bagless+vacuum&sampleq=1">bagless vacuum</a></font></nobr></td> +<td nowrap="nowrap" width="20"><nobr><font size="-1"><a href="http://www.google.com/products?q=crystal+chandelier&sampleq=1">crystal chandelier</a></font></nobr></td> +</tr> +<tr><td style="border-bottom: 1px solid rgb(51, 102, 204); height: 5px; font-size: 1px;" colspan="5"> </td></tr> +</tbody></table> +<br> +<p></p> +<hr class="z"> +<table border="0" cellpadding="2" cellspacing="0" width="100%"> +<tbody><tr> +<td align="center"> +<font size="-1"><a href="http://www.google.com/">Google Home</a> - +<a href="http://www.google.com/base/help/sellongoogle.html">Information for Sellers</a> - <a href="http://www.google.com/products/intl/en_us/about.html">Help</a> +</font> +</td> +</tr> +</tbody></table> +<br> +<font class="p" size="-1">©2007 Google</font> + +</td></tr></tbody></table></center></body></html>
\ No newline at end of file diff --git a/chrome/test/data/interstitial_page/shopping_files/froogle.css b/chrome/test/data/interstitial_page/shopping_files/froogle.css new file mode 100644 index 0000000..db2e22b --- /dev/null +++ b/chrome/test/data/interstitial_page/shopping_files/froogle.css @@ -0,0 +1 @@ +.attr-div{padding:0 0 0 0;margin-bottom:.25em}.attr-table th,.attr-table td{text-align:left;vertical-align:top;font-size:small;white-space:nowrap;padding-right:2em}.attr-div th{font-weight:normal}.attr-table ul,.attr-table li{display:block;margin:0;padding:0;text-indent:0;white-space:nowrap}.directions{white-space:nowrap}.directions a{font-weight:bold}.directions a:visited,.directions a:link{font-weight:normal;color:blue}.directions form{margin-bottom:1em}body,td, div, a, p{font-family:arial, sans-serif}.indent{margin-left:1em;margin-right:1em}.q a:visited,.q a:link, .q a:active, .q{color:#0000cc}.z{display:none}img{border-color:#0000a0}form{margin:0px}.w{white-space:nowrap!important;background-color:white;padding:6px 0}.h{font-size:78%}.g{font-size:83%;border:1px solid #cccccc;font-weight:normal}.c{border-right:1px solid #cccccc;padding:3px 2px 6px 2px}.d{border-left:1px solid #cccccc;padding:3px 2px 6px 2px}.b{font-size:12pt;color:#0000cc;font-weight:bold}.n a{font-size:10pt;color:#000000}.f,.f:link, .f a:link{color:#6f6f6f}.fl:visited{color:#551a8b}.fl:active{color:#f00}.fl:link{color:#7777CC}.fmr:visited{color:#551a8b}.fmr:active{color:#f00}.fmr:link{color:#3366cc}.i,.i:link{color:#a90a08}.n .i{font-size:10pt;font-weight:bold}.t a:link,.t a:active, .t a:visited, .t{color:#000000}.ch{cursor:pointer;cursor:hand}.a,.cp{color:#008000}.cp:visited{color:#551a8b}.cpn:visited{color:#551a8b}.q a:visited,.q a:link, .q a:active, .q{color:#0000cc}.k{background-color:#80c65a}.z{display:none}.j{width:33em}.e{margin-top:.75em;margin-bottom:.75em}.submitLink{color:#00f;background-color:transparent;text-decoration:underline;border:none;cursor:pointer;cursor:hand}.inform{margin:0;padding:0;display:inline}.x{padding-right:10px}.dr{font-size:90%}.de{width:30em}.bo{border-bottom:1px solid #efefef;width:11em}.bot{border-bottom:1px solid #cdcdcd}.ol{border-bottom:1px solid #efefef}.la{margin-top:0.5em}.la td{border-right:1px solid silver;padding-left:10px;padding-right:10px}.la .pad{border-right:0px;height:6px}.la .last{border-right:0px}.la f{color:#6f6f6f}.la .s{font-size:70%}.compare a{background-color:#efefef;width:11em;border-style:outset;border-width:1px;text-align:center;bottom:0px;display:block;padding:1px}.compare a:active,.compare a:focus{border-style:inset}.no{text-decoration:none;color:#000000;font-size:90%}.buy a{width:7em}.pd{padding-bottom:10px}body{background:#fff;color:#000;margin:3px 8px 0 8px}a img{border:0}table{border:0}.store-info,.product-info{font-size:small;width:300px}.store-info td{vertical-align:top}.store-info td.pr,.store-info td.icn{text-align:center;font-size:small;font-weight:bold;width:100px}.store-info td.icn img{width:90px;height:90px}.store-info .name,.product-info .name{font-size:medium;font-weight:normal}.store-info .pr,.product-info .pr{font-size:medium;font-weight:bold}.store-info .ratings a{color:green}.all-stores{text-align:right}.product-info .icon{float:left;margin:5px}#page{margin-top:8px;position:relative}#panel{overflow:auto;width:400px;left:0px}#map{left:410px;border:1px solid #979797}#panel,#map{position:absolute;top:0px}#result .list{width:100%;width:expression(this.offsetParent.clientWidth+'px')}.list{margin:0 0 0.5em 0}.list td{font-size:small;vertical-align:top;padding:2px}.list .bc td{padding:0}.list p{margin:0}.list img{border:0}.list h3{margin:0;font-weight:normal;font-size:medium}.list address{display:inline;font-style:normal}.list .pr{font-weight:bold}.list .price-cell{font-size:small;text-align:center}.list .icon-cell{text-align:center}.list .icon-cell img{width:60px;height:60px;margin-right:5px;cursor:pointer}.list .icon-cell{width:65px}.list .marker-cell img{width:20px;height:34px;margin:0 2px}.list .store{color:green;font-weight:bold}.list .cluster-selected{background:#efefef}.list .distance{color:#555555}#location{background:white;border:0;border:1px solid #ddd;color:black;margin:0 5px}.tabs td.addr-cell{padding-top:0;padding-bottom:0}.tabs form{display:inline;margin:0}.pr{font-size:medium}.compare a{color:black;text-decoration:none;margin-left:auto;margin-right:auto}h3.name{font-size:medium;font-weight:normal;margin-top:0}.description{width:47em}#panel .description{width:auto}.description td{font-size:small}.description .pr{font-size:medium;font-weight:bold}.list h3{font-size:medium;font-weight:normal;margin:0}.bot td{border-bottom:1px solid #cdcdcd}.list .bot td{padding:5px 10px}.list .description{padding-bottom:0.5em}.currency-input{font-size:90%;font-family:arial,sans-serif;width:3em;text-align:right;vertical-align:middle;margin-top:0.2em}.units-input{font-size:90%;font-family:arial,sans-serif;width:3em;text-align:right;vertical-align:middle;margin-top:0.2em}#q,#addr{-moz-box-sizing:border-box;box-sizing:border-box}#addr{width:16em}#q,#addr{margin-right:.2em}#qt .addr{display:none}#qt.show-addr .addr{display:inline}#qt.show-addr .non-addr{display:none}#qt.show-addr #q{width:11.8em}#qt.show-addr td.addr{display:block;display:table-cell}#qt td{text-align:left;vertical-align:top;white-space:nowrap}#qt span{color:#666}#qt .lbl{font-size:70%}.sw{margin:0 5px 2px 10px;font-size:small}.sort-header td{background:#efefef;vertical-align:middle}.offer-list td{padding:5px 10px;border-bottom:1px solid #cdcdcd}.sort-header .selected{background:#cdcdcd}.disclaimer{font-size:small;margin:0.2em;text-align:center}.n a{text-decoration:none}.n a span{text-decoration:underline}
\ No newline at end of file diff --git a/chrome/test/data/interstitial_page/shopping_files/hp0.gif b/chrome/test/data/interstitial_page/shopping_files/hp0.gif Binary files differnew file mode 100644 index 0000000..5452545 --- /dev/null +++ b/chrome/test/data/interstitial_page/shopping_files/hp0.gif diff --git a/chrome/test/data/interstitial_page/shopping_files/hp1.gif b/chrome/test/data/interstitial_page/shopping_files/hp1.gif Binary files differnew file mode 100644 index 0000000..b84be85 --- /dev/null +++ b/chrome/test/data/interstitial_page/shopping_files/hp1.gif diff --git a/chrome/test/data/interstitial_page/shopping_files/hp2.gif b/chrome/test/data/interstitial_page/shopping_files/hp2.gif Binary files differnew file mode 100644 index 0000000..30623b8 --- /dev/null +++ b/chrome/test/data/interstitial_page/shopping_files/hp2.gif diff --git a/chrome/test/data/interstitial_page/shopping_files/hp3.gif b/chrome/test/data/interstitial_page/shopping_files/hp3.gif Binary files differnew file mode 100644 index 0000000..ea140b7 --- /dev/null +++ b/chrome/test/data/interstitial_page/shopping_files/hp3.gif diff --git a/chrome/test/data/interstitial_page/x2.gif b/chrome/test/data/interstitial_page/x2.gif Binary files differnew file mode 100644 index 0000000..552b769 --- /dev/null +++ b/chrome/test/data/interstitial_page/x2.gif diff --git a/chrome/test/data/npapi/arguments.html b/chrome/test/data/npapi/arguments.html new file mode 100644 index 0000000..835473c --- /dev/null +++ b/chrome/test/data/npapi/arguments.html @@ -0,0 +1,40 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +NPAPI Loading and Argument Tests<p> +Tests our ability to pass arguments to the plugin via the embed +tag.<P> + +<embed type="application/vnd.npapi-test" + src="foo" + name="arguments" + id="1" + mode="np_embed" + count="12" + size="10" + val1="0123456789" + val2="01234567890123456789" + val3="012345678901234567890123456789" + val4="0123456789012345678901234567890123456789" + val5="01234567890123456789012345678901234567890123456789" + val6="012345678901234567890123456789012345678901234567890123456789" + val7="0123456789012345678901234567890123456789012345678901234567890123456789" + val8="01234567890123456789012345678901234567890123456789012345678901234567890123456789" + val9="012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + val10="0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + val11="01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + val12="012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +> + +</body> +</html> diff --git a/chrome/test/data/npapi/execute_script_delete_in_npn_evaluate.html b/chrome/test/data/npapi/execute_script_delete_in_npn_evaluate.html new file mode 100644 index 0000000..f2e2bbe --- /dev/null +++ b/chrome/test/data/npapi/execute_script_delete_in_npn_evaluate.html @@ -0,0 +1,39 @@ +<html> + +<head> +<script src="npapi.js"></script> + +<script> +function DeletePluginWithinScript() { + var plugin_div = document.getElementById("PluginDiv"); + plugin_div.innerHTML = "Object Deleted"; + onSuccess("npobject_delete_plugin_in_evaluate", 1); +} +</script> +</head> + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +NPObject Proxy Test<p> + +Tests the case where a plugin instance is deleted in the context +of NPN_Evaluate + +<DIV ID=PluginDiv> +<embed type="application/vnd.npapi-test" + src="foo" + name="npobject_delete_plugin_in_evaluate" + id="1" + mode="np_embed" +> +</DIV> +<script> + var height = document.body.offsetHeight; +</script> + +</body> +</html> diff --git a/chrome/test/data/npapi/execute_script_delete_in_paint.html b/chrome/test/data/npapi/execute_script_delete_in_paint.html new file mode 100644 index 0000000..fa9ff21 --- /dev/null +++ b/chrome/test/data/npapi/execute_script_delete_in_paint.html @@ -0,0 +1,39 @@ +<html> + +<head> +<script src="npapi.js"></script> + +<script> +function DeletePluginWithinScript() { + var plugin_div = document.getElementById("PluginDiv"); + plugin_div.innerHTML = "Object Deleted"; + onSuccess("execute_script_delete_in_paint", 1); +} +</script> +</head> + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +NPObject Proxy Test<p> + +Tests the case where a plugin instance is deleted in the context +of a synchronous paint. + +<DIV ID=PluginDiv> +<embed type="application/vnd.npapi-test" + src="foo" + name="execute_script_delete_in_paint" + id="1" + mode="np_embed" +> +</DIV> +<script> + var height = document.body.offsetHeight; +</script> + +</body> +</html> diff --git a/chrome/test/data/npapi/get_javascript_url.html b/chrome/test/data/npapi/get_javascript_url.html new file mode 100644 index 0000000..404613b --- /dev/null +++ b/chrome/test/data/npapi/get_javascript_url.html @@ -0,0 +1,26 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +GetJavscriptURL Test<p> +This test fetches a javascript URL via the plugin with _top as the +target frame, and verifies that the call succeeds. + +<embed type="application/vnd.npapi-test" + src="foo" + name="getjavascripturl" + id="1" + mode="np_embed" +> + +</body> +</html> diff --git a/chrome/test/data/npapi/geturl.html b/chrome/test/data/npapi/geturl.html new file mode 100644 index 0000000..002b63b --- /dev/null +++ b/chrome/test/data/npapi/geturl.html @@ -0,0 +1,26 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +GetURL Test<p> +This test fetches an URL via the plugin, and verifies that the +callbacks are expected and that the retrieved content is correct. + +<embed type="application/vnd.npapi-test" + src="foo" + name="geturl" + id="1" + mode="np_embed" +> + +</body> +</html> diff --git a/chrome/test/data/npapi/layout_test_plugin.html b/chrome/test/data/npapi/layout_test_plugin.html new file mode 100644 index 0000000..d523d3c --- /dev/null +++ b/chrome/test/data/npapi/layout_test_plugin.html @@ -0,0 +1,17 @@ +<html> +<head> +<title>Layout Test Plugin Test</title> +</head> +<body> +<embed name="plg" type="application/x-webkit-test-netscape"></embed> +<script> +// Test for bug 711411: http://b/issue?id=711411 +// There was a crash because of the plugin dll being unloaded before the JS +// interpreter got a chance to drop references. +window.plg.eventLoggingEnabled = true; +</script> + +<!-- Make sure unknown plugin types don't crash either --> +<embed name="no-plg" type="application/not-installed"></embed> +</body> +</html> diff --git a/chrome/test/data/npapi/many_plugins.html b/chrome/test/data/npapi/many_plugins.html new file mode 100644 index 0000000..5edcc55 --- /dev/null +++ b/chrome/test/data/npapi/many_plugins.html @@ -0,0 +1,94 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +Loading many plugins<p> +Tests our ability to load multiple plugins in a single page.<P> + +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="1" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="2" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="3" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="4" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="5" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="6" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="7" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="8" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="9" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="10" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="11" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="12" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="13" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="14" +> +<embed type="application/vnd.npapi-test" + name="arguments" + mode="np_embed" + id="15" +> + +</body> +</html> diff --git a/chrome/test/data/npapi/new_fails.html b/chrome/test/data/npapi/new_fails.html new file mode 100644 index 0000000..a4b7de9 --- /dev/null +++ b/chrome/test/data/npapi/new_fails.html @@ -0,0 +1,30 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +NPP_NEW test<p> +This test ensures we don't crash or assert if NPP_New fails. + +<embed type="application/vnd.npapi-test" + src="foo" + name="new_fails" + id="1" + mode="np_embed" +> + +<script> + var height = document.body.offsetHeight; + onSuccess("new_fails", 1); +</script> + +</body> +</html> diff --git a/chrome/test/data/npapi/npapi.js b/chrome/test/data/npapi/npapi.js new file mode 100644 index 0000000..207d188 --- /dev/null +++ b/chrome/test/data/npapi/npapi.js @@ -0,0 +1,28 @@ +// +// This script provides some mechanics for testing NPAPI +// + +/* public */ function onSuccess(name, id) +{ + setTimeout(onFinished, 0, name, id, "OK"); +} + +/* public */ function onFailure(name, id, status) +{ + setTimeout(onFinished, 0, name, id, status); +} + + + +// Finish running a test by setting the status +// and the cookie. +/* private */ function onFinished(name, id, result) +{ + var statusPanel = document.getElementById("statusPanel"); + if (statusPanel) { + statusPanel.innerHTML = result; + } + + var cookie = name + "." + id + ".status=" + result + "; path=/"; + document.cookie = cookie; +} diff --git a/chrome/test/data/npapi/npobject_lifetime_test.html b/chrome/test/data/npapi/npobject_lifetime_test.html new file mode 100644 index 0000000..634fad8 --- /dev/null +++ b/chrome/test/data/npapi/npobject_lifetime_test.html @@ -0,0 +1,58 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +NPObject Lifetime test<p> + +Tests the case where a plugin holds on to an NPObject reference +to another plugin in a different frame in the page and whether +the npobject is callable when the frame is destroyed. + +<div ID=npobject_lifetime_test_instance2> +<iframe src="npobject_lifetime_test_second_instance.html" name="plugin_frame"> +</iframe> +</div> + +<embed type="application/vnd.npapi-test" + src="foo" + name="npobject_lifetime_test" + id="1" + mode="np_embed"> + +<script> + +function GetSecondPluginInstance() { + var plugin_frame = window.frames["plugin_frame"]; + if (!plugin_frame) { + alert("failed to find frame in frames list"); + return; + } + + var plugin = plugin_frame.document.getElementById(2); + if (!plugin) { + alert("Failed to locate second plugin"); + return; + } + return plugin; +} + +function DeleteSecondPluginInstance() { + var frame_div = document.getElementById("npobject_lifetime_test_instance2"); + if (frame_div.parentNode && frame_div.parentNode.removeChild) { + frame_div.parentNode.removeChild(frame_div); + } +} +</script> + +</body> +</html> + diff --git a/chrome/test/data/npapi/npobject_lifetime_test_second_instance.html b/chrome/test/data/npapi/npobject_lifetime_test_second_instance.html new file mode 100644 index 0000000..5876f8e --- /dev/null +++ b/chrome/test/data/npapi/npobject_lifetime_test_second_instance.html @@ -0,0 +1,20 @@ +<html> + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Second instance. +</div> + +NPObject Lifetime test second plugin instance<p> + +Tests the case where a plugin holds on to an NPObject reference +to another plugin in a different frame in the page and whether +the npobject is callable when the frame is destroyed. + +<embed type="application/vnd.npapi-test" + name="npobject_lifetime_test_second_instance" + id="2" + mode="np_embed"> </embed> + +</body> +</html> diff --git a/chrome/test/data/npapi/npobject_proxy.html b/chrome/test/data/npapi/npobject_proxy.html new file mode 100644 index 0000000..ef85ee7 --- /dev/null +++ b/chrome/test/data/npapi/npobject_proxy.html @@ -0,0 +1,28 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +NPObject Proxy Test<p> + +Tests that if an NPObject is proxies back to its original process, the +original pointer is returned and not a proxy. If this fails the plugin +will crash. + +<embed type="application/vnd.npapi-test" + src="foo" + name="npobject_proxy" + id="1" + mode="np_embed" +> + +</body> +</html> diff --git a/chrome/test/data/npapi/self_delete_plugin_geturl.html b/chrome/test/data/npapi/self_delete_plugin_geturl.html new file mode 100644 index 0000000..2d14340 --- /dev/null +++ b/chrome/test/data/npapi/self_delete_plugin_geturl.html @@ -0,0 +1,37 @@ +<html> +<head> +<title>Self Deleting Plugin Test - GetURL</title> +<script src="npapi.js"></script> +<script> +function DeletePluginWithinScript() { + var plugin_div = document.getElementById("PluginDiv"); + plugin_div.innerHTML = "Object Deleted"; +} + +function CallGetUrl() { + var plg = window.document["plg"]; + plg.getURL("javascript:DeletePluginWithinScript()"); +} +</script> +</head> + +<body> + +<h2>Test to delete a plugin during script execution</h2> + +<p> +This test is for a corner case when a plugin executes a script +that deletes the invoking plugin itself. +</p> + +<DIV ID=PluginDiv> +<embed name="plg" type="application/x-webkit-test-netscape"></embed> +</DIV> +<script> + CallGetUrl(); + onSuccess("self_delete_plugin_geturl", 1); +</script> + +</body> +</html> + diff --git a/chrome/test/data/npapi/self_delete_plugin_invoke.html b/chrome/test/data/npapi/self_delete_plugin_invoke.html new file mode 100644 index 0000000..73b940f --- /dev/null +++ b/chrome/test/data/npapi/self_delete_plugin_invoke.html @@ -0,0 +1,33 @@ +<html> +<head> +<title>Self Deleting Plugin Test - Invoke</title> +<script src="npapi.js"></script> +<script> +function DeletePluginWithinScript() { + var plugin_div = document.getElementById("PluginDiv"); + plugin_div.innerHTML = "Object Deleted"; +} +</script> +</head> + +<body> + +<h2>Test to delete a plugin during script execution</h2> + +<p> +This test is for a corner case when a plugin executes a script +that deletes the invoking plugin itself. +</p> + +<DIV ID=PluginDiv> +<embed name="plg" type="application/x-webkit-test-netscape"></embed> +</DIV> +<script> + var plg = window.document["plg"]; + plg.testCallback("DeletePluginWithinScript"); + onSuccess("self_delete_plugin_invoke", 1); +</script> + +</body> +</html> + diff --git a/chrome/test/data/npapi/self_delete_plugin_stream.html b/chrome/test/data/npapi/self_delete_plugin_stream.html new file mode 100644 index 0000000..a43c38a --- /dev/null +++ b/chrome/test/data/npapi/self_delete_plugin_stream.html @@ -0,0 +1,34 @@ +<html> + +<head> +<script src="npapi.js"></script> + +<script> +function DeletePluginWithinScript() { + var plugin_div = document.getElementById("PluginDiv"); + plugin_div.innerHTML = "Object Deleted"; + onSuccess("self_delete_plugin_stream", 1); +} +</script> +</head> + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +<DIV ID=PluginDiv> +<embed type="application/vnd.npapi-test" + src="foo" + name="self_delete_plugin_stream" + id="1" + mode="np_embed" +> +</DIV> +<script> + var height = document.body.offsetHeight; +</script> + +</body> +</html> diff --git a/chrome/test/data/npapi/verify_plugin_window_rect.html b/chrome/test/data/npapi/verify_plugin_window_rect.html new file mode 100644 index 0000000..7dca47a --- /dev/null +++ b/chrome/test/data/npapi/verify_plugin_window_rect.html @@ -0,0 +1,30 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +Plugin Window Rect Test<p> + +Tests whether the plugin window has a non zero client rect. + +<DIV ID=PluginDiv> +<embed type="application/vnd.npapi-test" + src="foo" + name="checkwindowrect" + id="1" + mode="np_embed" +> +</DIV> +<script> + var height = document.body.offsetHeight; +</script> + +</body> +</html> diff --git a/chrome/test/data/omnibox_tests.xml b/chrome/test/data/omnibox_tests.xml new file mode 100644 index 0000000..f9ce9521 --- /dev/null +++ b/chrome/test/data/omnibox_tests.xml @@ -0,0 +1,38 @@ +<omnibox_tests> + <test query="google.com"> + </test> + <test query="www.yahoo.com"> + </test> + <test query="http://myspace.com/"> + </test> + <test query="youtube.com"> + </test> + <test query="wikipedia.org/"> + </test> + <test query="msn.com"> + </test> + <test query="ebay.com"> + </test> + <test query="http://live.com"> + </test> + <test query="craigslist.org"> + </test> + <test query="http://blogger.com/"> + </test> + <test query="flickr.com"> + </test> + <test query="nytimes.com"> + </test> + <test query="cnn.com/"> + </test> + <test query="digg.com"> + </test> + <test query="rapidshare.com"> + </test> + <test query="orkut.com/"> + </test> + <test query="http://download.com"> + </test> + <test query="photobucket.com/"> + </test> +</omnibox_tests> diff --git a/chrome/test/data/onunload_cookie.html b/chrome/test/data/onunload_cookie.html new file mode 100644 index 0000000..0a7de8d --- /dev/null +++ b/chrome/test/data/onunload_cookie.html @@ -0,0 +1,18 @@ +<html> + <head> + <title>Loading...</title> + </head> + <body onload="attachUnloadListener()"> + <script> + function attachUnloadListener() { + window.addEventListener('unload', onUnload, false); + document.title = "set cookie on unload"; + } + + function onUnload() { + document.cookie = "onunloadCookie=foo"; + } + </script> + <p>Navigate to another page to set cookie</p> + </body> +</html> diff --git a/chrome/test/data/pref_service/overlay.json b/chrome/test/data/pref_service/overlay.json new file mode 100644 index 0000000..ea4d831 --- /dev/null +++ b/chrome/test/data/pref_service/overlay.json @@ -0,0 +1,22 @@ +{
+ "both": {
+ "bool": false,
+ "dictionary": {
+ "value": "persistent"
+ },
+ "int": 1,
+ "list": [ "persistent" ],
+ "real": 1,
+ "string": "persistent"
+ },
+ "persistent": {
+ "bool": false,
+ "dictionary": {
+ "value": "persistent"
+ },
+ "int": 1,
+ "list": [ "persistent" ],
+ "real": 1.0,
+ "string": "persistent"
+ }
+}
diff --git a/chrome/test/data/pref_service/read.json b/chrome/test/data/pref_service/read.json new file mode 100644 index 0000000..0225f17 --- /dev/null +++ b/chrome/test/data/pref_service/read.json @@ -0,0 +1,7 @@ +{ + "homepage": "http://www.cnn.com", + "tabs": { + "new_windows_in_tabs": true, + "max_tabs": 20 + } +}
\ No newline at end of file diff --git a/chrome/test/data/pref_service/write.golden.json b/chrome/test/data/pref_service/write.golden.json new file mode 100644 index 0000000..1da3ec4 --- /dev/null +++ b/chrome/test/data/pref_service/write.golden.json @@ -0,0 +1,7 @@ +{
+ "homepage": "http://www.cnn.com",
+ "tabs": {
+ "max_tabs": 10,
+ "new_windows_in_tabs": false
+ }
+}
diff --git a/chrome/test/data/printing/alert_small.png b/chrome/test/data/printing/alert_small.png Binary files differnew file mode 100644 index 0000000..6ac7854 --- /dev/null +++ b/chrome/test/data/printing/alert_small.png diff --git a/chrome/test/data/printing/cleardot.gif b/chrome/test/data/printing/cleardot.gif Binary files differnew file mode 100644 index 0000000..1d11fa9 --- /dev/null +++ b/chrome/test/data/printing/cleardot.gif diff --git a/chrome/test/data/printing/click_me.png b/chrome/test/data/printing/click_me.png Binary files differnew file mode 100644 index 0000000..fc2a70b --- /dev/null +++ b/chrome/test/data/printing/click_me.png diff --git a/chrome/test/data/printing/iframe.emf b/chrome/test/data/printing/iframe.emf Binary files differnew file mode 100644 index 0000000..dc7839b --- /dev/null +++ b/chrome/test/data/printing/iframe.emf diff --git a/chrome/test/data/printing/iframe.htm b/chrome/test/data/printing/iframe.htm new file mode 100644 index 0000000..7c9f443 --- /dev/null +++ b/chrome/test/data/printing/iframe.htm @@ -0,0 +1,29 @@ +<html> +<title>iframe</title> +<SCRIPT type="text/javascript" language="JavaScript"> +function PrintIframe() { + // Standard way + //window.frames["inner_frame"].focus(); + //window.frames["inner_frame"].print(); + // IE6 way + //document.inner_frame.focus(); + //document.inner_frame.print(); + // IE7 way. That's the way Safari does it. + window.frames["inner_frame"].document.execCommand('print',false,null) +} +function DelayedPrint() { + setTimeout(PrintIframe, 0); +} +</SCRIPT> +<body onload="javascript:DelayedPrint()"> + +<p> +<a href="javascript:PrintIframe()"><img src="click_me.png" /></a> +<p> +<div> +<iframe src="test2.html" id="inner_frame" style="height:150px; margin:0px; padding:0px"><html><body>A</body></html></iframe> +</div> +<br> +<img src="sadtab.png" /> +</body> +</html> diff --git a/chrome/test/data/printing/iframe.png b/chrome/test/data/printing/iframe.png Binary files differnew file mode 100644 index 0000000..f57d335 --- /dev/null +++ b/chrome/test/data/printing/iframe.png diff --git a/chrome/test/data/printing/popup_delayed_print.emf b/chrome/test/data/printing/popup_delayed_print.emf Binary files differnew file mode 100644 index 0000000..0698293 --- /dev/null +++ b/chrome/test/data/printing/popup_delayed_print.emf diff --git a/chrome/test/data/printing/popup_delayed_print.htm b/chrome/test/data/printing/popup_delayed_print.htm new file mode 100644 index 0000000..bddcb20 --- /dev/null +++ b/chrome/test/data/printing/popup_delayed_print.htm @@ -0,0 +1,13 @@ +<HTML> +<HEAD> +<TITLE>Bug 1184673</TITLE> +</HEAD> +<script> +function DoThePopup() { + window.open('popup_delayed_print_child.htm'); +} +</script> +<BODY onload="javascript:DoThePopup()"> +<a href="javascript:DoThePopup()">This won't be printed.</a> +</BODY> +</HTML>
\ No newline at end of file diff --git a/chrome/test/data/printing/popup_delayed_print.png b/chrome/test/data/printing/popup_delayed_print.png Binary files differnew file mode 100644 index 0000000..34fa01c --- /dev/null +++ b/chrome/test/data/printing/popup_delayed_print.png diff --git a/chrome/test/data/printing/popup_delayed_print_child.htm b/chrome/test/data/printing/popup_delayed_print_child.htm new file mode 100644 index 0000000..7463b9d --- /dev/null +++ b/chrome/test/data/printing/popup_delayed_print_child.htm @@ -0,0 +1,14 @@ +<HTML> +<HEAD> +<TITLE>Bug 1184673</TITLE> +</HEAD> +<script> +function DoThePrint() { + window.print(); + window.close(); +} +</script> +<BODY onload="DoThePrint()"> +<img src="click_me.png" /> +</BODY> +</HTML>
\ No newline at end of file diff --git a/chrome/test/data/printing/sadtab.png b/chrome/test/data/printing/sadtab.png Binary files differnew file mode 100644 index 0000000..a19d09d --- /dev/null +++ b/chrome/test/data/printing/sadtab.png diff --git a/chrome/test/data/printing/test1.emf b/chrome/test/data/printing/test1.emf Binary files differnew file mode 100644 index 0000000..3f102e6 --- /dev/null +++ b/chrome/test/data/printing/test1.emf diff --git a/chrome/test/data/printing/test1.html b/chrome/test/data/printing/test1.html new file mode 100644 index 0000000..af4db0f --- /dev/null +++ b/chrome/test/data/printing/test1.html @@ -0,0 +1,20 @@ +<html> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<title>test1</title> +<body bgcolor=#eeeeee > +<a href="">Random invalid link.</a> +<br> +<div style="font-family:arial unicode ms"> +Arabic ligature testing: allāh: ﷲ +<br> +Arabic ligature testing: lām: الله +<br> +Alphabet in Hebrew: alephbet: אלפבית +<br> +Hello world in Korean: 여러분, 안녕하세요 +<br> +Hello world in Chinese: 你好世界 +<br> +</div> +</body> +</html>
\ No newline at end of file diff --git a/chrome/test/data/printing/test1.png b/chrome/test/data/printing/test1.png Binary files differnew file mode 100644 index 0000000..423d640 --- /dev/null +++ b/chrome/test/data/printing/test1.png diff --git a/chrome/test/data/printing/test1_cleartype.png b/chrome/test/data/printing/test1_cleartype.png Binary files differnew file mode 100644 index 0000000..99feff7 --- /dev/null +++ b/chrome/test/data/printing/test1_cleartype.png diff --git a/chrome/test/data/printing/test2.emf b/chrome/test/data/printing/test2.emf Binary files differnew file mode 100644 index 0000000..6ccfa9e --- /dev/null +++ b/chrome/test/data/printing/test2.emf diff --git a/chrome/test/data/printing/test2.html b/chrome/test/data/printing/test2.html new file mode 100644 index 0000000..aa9ec22 --- /dev/null +++ b/chrome/test/data/printing/test2.html @@ -0,0 +1,10 @@ +<html> +<title>test2</title> +<body bgcolor=#eeeeee > +<img src="sadtab.png" width=10 height=10 /> +<br> +<img src="sadtab.png" /> +<br> +<img src="sadtab.png" width=100 height=100 /> +</body> +</html> diff --git a/chrome/test/data/printing/test2.png b/chrome/test/data/printing/test2.png Binary files differnew file mode 100644 index 0000000..f57d335 --- /dev/null +++ b/chrome/test/data/printing/test2.png diff --git a/chrome/test/data/printing/test3.emf b/chrome/test/data/printing/test3.emf Binary files differnew file mode 100644 index 0000000..ec5fbc7 --- /dev/null +++ b/chrome/test/data/printing/test3.emf diff --git a/chrome/test/data/printing/test3.html b/chrome/test/data/printing/test3.html new file mode 100644 index 0000000..06f34c7 --- /dev/null +++ b/chrome/test/data/printing/test3.html @@ -0,0 +1,8 @@ +<html> +<title>test3</title> +<body bgcolor=#eeeeee > +<img src="cleardot.gif" /> +<br> +<img src="cleardot.gif" width=10 height=10 /> +</body> +</html> diff --git a/chrome/test/data/printing/test3.png b/chrome/test/data/printing/test3.png Binary files differnew file mode 100644 index 0000000..d1a4948 --- /dev/null +++ b/chrome/test/data/printing/test3.png diff --git a/chrome/test/data/printing/test4.emf b/chrome/test/data/printing/test4.emf Binary files differnew file mode 100644 index 0000000..3a62454 --- /dev/null +++ b/chrome/test/data/printing/test4.emf diff --git a/chrome/test/data/printing/test4.html b/chrome/test/data/printing/test4.html new file mode 100644 index 0000000..ae12955 --- /dev/null +++ b/chrome/test/data/printing/test4.html @@ -0,0 +1,10 @@ +<html> +<title>test4</title> +<body bgcolor=#eeeeee > +<img src="alert_small.png" width=10 height=10 /> +<br> +<img src="alert_small.png" /> +<br> +<img src="alert_small.png" width=100 height=100 /> +</body> +</html> diff --git a/chrome/test/data/printing/test4.png b/chrome/test/data/printing/test4.png Binary files differnew file mode 100644 index 0000000..68f9551 --- /dev/null +++ b/chrome/test/data/printing/test4.png diff --git a/chrome/test/data/printing/test5.emf b/chrome/test/data/printing/test5.emf Binary files differnew file mode 100644 index 0000000..a6a1a48 --- /dev/null +++ b/chrome/test/data/printing/test5.emf diff --git a/chrome/test/data/printing/test5.html b/chrome/test/data/printing/test5.html new file mode 100644 index 0000000..e1b09dc --- /dev/null +++ b/chrome/test/data/printing/test5.html @@ -0,0 +1,18 @@ +<html> +<title>test5</title> +<style> +#localbackground img { +background:white url(sadtab.png) no-repeat scroll 0px; +height:66px; +width:66px; +} +img { +border:medium none; +} +</style> +<body> +<div id="localbackground"> +<img src="cleardot.gif" width="66" height="66" border="0" alt=""> +</div> +</body> +</html>
\ No newline at end of file diff --git a/chrome/test/data/printing/test5.png b/chrome/test/data/printing/test5.png Binary files differnew file mode 100644 index 0000000..2ef0a17 --- /dev/null +++ b/chrome/test/data/printing/test5.png diff --git a/chrome/test/data/profiles/chrome_prefs/History b/chrome/test/data/profiles/chrome_prefs/History new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/profiles/chrome_prefs/History diff --git a/chrome/test/data/profiles/chrome_prefs/Preferences b/chrome/test/data/profiles/chrome_prefs/Preferences new file mode 100644 index 0000000..937b1e39 --- /dev/null +++ b/chrome/test/data/profiles/chrome_prefs/Preferences @@ -0,0 +1,15 @@ +{
+ "intl": {
+ "charset_default": "utf8"
+ },
+ "webkit": {
+ "webprefs": {
+ "default_font_size": 20,
+ "text_areas_are_resizable": false,
+ "uses_universal_detector": true,
+
+ "foo": "bar",
+ "standard_font_family": true
+ }
+ }
+}
diff --git a/chrome/test/data/profiles/sample/Full Text Index b/chrome/test/data/profiles/sample/Full Text Index Binary files differnew file mode 100644 index 0000000..b1f52bd --- /dev/null +++ b/chrome/test/data/profiles/sample/Full Text Index diff --git a/chrome/test/data/profiles/sample/History b/chrome/test/data/profiles/sample/History Binary files differnew file mode 100644 index 0000000..517a3a5 --- /dev/null +++ b/chrome/test/data/profiles/sample/History diff --git a/chrome/test/data/profiles/sample/Preferences b/chrome/test/data/profiles/sample/Preferences new file mode 100644 index 0000000..19765bd --- /dev/null +++ b/chrome/test/data/profiles/sample/Preferences @@ -0,0 +1 @@ +null diff --git a/chrome/test/data/profiles/sample/Thumbnails b/chrome/test/data/profiles/sample/Thumbnails Binary files differnew file mode 100644 index 0000000..404701d --- /dev/null +++ b/chrome/test/data/profiles/sample/Thumbnails diff --git a/chrome/test/data/profiles/sample/Visited Links b/chrome/test/data/profiles/sample/Visited Links Binary files differnew file mode 100644 index 0000000..48635f9 --- /dev/null +++ b/chrome/test/data/profiles/sample/Visited Links diff --git a/chrome/test/data/profiles/sample/Web Data b/chrome/test/data/profiles/sample/Web Data Binary files differnew file mode 100644 index 0000000..0954bf2 --- /dev/null +++ b/chrome/test/data/profiles/sample/Web Data diff --git a/chrome/test/data/profiles/typical_history/Default/Cookies b/chrome/test/data/profiles/typical_history/Default/Cookies Binary files differnew file mode 100644 index 0000000..e138f7c --- /dev/null +++ b/chrome/test/data/profiles/typical_history/Default/Cookies diff --git a/chrome/test/data/profiles/typical_history/Default/Full Text Index b/chrome/test/data/profiles/typical_history/Default/Full Text Index Binary files differnew file mode 100644 index 0000000..65ea2f6 --- /dev/null +++ b/chrome/test/data/profiles/typical_history/Default/Full Text Index diff --git a/chrome/test/data/profiles/typical_history/Default/History b/chrome/test/data/profiles/typical_history/Default/History Binary files differnew file mode 100644 index 0000000..9c33937 --- /dev/null +++ b/chrome/test/data/profiles/typical_history/Default/History diff --git a/chrome/test/data/profiles/typical_history/Default/Preferences b/chrome/test/data/profiles/typical_history/Default/Preferences new file mode 100644 index 0000000..e56c782 --- /dev/null +++ b/chrome/test/data/profiles/typical_history/Default/Preferences @@ -0,0 +1,11 @@ +{
+ "profile": {
+ "exited_cleanly": true,
+ "id": "not-signed-in",
+ "name": "Not Signed In",
+ "nickname": "not-signed-in"
+ },
+ "spellcheck": {
+ "dictionary": "en-US"
+ }
+}
diff --git a/chrome/test/data/profiles/typical_history/Default/Thumbnails b/chrome/test/data/profiles/typical_history/Default/Thumbnails Binary files differnew file mode 100644 index 0000000..fc26118 --- /dev/null +++ b/chrome/test/data/profiles/typical_history/Default/Thumbnails diff --git a/chrome/test/data/profiles/typical_history/Default/Visited Links b/chrome/test/data/profiles/typical_history/Default/Visited Links Binary files differnew file mode 100644 index 0000000..2fa35a9 --- /dev/null +++ b/chrome/test/data/profiles/typical_history/Default/Visited Links diff --git a/chrome/test/data/profiles/typical_history/README.txt b/chrome/test/data/profiles/typical_history/README.txt new file mode 100644 index 0000000..d8441f9 --- /dev/null +++ b/chrome/test/data/profiles/typical_history/README.txt @@ -0,0 +1,14 @@ +This directory is supposed to represent a "typical" size of a history database +that a user will have. It does not include thumbnail or full text index data. +It should be copied to another location before using in a test. + +It was generated with + <delete the files "Full Text Index" and "History" in "Default" - this is important!> + generate_profile --history-only 50000 "Default" + +The unit test HistoryProfileTest.TypicalProfileVersion tests that the version +of this profile is the same that the application is expecting without +migration. Otherwise, migration time will be counted in some of the performance +tests. + + diff --git a/chrome/test/data/profiles/window_placement/Local State b/chrome/test/data/profiles/window_placement/Local State new file mode 100644 index 0000000..39bc7d5 --- /dev/null +++ b/chrome/test/data/profiles/window_placement/Local State @@ -0,0 +1,11 @@ +{ + "browser" : { + "window_placement" : { + "bottom" : 610, + "left" : 50, + "maximized" : false, + "right" : 1014, + "top" : 50 + } + } +} diff --git a/chrome/test/data/purify/ignore.txt b/chrome/test/data/purify/ignore.txt new file mode 100644 index 0000000..1f9a186 --- /dev/null +++ b/chrome/test/data/purify/ignore.txt @@ -0,0 +1,6 @@ +# See bug 1157381 +Pure: Trap bits found in live chunk + +# See bug 1128489 +NSSDecryptor::Init +NSSDecryptor::Free diff --git a/chrome/test/data/purify/ipc_tests.exe_MLK.txt b/chrome/test/data/purify/ipc_tests.exe_MLK.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/purify/ipc_tests.exe_MLK.txt diff --git a/chrome/test/data/purify/ipc_tests.exe_UMR.txt b/chrome/test/data/purify/ipc_tests.exe_UMR.txt new file mode 100644 index 0000000..6f7d34f --- /dev/null +++ b/chrome/test/data/purify/ipc_tests.exe_UMR.txt @@ -0,0 +1,157 @@ +Uninitialized memory read in strlen +Error Location + ... + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&) + chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + base/message_loop.cc MessageLoop::SignalWatcher(DWORD) + base/message_loop.cc MessageLoop::ProcessNextObject(void) + base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *) + base/message_loop.cc MessageLoop::Run(void) + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... + +Uninitialized memory read in WriteFile +Error Location + ... + chrome/common/ipc_channel.cc IPC::Channel::ProcessOutgoingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + chrome/common/ipc_channel.cc IPC::Channel::Send(Message::IPC *) + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&) + chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + base/message_loop.cc MessageLoop::SignalWatcher(DWORD) + base/message_loop.cc MessageLoop::ProcessNextObject(void) + base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *) + base/message_loop.cc MessageLoop::Run(void) + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... +Alloc Location + ... + base/pickle.cc Pickle::Resize(UINT) + base/pickle.cc Pickle::BeginWrite(UINT) + base/pickle.cc Pickle::WriteBytes(void const*,int) + base/pickle.cc Pickle::WriteString(basic_string::std const&) + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&) + chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + base/message_loop.cc MessageLoop::SignalWatcher(DWORD) + base/message_loop.cc MessageLoop::ProcessNextObject(void) + base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *) + base/message_loop.cc MessageLoop::Run(void) + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... + +Uninitialized memory read in strlen +Error Location + ... + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&) + chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + base/message_loop.cc MessageLoop::SignalWatcher(DWORD) + base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *) + base/message_loop.cc MessageLoop::Run(void) + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... + +Uninitialized memory read in WriteFile +Error Location + ... + chrome/common/ipc_channel.cc IPC::Channel::ProcessOutgoingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + chrome/common/ipc_channel.cc IPC::Channel::Send(Message::IPC *) + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&) + chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + base/message_loop.cc MessageLoop::SignalWatcher(DWORD) + base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *) + base/message_loop.cc MessageLoop::Run(void) + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... +Alloc Location + ... + base/pickle.cc Pickle::Resize(UINT) + base/pickle.cc Pickle::BeginWrite(UINT) + base/pickle.cc Pickle::WriteBytes(void const*,int) + base/pickle.cc Pickle::WriteString(basic_string::std const&) + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&) + chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + base/message_loop.cc MessageLoop::SignalWatcher(DWORD) + base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *) + base/message_loop.cc MessageLoop::Run(void) + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... + +Uninitialized memory read in WriteFile +Error Location + ... + chrome/common/ipc_channel.cc IPC::Channel::ProcessOutgoingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::Send(Message::IPC *) + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&) + chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + base/message_loop.cc MessageLoop::SignalWatcher(DWORD) + base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *) + base/message_loop.cc MessageLoop::Run(void) + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... +Alloc Location + ... + base/pickle.cc Pickle::Resize(UINT) + base/pickle.cc Pickle::BeginWrite(UINT) + base/pickle.cc Pickle::WriteBytes(void const*,int) + base/pickle.cc Pickle::WriteString(basic_string::std const&) + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc MyChannelListener::OnMessageReceived(Message::IPC const&) + chrome/common/ipc_channel.cc IPC::Channel::ProcessIncomingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::OnObjectSignaled(void *) + base/message_loop.cc MessageLoop::SignalWatcher(DWORD) + base/message_loop.cc MessageLoop::Run(Dispatcher::MessageLoop *) + base/message_loop.cc MessageLoop::Run(void) + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... + +Uninitialized memory read in strlen +Error Location + ... + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... + +Uninitialized memory read in WriteFile +Error Location + ... + chrome/common/ipc_channel.cc IPC::Channel::ProcessOutgoingMessages(void) + chrome/common/ipc_channel.cc IPC::Channel::Send(Message::IPC *) + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... +Alloc Location + ... + base/pickle.cc Pickle::Resize(UINT) + base/pickle.cc Pickle::BeginWrite(UINT) + base/pickle.cc Pickle::WriteBytes(void const*,int) + base/pickle.cc Pickle::WriteString(basic_string::std const&) + chrome/common/ipc_tests.cc Send + chrome/common/ipc_tests.cc RunTestClient + chrome/common/ipc_tests.cc main + ... + diff --git a/chrome/test/data/purify/unit_tests.exe.gtest.txt b/chrome/test/data/purify/unit_tests.exe.gtest.txt new file mode 100644 index 0000000..4e83728 --- /dev/null +++ b/chrome/test/data/purify/unit_tests.exe.gtest.txt @@ -0,0 +1,2 @@ +# bug 1178136 +ImporterTest.Firefox3Importer diff --git a/chrome/test/data/purify/unit_tests.exe_FIM.txt b/chrome/test/data/purify/unit_tests.exe_FIM.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/purify/unit_tests.exe_FIM.txt diff --git a/chrome/test/data/purify/unit_tests.exe_FIM_flakey.txt b/chrome/test/data/purify/unit_tests.exe_FIM_flakey.txt new file mode 100644 index 0000000..76276cb --- /dev/null +++ b/chrome/test/data/purify/unit_tests.exe_FIM_flakey.txt @@ -0,0 +1,12 @@ +Freeing invalid memory in free +Free Location + ... + chrome/third_party/hunspell/src/hunspell/hashmgr.cxx HashMgr::~HashMgr(void) + chrome/release/unit_tests.exe HashMgr::`scalar deleting destructor'(UINT) + chrome/third_party/hunspell/src/hunspell/hunspell.cxx Hunspell::~Hunspell(void) + chrome/release/unit_tests.exe Hunspell::`scalar deleting destructor'(UINT) + chrome/browser/spellchecker.cc SpellChecker::~SpellChecker(void) + chrome/renderer/spellcheck_unittest.cc SpellCheckTest_SpellCheckStrings_EN_US_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + diff --git a/chrome/test/data/purify/unit_tests.exe_IPR.txt b/chrome/test/data/purify/unit_tests.exe_IPR.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/purify/unit_tests.exe_IPR.txt diff --git a/chrome/test/data/purify/unit_tests.exe_MLK.txt b/chrome/test/data/purify/unit_tests.exe_MLK.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/purify/unit_tests.exe_MLK.txt diff --git a/chrome/test/data/purify/unit_tests.exe_MLK_flakey.txt b/chrome/test/data/purify/unit_tests.exe_MLK_flakey.txt new file mode 100644 index 0000000..951467c --- /dev/null +++ b/chrome/test/data/purify/unit_tests.exe_MLK_flakey.txt @@ -0,0 +1,97 @@ +sqlite3GenericRealloc [unit_tests.exe] +Alloc Location + ... + chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +sqlite3GenericRealloc [unit_tests.exe] +Alloc Location + ... + chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +sqlite3GenericRealloc [unit_tests.exe] +Alloc Location + ... + chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +sqlite3GenericMalloc [unit_tests.exe] +Alloc Location + ... + chrome/common/sqlite_utils.h SQLStatement::prepare(sqlite3 *,char const*,int) + chrome/common/sqlite_utils.h SQLStatement::prepare(sqlite3 *,char const*) + chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +sqlite3GenericMalloc [unit_tests.exe] +Alloc Location + ... + chrome/common/sqlite_utils.h SQLStatement::step(void) + chrome/browser/history/history_unittest.cc history::HistoryProfileTest_TypicalProfileVersion_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +TabStripModelTest::CreateTabContents(void) [unit_tests.exe] +Alloc Location + ... + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +TabContents::SetupController(Profile *) [unit_tests.exe] +Alloc Location + ... + chrome/browser/tab_contents.cc TabContents::SetupController(Profile *) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +?_Allocate@U_Node@?$_List_nod@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@V?$allocator@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@@2@@std@@@std@@YAPAU_Node@?$_List_nod@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@V?$allocator@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@@2@@0@IPAU120@@Z [unit_tests.exe] +Alloc Location + ... + chrome/browser/navigation_controller.cc NavigationController::NavigationController(TabContents *,Profile *) + chrome/browser/tab_contents.cc TabContents::SetupController(Profile *) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +c:\b\slave\p\build\third_party\platformsdk_vista_6_0\files\vc\include\xmemory. +Alloc Location + ... + chrome/browser/navigation_controller.cc NavigationController::NavigationController(TabContents *,Profile *) + chrome/browser/tab_contents.cc TabContents::SetupController(Profile *) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +?_Allocate@U_Node@?$_List_nod@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@V?$allocator@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@@2@@std@@@std@@YAPAU_Node@?$_List_nod@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@V?$allocator@U?$pair@$$CBW4TabContentsType@@PAVTabContents@@@std@@@2@@0@IPAU120@@Z [unit_tests.exe] +Alloc Location + ... + chrome/browser/navigation_controller.cc NavigationController::RegisterTabContents(TabContents *) + chrome/browser/navigation_controller.cc NavigationController::NavigationController(TabContents *,Profile *) + chrome/browser/tab_contents.cc TabContents::SetupController(Profile *) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +c:\b\slave\p\build\third_party\platformsdk_vista_6_0\files\vc\include\xmemory. +Alloc Location + ... + chrome/browser/ssl_manager.cc SSLManager::SSLManager(NavigationController *,Delegate::SSLManager *) + chrome/browser/navigation_controller.cc NavigationController::NavigationController(TabContents *,Profile *) + chrome/browser/tab_contents.cc TabContents::SetupController(Profile *) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest::CreateTabContents(void) + chrome/browser/tabs/tab_strip_model_unittest.cc TabStripModelTest_TestBasicAPI_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + diff --git a/chrome/test/data/purify/unit_tests.exe_UMR.txt b/chrome/test/data/purify/unit_tests.exe_UMR.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/purify/unit_tests.exe_UMR.txt diff --git a/chrome/test/data/purify/unit_tests.exe_UMR_flakey.txt b/chrome/test/data/purify/unit_tests.exe_UMR_flakey.txt new file mode 100644 index 0000000..a737c34 --- /dev/null +++ b/chrome/test/data/purify/unit_tests.exe_UMR_flakey.txt @@ -0,0 +1,100 @@ +Uninitialized memory read in WriteFile +Error Location + ... + chrome/browser/session_backend.cc SessionBackend::AppendCommandsToFile(void *,vector::std const&) + chrome/browser/session_backend.cc SessionBackend::AppendCommands(vector::std *,bool) + chrome/browser/session_service.cc SessionService::Save(void) + chrome/browser/session_service.cc SessionService::~SessionService(void) + chrome/release/unit_tests.exe SessionService::`vector deleting destructor'(UINT) + base/ref_counted.h base::RefCountedThreadSafe::Release(void) + base/ref_counted.h scoped_refptr::=(SessionService *) + chrome/browser/session_service_test_helper.h SessionServiceTestHelper::set_service(SessionService *) + chrome/browser/session_service_unittest.cc SessionServiceTest::ReadWindows(vector::std *) + chrome/browser/session_service_unittest.cc SessionServiceTest_ClosingTabStaysClosed_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ +Alloc Location + ... + chrome/browser/session_backend.cc SessionCommand::SessionCommand(BYTE,WORD) + chrome/browser/session_service.cc SessionService::CreateTabClosedCommand(int) + chrome/browser/session_service.cc SessionService::TabClosed(SessionID const&,SessionID const&) + chrome/browser/session_service_unittest.cc SessionServiceTest_ClosingTabStaysClosed_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +Uninitialized memory read in WriteFile +Error Location + ... + chrome/browser/session_backend.cc SessionBackend::AppendCommandsToFile(void *,vector::std const&) + chrome/browser/session_backend.cc SessionBackend::AppendCommands(vector::std *,bool) + chrome/browser/session_service.cc SessionService::Save(void) + chrome/browser/session_service.cc SessionService::~SessionService(void) + chrome/release/unit_tests.exe SessionService::`vector deleting destructor'(UINT) + base/ref_counted.h base::RefCountedThreadSafe::Release(void) + base/ref_counted.h scoped_refptr::=(SessionService *) + chrome/browser/session_service_test_helper.h SessionServiceTestHelper::set_service(SessionService *) + chrome/browser/session_service_unittest.cc SessionServiceTest::ReadWindows(vector::std *) + chrome/browser/session_service_unittest.cc SessionServiceTest_WindowCloseCommittedAfterNavigate_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ +Alloc Location + ... + chrome/browser/session_backend.cc SessionCommand::SessionCommand(BYTE,WORD) + chrome/browser/session_service.cc SessionService::CreateTabClosedCommand(int) + chrome/browser/session_service.cc SessionService::CommitPendingCloses(void) + chrome/browser/session_service.cc SessionService::UpdateTabNavigation(SessionID const&,int,NavigationEntry const&) + chrome/browser/session_service_unittest.cc SessionServiceTest::UpdateNavigation(SessionID const&,TabNavigation const&,bool) + chrome/browser/session_service_unittest.cc SessionServiceTest_WindowCloseCommittedAfterNavigate_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +Uninitialized memory read in WriteFile +Error Location + ... + chrome/browser/session_backend.cc SessionBackend::AppendCommandsToFile(void *,vector::std const&) + chrome/browser/session_backend.cc SessionBackend::AppendCommands(vector::std *,bool) + chrome/browser/session_service.cc SessionService::Save(void) + chrome/browser/session_service.cc SessionService::~SessionService(void) + chrome/release/unit_tests.exe SessionService::`scalar deleting destructor'(UINT) + base/ref_counted.h base::RefCountedThreadSafe::Release(void) + base/ref_counted.h scoped_refptr::=(SessionService *) + chrome/browser/session_service_test_helper.h SessionServiceTestHelper::set_service(SessionService *) + chrome/browser/session_service_unittest.cc SessionServiceTest::ReadWindows(vector::std *) + chrome/browser/session_service_unittest.cc SessionServiceTest_WindowCloseCommittedAfterNavigate_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ +Alloc Location + ... + chrome/browser/session_backend.cc SessionCommand::SessionCommand(BYTE,WORD) + chrome/browser/session_service.cc SessionService::CreateTabClosedCommand(int) + chrome/browser/session_service.cc SessionService::CommitPendingCloses(void) + chrome/browser/session_service.cc SessionService::UpdateTabNavigation(SessionID const&,int,NavigationEntry const&) + chrome/browser/session_service_unittest.cc SessionServiceTest::UpdateNavigation(SessionID const&,TabNavigation const&,bool) + chrome/browser/session_service_unittest.cc SessionServiceTest_WindowCloseCommittedAfterNavigate_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + +Uninitialized memory read in WriteFile +Error Location + ... + chrome/browser/session_backend.cc SessionBackend::AppendCommandsToFile(void *,vector::std const&) + chrome/browser/session_backend.cc SessionBackend::AppendCommands(vector::std *,bool) + chrome/browser/session_service.cc SessionService::Save(void) + chrome/browser/session_service.cc SessionService::~SessionService(void) + chrome/release/unit_tests.exe SessionService::`scalar deleting destructor'(UINT) + base/ref_counted.h base::RefCountedThreadSafe::Release(void) + base/ref_counted.h scoped_refptr::=(SessionService *) + chrome/browser/session_service_test_helper.h SessionServiceTestHelper::set_service(SessionService *) + chrome/browser/session_service_unittest.cc SessionServiceTest::ReadWindows(vector::std *) + chrome/browser/session_service_unittest.cc SessionServiceTest_ClosingTabStaysClosed_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ +Alloc Location + ... + chrome/browser/session_backend.cc SessionCommand::SessionCommand(BYTE,WORD) + chrome/browser/session_service.cc SessionService::CreateTabClosedCommand(int) + chrome/browser/session_service.cc SessionService::TabClosed(SessionID const&,SessionID const&) + chrome/browser/session_service_unittest.cc SessionServiceTest_ClosingTabStaysClosed_Test::TestBody(void) + testing/gtest/src/gtest.cc testing::Test::Run(void) + ^^^ + diff --git a/chrome/test/data/read_cookies.html b/chrome/test/data/read_cookies.html new file mode 100644 index 0000000..b457c34 --- /dev/null +++ b/chrome/test/data/read_cookies.html @@ -0,0 +1,35 @@ +<html> +<body> +<pre> +<script> + +// This script tests the performance of reading cookies. It sets a cookie and +// then reads cookies N times. Finally, it outputs the average time taken to +// read the cookie. + +document.cookie = + 'one_heck_of_a_crazy_cookie_name=1234567890.1234567890.1234567890.1234567890'; + +var ok = true; + +var num_iters = document.location.search.substring(1) - 0; +if (num_iters == 0) + num_iters = 10000; +document.writeln("num_iters: " + num_iters); + +var ts = (new Date()).getTime(); + +// read the cookie num_iters times +for (var i = 0; i < num_iters; ++i) { + var d = document.cookie; +} + +var te = (new Date()).getTime(); + +var time_per_read = (te - ts) / num_iters; +document.writeln("time per read: " + time_per_read.toFixed(3) + " msec"); + +</script> +</pre> +</body> +</html> diff --git a/chrome/test/data/ref_redirect.html b/chrome/test/data/ref_redirect.html new file mode 100644 index 0000000..e42704a --- /dev/null +++ b/chrome/test/data/ref_redirect.html @@ -0,0 +1,8 @@ +<!-- Test used by RedirectTest.ClientFragments to make sure non-user initiated +location changes (within page) are flagged as client redirects.--> +<html> + <body onload="document.location.href='#myanchor'"> + <a name="myanchor">Anchor</a><br/> + </body> +</html> + diff --git a/chrome/test/data/resource.h b/chrome/test/data/resource.h new file mode 100644 index 0000000..7008da4 --- /dev/null +++ b/chrome/test/data/resource.h @@ -0,0 +1,23 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resource.rc +// +#define IDS_SIMPLE 101 +#define IDS_PLACEHOLDERS 102 +#define IDS_PLACEHOLDERS_2 103 +#define IDS_PLACEHOLDERS_3 104 + +#define IDS_LOCALE_BOOL 105 +#define IDS_LOCALE_INT 106 +#define IDS_LOCALE_STRING 107 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/chrome/test/data/resource.rc b/chrome/test/data/resource.rc new file mode 100644 index 0000000..767b9db --- /dev/null +++ b/chrome/test/data/resource.rc @@ -0,0 +1,80 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_SIMPLE "Hello World!" + IDS_PLACEHOLDERS "Hello, $1. Your number is $2." + IDS_PLACEHOLDERS_2 "You owe me $$$1." + IDS_PLACEHOLDERS_3 "Hello, $2. Your number is $1." + IDS_LOCALE_BOOL "false" + IDS_LOCALE_INT "1" + IDS_LOCALE_STRING "hello" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/chrome/test/data/safe_browsing/download_update.py b/chrome/test/data/safe_browsing/download_update.py new file mode 100644 index 0000000..6b100376 --- /dev/null +++ b/chrome/test/data/safe_browsing/download_update.py @@ -0,0 +1,33 @@ +import urllib,sys + + +url = 'http://safebrowsing.clients.google.com/safebrowsing/downloads?client=googleclient&appver=1.0&pver=2.1' + +if len(sys.argv) == 1: + data = 'goog-phish-shavar;\ngoog-malware-shavar;\n' +else: + post_data_file = sys.argv[1] + file = open(post_data_file, "r") + data = file.read() + file.close + +response = urllib.urlopen(url, data) + +response_file = open("response", "r+") +response_file.write(response.read()) +response_file.seek(0) + +counter = 0 + +for line in response_file: + if not line.startswith('u:'): + continue + + chunk_url = 'http://' + line[2:] + filename = chunk_url[chunk_url.rfind('/') + 1:] + filename = "%03d" % counter + filename[0:filename.rfind('_')] + counter += 1 + + urllib.urlretrieve(chunk_url, filename) + +response_file.close()
\ No newline at end of file diff --git a/chrome/test/data/safe_browsing/initial/000goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/000goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..2f70434 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/000goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/001goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/001goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..dd660ae --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/001goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/002goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/002goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..7d81aef --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/002goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/003goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/003goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..0f18dea --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/003goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/004goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/004goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..156d187 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/004goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/005goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/005goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..66f35f3 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/005goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/006goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/006goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..c13fbc3 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/006goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/007goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/007goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..8e30acb --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/007goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/008goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/008goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..58ccc45 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/008goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/009goog-malware-shavar_s b/chrome/test/data/safe_browsing/initial/009goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..ebca6c6 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/009goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/010goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/010goog-malware-shavar_a Binary files differnew file mode 100644 index 0000000..0bed13ca --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/010goog-malware-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/011goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/011goog-malware-shavar_a Binary files differnew file mode 100644 index 0000000..dac6efd --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/011goog-malware-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/012goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/012goog-malware-shavar_a Binary files differnew file mode 100644 index 0000000..06abcc5 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/012goog-malware-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/013goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/013goog-malware-shavar_a Binary files differnew file mode 100644 index 0000000..0b1b2ce --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/013goog-malware-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/014goog-malware-shavar_a b/chrome/test/data/safe_browsing/initial/014goog-malware-shavar_a Binary files differnew file mode 100644 index 0000000..27500b2 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/014goog-malware-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/015goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/015goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..5571b11 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/015goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/016goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/016goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..588a9c3 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/016goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/017goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/017goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..a18cfc5 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/017goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/018goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/018goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..a6b7fad --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/018goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/019goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/019goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..672d40b --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/019goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/020goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/020goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..2b551cb --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/020goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/021goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/021goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..3bffe0f --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/021goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/022goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/022goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..d441b11 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/022goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/023goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/023goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..0593ff6 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/023goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/024goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/024goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..a08966a --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/024goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/025goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/025goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..cbc6de3 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/025goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/026goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/026goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..d77f24d --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/026goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/027goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/027goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..7469338 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/027goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/028goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/028goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..a317a27 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/028goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/029goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/029goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..cefbff0 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/029goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/030goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/030goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..458f1ab --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/030goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/031goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/031goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..415b39e --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/031goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/032goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/032goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..b31ed3746 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/032goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/033goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/033goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..9ca635a --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/033goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/034goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/034goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..57cccd6 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/034goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/035goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/035goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..0f4f981 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/035goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/036goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/036goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..f3a46d2 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/036goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/037goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/037goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..3c35575 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/037goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/038goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/038goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..9230663 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/038goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/039goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/039goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..32cdec4 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/039goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/040goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/040goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..bc32d54 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/040goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/041goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/041goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..2ff0a2a --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/041goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/042goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/042goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..586cbff --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/042goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/043goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/043goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..ad319749 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/043goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/044goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/044goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..6622fba --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/044goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/045goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/045goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..107d5d4 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/045goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/046goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/046goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..e8c6b9e --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/046goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/047goog-phish-shavar_s b/chrome/test/data/safe_browsing/initial/047goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..cd99328 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/047goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/initial/048goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/048goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..9f0a267 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/048goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/049goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/049goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..fab1ea4 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/049goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/050goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/050goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..2ed4261 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/050goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/051goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/051goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..b5206f7 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/051goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/initial/052goog-phish-shavar_a b/chrome/test/data/safe_browsing/initial/052goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..e3634f4 --- /dev/null +++ b/chrome/test/data/safe_browsing/initial/052goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/old/SafeBrowsing b/chrome/test/data/safe_browsing/old/SafeBrowsing Binary files differnew file mode 100644 index 0000000..5a51ecd --- /dev/null +++ b/chrome/test/data/safe_browsing/old/SafeBrowsing diff --git a/chrome/test/data/safe_browsing/old/postdata b/chrome/test/data/safe_browsing/old/postdata new file mode 100644 index 0000000..a049fbb --- /dev/null +++ b/chrome/test/data/safe_browsing/old/postdata @@ -0,0 +1,2 @@ +goog-malware-shavar;a:8,10,29,38,40-43,63-86,88-115,118-126,128-134,136-142,144-148,150-159,161-168,170-177,179-180,184-186,188-190,192-196,198-211,213-244,246-251,253,262,269-299,301-308,310-313,329-331,333-346,348-366,368-413,415-416,418-419,421-532,534-535,537-539,541-583,585-589,591-617,619-623,625,627-632,634-637,639,645,647-648,650,652,663-664,666-669,673-674,680,684-685,687-688,691-692,695,697,699-701,705,708-711,713-714,716,718,720-727,730-731,734,741,748-751,754-755,760,764,766-767,771-772,776-780,782-784,786,789-790,793,796-799,801-804,806,808,812-814,816-817,820-821,824-826,829-831,833,836-839,841,843-845,847,849-850,852,854-857,861-864,869,871-873,875-878,884-885,888-889,891-893,895-898,900-903,909-914,919,921,923-932,934-941,944-946,949,953-954,958,962,964-967,970-971,974-977,979-981,985-987,989-991,993,1000-1001,1003,1005,1008-1009,1013,1019,1022-1023,1026-1027,1029-1031,1035-1038,1040,1049,1051,1053-1055,1063-1067,1069,1071-1072,1075-1077,1083,1087,1089,1093-1094,1096,1099-1101,1103,1106-1107,1110-1111,1115,1118-1119,1122,1126,1128-1129,1134,1139-1140,1146-1148,1150-1152,1154-1155,1157-1158,1162-1164,1170,1172,1175-1177,1179-1180,1182-1183,1185,1188,1192-1193,1197-1198,1200-1205,1207,1209,1212-1213,1216,1219,1222-1224,1226-1227,1229-1230,1233-1235,1238,1243-1244,1246,1250,1255-1256,1263,1265-1267,1270,1272-1273,1275-1276,1279,1281,1284-1285,1289-1290,1292-1293,1296,1299-1300,1303-1308,1310,1313-1314,1316-1324,1329,1333,1336,1343,1346,1348-1349,1351,1353,1355-1356,1359-1360,1362,1368,1374,1378-1387,1390-1391,1394-1395,1398-1399,1402-1403,1407,1411,1413,1416-1417,1419,1423,1425-1427,1431-1432,1434-1436,1438-1445,1448-1450,1452-1453,1455-1456,1458-1464,1466-1467,1469,1473,1477-1478,1482,1484,1486-1487,1490,1493,1497-1532,1535-1540,1542-1571,1573-1575,1577-1579,1581-1583,1585,1588-1592,1594,1597,1600,1607-1611,1618,1620-1627,1629-1631,1633,1693,1696,1726,1729,1731-1732,1738-1739,1742,1746-1749,1752-1755,1758,1773-1774,1792,1820,1823-1826,1851,1879,1884,1888,1894,1897,1901-1903,1906,1911-1912,1915,1919,1932,1936,1950,1953-1954,1956,1961-1962,1964-1965,1968-1972,1974,1976-1978,1981,1983,1989,1992,2000,2002-2007,2010-2011,2017,2025-2029,2031-2047,2065-2067,2071-2072,2074,2085,2091,2093-2096,2098-2102,2104,2107-2133,2135-2136,2138-2139,2141,2143-2169,2183-2192,2194-2198,2200-2208,2210-2218,2221,2224,2227,2260,2330-2331,2372,2378,2384-2387,2390,2392,2395,2397-2398,2400,2428-2431,2433-2441,2445-2446,2448-2449,2451-2455,2457,2462,2464,2466-2469,2471-2473,2475,2479-2486,2488-2496,2498-2502,2505,2508,2510,2512,2516,2518,2520-2535,2543-2546,2548-2551,2557,2561,2563-2565,2570-2578,2583,2585-2587,2589,2592-2593,2596-2607,2610,2615,2619-2622,2625-2627,2631-2632,2640-2649,2651,2653-2656,2664-2665,2668-2672,2674-2675,2679,2681,2683,2691-2692,2695-2700,2702-2721,2723-2726,2728-2736,2738,2742-2743,2745-2776,2778-2779,2781,2783,2785-2786,2790-2792,2794,2797-2978,2980-3186,3188-3190,3193-3197,3199-3205,3207-3208,3210-3211,3215-3216,3218-3219,3221,3223,3227-3229,3231-3232,3234-3237,3240,3242-3243,3245-3246,3249-3250,3252-3256,3258,3260,3263-3266,3268-3277,3279-3280,3284,3286,3289,3291-3295,3297,3299-3302,3305,3307-3311,3313-3326,3328-3331,3336-3338,3342,3345-3349,3351-3377,3379,3381-3383,3385-3391,3394-3399,3405-3420,3423-3424,3430,3432,3434,3436,3439-3742,3746-3747,3749,3751,3753-3786,3788-3789,3791-3792,3794-3803,3805-3809,3813-3918,3920,3922,3924,3926-3927,3929-3933,3935-3939,3941,3943-3945,3947-3957,3960-3961,3963-3966,3968-3970,3972-3973,3976,3978-3981,3983-4003,4005,4007-4008,4011-4023,4025,4027-4032,4034-4045,4047-4062,4065,4068-4070,4072-4073,4075-4080,4082-4083,4085-4095,4097-4100,4104-4114,4116-4122,4124-4127,4129-4141,4143-4149,4151-4159,4161-4170,4172-4197:s:1-3940
+goog-phish-shavar;a:27,60,79,90,93,105-106,3257,3331-3332,3338-3339,3347-3349,3351,3356-3358,3371,3442,3475,3478,3491,3498,3517,3576,3590-3591,3600-3602,3612,3715,3722-3723,3728,3733,3853,3997,4041-4043,4111,4152,4173-4174,4243,4258,4260,4275,4279,4305,4323,4330,4386,4403,4415,4520,4556,4562,4660-4661,4669,4679-4680,4684,4741,4814,4816,4822,4933,4938,4940,4961,4964,5068,5079,5081,5084,5110-5111,5116,5140,5193,5222,5236,5250,5313,5328,5351,5353,5358,5394-5395,5412,5444,5461-5463,5466-5467,5470,5475,5518-5519,5574,5587,5623,5714-5715,5730-5731,5734,5772,5810,5877,5939,5955,5957,6028,6039,6076,6084,6089,6120,6122,6147,6165,6177,6233,6280,6286,6364,6391,6407-6408,6429,6479,6508-6509,6537,6541,6551,6553,6572-6574,6576,6578-6580,6582-6583,6585-6587,6589-6598,6600,6603-6605,6607-6613,6615,6617-6618,6620-6625,6627-6632,6634-6635,6637-6638,6641-6642,6644-6649,6651-6652,6655-6657,6659,6661-6668,6670-6693,6695,6697-6699,6701-6706,6708-6728,6730-6732,6734,6736-6752,6754-6757,6759-6798,6800-6830,6832-6838,6840,6842-6844,6846-6852,6854,6856-6865,6867-6869,6872-6876,6878,6880-6886,6888-6910,6912,6914-6916,6918-6933,6935-6950,6953-6954,6957-6959,6963,6965-6977,6979-6980,6982-6992,6994-6999,7001-7008,7010-7012,7014-7023,7025-7027,7029-7037,7039-7063,7065-7078,7080-7084,7087-7088,7090-7106,7108-7116,7118-7121,7123,7126-7134,7136-7142,7144-7150,7152-7159,7161-7173,7175-7188,7191-7192,7194-7200,7202-7207,7209-7221,7223-7226,7228-7230,7232-7234,7236-7246,7248-7252,7255-7259,7261-7262,7264-7276,7278-7280,7282-7284,7286-7291,7293-7300,7302-7328,7330-7336,7338-7341,7343-7347,7349-7369,7371-7375,7377-7379,7381-7390,7396-7401,7403-7404,7406,7409-7410,7412-7414,7417-7427,7429-7430,7432-7435,7437-7443,7445-7447,7449-7451,7453-7456,7458,7460,7462-7477,7480-7489,7491,7493-7495,7497-7498,7500-7501,7503,7505,7507-7510,7512-7513,7515-7520,7522-7531,7533-7537,7540-7549,7551-7552,7554,7556,7558-7561,7563-7585,7587-7590,7593-7595,7597,7599-7608,7610-7612,7614-7616,7618-7624,7626,7628-7635,7637-7638,7640-7648,7650-7653,7655-7660,7662-7684,7686-7723,7726-7750,7752-7757,7759-7765,7768-7783,7786-7789,7791-7805,7807-7809,7811-7813,7815-7821,7823-7841,7843-7857,7859-7870,7872,7874-7876,7878-7879,7881,7883-7891,7893-7897,7899-7902,7904-7906,7908-7918,7920-7926,7928-7946,7948-8008,8010-8016,8018-8019,8021-8024,8026-8029,8031,8033-8045,8048-8049,8051-8087,8089-8134,8136-8146,8148-8152,8155-8195,8197-8215,8217-8219,8221-8222,8224-8259,8261-8263,8266-8282,8284-8287,8289-8292,8294,8296-8297,8300-8302,8304-8307,8309-8335,8337-8339,8341-8356,8358-8359,8361-8391,8393-8399,8402,8404-8409,8412-8419,8421-8425,8427,8431-8433,8435-8439,8441-8443,8446,8448-8464,8466,8468-8469,8471-8478,8480-8497,8499-8500,8502-8504,8506-8507,8510-8511,8513-8517,8519-8522,8524-8525,8527-8531,8533,8538-8539,8541-8546,8548-8552,8554-8570,8572,8574-8576,8578,8580-8597,8599-8619,8621-8638,8640-8661,8663-8684,8686-8689,8691-8706,8708-8731,8733-8736,8738-8762,8764-8777,8779-8782,8785-8788,8790-8797,8799-8801,8803-8813,8815-8833,8835-8837,8839-8848,8851-8856,8858-8867,8869-8890,8892-8893,8895-8899,8901-8915,8919-8925,8927,8932,8936-8940,8942-8943,8946,8948-8949,8951-8952,8955,8957,8959-8967,8970-8973,8975-8990,8992-8997,8999-9015,9017-9018,9020-9023,9025-9028,9030-9032,9034-9038,9040-9041,9044-9053,9055,9057-9058,9060-9127,9129-9138,9140-9142,9144-9150,9152,9154-9169,9171,9173-9178,9181-9183,9185-9197,9199-9202,9205-9209,9211-9212,9214-9215,9218-9219,9221-9232,9234-9238,9240-9278,9280-9287,9289,9291,9293-9303,9305-9306,9308-9310,9313-9315,9317-9321,9323-9326,9328-9331,9333,9335,9337,9339-9341,9343-9349,9352-9353,9355,9357-9362,9364-9367,9370-9382,9384-9401,9404-9406,9408-9411,9413-9424,9426-9444,9446-9448,9450-9465,9468-9471,9473-9475,9477,9479-9483,9486-9489,9491-9500,9502-9530,9532-9533,9535-9553,9555-9595,9597-9601,9603-9604,9606-9623,9625-9646,9648-9675,9677-9681,9683-9690,9692-9693,9695-9699,9701-9737,9739-9803,9805-9825,9827-9850,9852-9868,9870-9900,9902-9938,9940-9981,9983-10012,10014-10080,10082-10092,10094-10098,10100-10109,10111-10123,10125-10140,10142-10158,10160-10174,10176-10217,10219-10226,10228-10234,10236-10238,10241-10251,10253-10267,10271-10284,10286-10300,10302-10303,10305-10314,10316-10318,10320-10321,10323-10327,10329-10337,10339-10344,10346-10359,10361-10366,10368-10393,10395-10424,10426-10463,10465-10467,10470-10481,10484-10498,10501-10548,10550-10575,10578-10589,10591-10705,10707-10722,10724-10733,10735-10739,10741-10758,10760-10781,10783-10873,10875-10929,10931-10994,10996-11004,11006-11029,11031-11039,11041-11067:s:1-2045,2051-2060,2066-2100,2106-2110,2116-2145,2151-2160,2171-2180,2196-2260,2266-2280,2286-2325,2331-9209
diff --git a/chrome/test/data/safe_browsing/old/response b/chrome/test/data/safe_browsing/old/response new file mode 100644 index 0000000..9e8dc94 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/response @@ -0,0 +1,48 @@ +n:1835
+i:goog-malware-shavar
+ad:8,38,40-43,67,75,105,112-113,141,148,196,250-251,253,277,280,289,340,368,371,409,425,475,507,575,609,614,632,637,668,673,691,695,697,701,709-711,714,718,720-722,725-727,734,748,750,764,766,772,776,790,798-799,801,813,816,836,838-839,850,855,862,864,872,892,898,911,941,987,1001,1023,1026,1029,1031,1065,1069,1087,1094,1100,1107,1111,1115,1126,1129,1158,1172,1177,1182,1198,1202-1203,1219,1224,1230,1233-1234,1244,1265,1267,1275,1304,1314,1343,1346,1356,1359-1360,1368,1374,1391,1411,1413,1417,1427,1436,1444-1445,1452-1453,1455-1456,1459-1460,1462,1477,1484,1493,1510,1512,1539,1546,1554,1574,1594,1629,1726,1748,1753-1754,1774,1792,1824-1826,1884,1894,1897,1901-1903,1906,1974,1983,2026,2029,2036-2037,2041,2043,2045,2065,2116,2186,2192,2200,2204,2217-2218,2433,2437,2453,2455,2462,2464,2510,2535,2543,2546,2557,2585,2587,2592,2596-2597,2615,2645-2646,2691-2692,2698-2699,2711,2723,2753,2768-2769,2771,2783,2792,2794,2819,2842,2911,3032,3197,3208,3216,3221,3229,3234,3236-3237,3242,3255,3258,3265,3272-3274,3280,3286,3291-3294,3305,3328,3394,3423,3434,3746,3754,3785-3786,3797,3799,3806-3807,3896,3914,3917,3924,3927,3937,3941,3945,3952,3957,3969,3978-3979,3981,3984-3986,3991,3993,4015,4020-4022,4029-4030,4034,4038,4048,4051-4054,4069,4072,4076,4078,4080,4082,4085,4088-4089,4094,4104,4107,4114,4119-4121,4124,4126,4129,4131,4135,4139,4147,4152-4153,4158-4159,4163-4165,4167,4169,4178,4180,4182,4184,4187,4189-4191
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_3921-4000:3921-4000
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4001-4080:4001-4080
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4081-4160:4081-4160
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4161-4240:4161-4240
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4241-4280:4241-4280
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4281-4320:4281-4320
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4321-4400:4321-4400
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4401-4480:4401-4418
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_4161-4320:4161-4162,4166,4168,4170,4172-4177,4179,4181,4183,4185-4186,4188,4192-4198,4208-4215,4219,4221-4224,4226-4231,4233-4235,4240-4242,4244-4246,4248-4251,4253-4262,4265-4269,4272,4274,4276-4279,4281-4283,4285-4289,4291-4300,4302-4303,4305-4311,4313-4314,4316,4318-4320
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_4321-4480:4321-4324,4326-4342,4344-4347,4349-4352,4354,4356,4358-4373,4375-4381,4383-4386,4389-4394,4396-4399,4401-4407,4409-4411,4413,4416-4423,4425-4426,4428,4430-4435,4438-4446,4448-4456,4458-4464,4466-4477,4479-4480
+u:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_4481-4640:4481-4503,4505-4513,4515-4518,4520-4530
+i:goog-phish-shavar
+ad:27,60,90,93,105-106,3257,3331-3332,3338-3339,3347-3349,3351,3356-3358,3371,3442,3475,3478,3491,3498,3517,3576,3590-3591,3600-3602,3612,3715,3722-3723,3728,3733,3853,3997,4041-4043,4111,4152,4173-4174,4243,4258,4260,4275,4279,4305,4323,4330,4386,4403,4415,4520,4556,4562,4660-4661,4669,4679-4680,4684,4741,4814,4816,4822,4933,4938,4940,4961,4964,5068,5079,5081,5084,5110-5111,5116,5140,5193,5222,5236,5250,5328,5351,5353,5358,5394-5395,5412,5444,5461-5463,5466-5467,5470,5475,5518-5519,5574,5587,5623,5714,5730-5731,5734,5772,5955,6028,6076,6089,6165,6177,6280,6479,6551,6553,6572-6574,6576,6578-6580,6582-6583,6585-6587,6589-6598,6600,6603-6605,6607-6613,6615,6617-6618,6620-6625,6627-6632,6634-6635,6637-6638,6641-6642,6644-6649,6651-6652,6655-6657,6659,6661-6668,6670-6679,6681-6693,6695,6697-6699,6701-6706,6708-6727,6730-6732,6734,6736-6740,6742-6745,6747-6752,6755-6757,6759-6768,6770-6798,6800-6830,6832-6838,6840,6842-6844,6846-6852,6854,6856-6865,6867-6869,6872-6876,6878,6880-6886,6888-6901,6903,6905-6906,6908-6910,6912,6915,6919-6933,6935-6942,6944-6950,6953-6954,6957-6959,6963,6965-6977,6979-6980,6982-6992,6994-6999,7001,7004-7007,7012,7014-7023,7025-7027,7029-7032,7034-7037,7039-7040,7043,7045,7047,7049-7057,7061-7063,7065-7078,7080-7084,7087-7088,7090-7106,7108-7116,7118-7121,7123,7126-7130,7132,7136-7142,7146-7150,7152-7159,7161-7163,7165-7170,7172,7175-7179,7181-7188,7191-7192,7194-7200,7202-7207,7209-7219,7221,7223-7226,7228-7230,7232-7234,7236,7238-7246,7248-7252,7255-7257,7259,7261-7262,7265,7267-7276,7278-7280,7282-7284,7287,7289-7291,7293-7300,7302-7306,7308,7310-7328,7330-7336,7338-7341,7343,7345-7347,7349-7369,7371-7375,7377-7379,7381-7390,7396-7401,7403-7404,7406,7409-7410,7412-7414,7417-7427,7429-7430,7432-7435,7437-7443,7445-7447,7449-7451,7453-7456,7458,7460,7462-7477,7480-7489,7493-7495,7497-7498,7500-7501,7503,7505,7507-7509,7512-7513,7515-7517,7519-7520,7522-7526,7528-7531,7533-7537,7540-7549,7551-7552,7554,7556,7558-7561,7563-7585,7587-7590,7593-7595,7597,7599-7608,7610-7612,7614-7616,7618-7624,7626,7628-7629,7631-7632,7634,7638,7640-7648,7650-7651,7653,7655-7660,7662-7675,7678-7684,7686-7723,7726-7736,7739-7750,7752-7757,7759-7765,7768-7775,7777-7783,7786-7789,7791-7805,7807-7809,7811-7813,7815-7821,7823-7841,7843-7857,7859-7870,7872,7874-7876,7878-7879,7881,7883-7887,7889-7891,7893-7897,7899-7902,7904-7906,7908-7909,7911-7913,7915,7917-7918,7920-7925,7928-7946,7948-8008,8010-8016,8018-8019,8021-8024,8026-8029,8031,8033-8045,8048-8049,8052-8087,8089-8134,8136-8146,8148-8152,8155-8176,8178-8179,8181-8195,8197-8215,8217-8219,8221-8222,8224-8234,8236-8259,8261-8263,8266-8282,8284-8287,8289-8292,8294,8296-8297,8300-8302,8304-8307,8309-8335,8337-8339,8341,8343-8356,8358-8359,8361-8391,8393-8399,8402,8404-8409,8412-8419,8421-8425,8427,8431-8433,8435-8439,8441-8443,8446,8448-8464,8466,8468-8469,8471-8478,8480-8497,8499-8500,8502-8504,8506-8507,8510-8511,8513-8517,8519-8522,8524-8525,8527-8531,8533,8538-8539,8541-8543,8545-8546,8548-8552,8554-8562,8564-8570,8572,8574-8576,8578,8580-8597,8599-8619,8621-8636,8638,8640-8661,8663-8674,8676-8684,8686-8689,8691-8701,8703,8705-8706,8708-8712,8714-8729,8731,8733-8736,8738-8743,8746-8762,8764-8777,8779-8782,8785-8788,8790-8795,8797,8799-8801,8803-8813,8815-8821,8823-8824,8826-8833,8835-8837,8839-8848,8851-8856,8859,8861-8867,8869-8890,8892-8893,8895-8899,8901-8915,8919-8925,8927,8932,8936-8940,8942-8943,8946,8949,8952,8955,8957,8960-8961,8963-8967,8970-8973,8975-8990,8992-8995,8999-9012,9014-9015,9020-9021,9023,9025-9028,9030-9032,9034-9038,9040-9041,9045,9065,9073,9079,9100-9101,9107,9169,9187,9189,9193,9205,9215,9229-9230,9232,9234-9235,9241,9249,9253,9274,9276,9293,9333,9349,9373,9377,9382,9392,9394,9457,9528,9544,9558,9569,9572,9606,9677,9722,9748,9757,9808,9821,9866,9888,9891,9895,9916,9935,9957,9965,9969,9979,9986,10002,10005,10007,10023,10033,10051,10076,10078,10080,10098,10111,10193,10213-10214,10222,10224,10230,10237,10250,10272,10279,10434,10456,10481,10527,10584,10732,10813,10844-10845,10852,10911,10913,10956,10969,10982,10994,11008,11017,11032,11035,11055-11056,11058-11059,11064
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9121-9280:9121-9280
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9281-9440:9281-9440
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9441-9600:9441-9600
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9601-9760:9601-9760
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9761-9920:9761-9920
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_9921-10080:9921-10080
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10081-10240:10081-10240
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10241-10400:10241-10303,10305-10306,10308-10309,10311-10313,10316-10323,10325-10335,10337-10344,10346,10349-10351,10353,10356-10361,10363-10370,10372-10373,10375-10378,10380-10394,10396-10399
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10401-10405:10401-10405
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10411-10415:10411-10415
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10426-10430:10426-10430
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10431-10435:10432-10435
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10436-10440:10436,10438-10440
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10441-10460:10441-10445,10447,10449-10456,10458-10459
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10461-10465:10461-10463,10465
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10481-10485:10481,10483-10485
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10491-10495:10491,10493-10494
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10501-10520:10501-10502,10506-10510,10513-10520
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10521-10525:10521-10525
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10531-10535:10531-10535
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10536-10540:10536-10540
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10546-10550:10546,10548-10550
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10551-10555:10551-10555
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10561-10720:10561-10568,10571-10578,10580-10600,10602-10610,10612-10614,10616-10618,10620-10630,10632-10636,10638-10644,10646-10647,10649-10660,10662-10665,10667-10673,10675,10677-10694,10696-10697,10699-10704,10708-10709,10711-10719
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10721-10880:10721,10723-10726,10728-10730,10732,10734-10736,10738,10741-10753,10755-10756,10758,10760-10761,10763-10767,10770,10772-10774,10776-10777,10780-10781,10783-10790,10792-10816,10818-10824,10826-10828,10830-10848,10851-10853,10855-10856,10858-10862,10864,10866-10880
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_10881-11040:10881-10915,10917-10921,10923-10924,10926-10927,10929-10935,10937-10949,10951-10952,10954-11012,11014-11040
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_11041-11200:11041,11043-11046,11048-11086
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_12801-12960:12801-12814,12816-12827,12830-12833,12835-12870,12873-12878,12880-12883,12885-12888,12890-12932,12934-12937,12939-12944,12946-12953,12955-12957,12959-12960
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_12961-13120:12961,12963-12969,12971-12973,12975-13012,13014-13048,13050-13076,13078-13120
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_13121-13280:13121-13169,13171-13188,13190-13196,13198-13207,13209-13280
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_13281-13440:13281-13392,13394-13406,13408-13440
+u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_13441-13600:13441-13453,13455-13511,13513-13596
diff --git a/chrome/test/data/safe_browsing/old/updates/000goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/000goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..c13fbc3 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/000goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/001goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/001goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..8e30acb --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/001goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/002goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/002goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..58ccc45 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/002goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/003goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/003goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..ebca6c6 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/003goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/004goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/004goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..83762db --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/004goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/005goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/005goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..e815f48 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/005goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/006goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/006goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..67aaa32 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/006goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/007goog-malware-shavar_s b/chrome/test/data/safe_browsing/old/updates/007goog-malware-shavar_s Binary files differnew file mode 100644 index 0000000..bfdf3ae0 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/007goog-malware-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/008goog-malware-shavar_a b/chrome/test/data/safe_browsing/old/updates/008goog-malware-shavar_a Binary files differnew file mode 100644 index 0000000..567036e --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/008goog-malware-shavar_a diff --git a/chrome/test/data/safe_browsing/old/updates/009goog-malware-shavar_a b/chrome/test/data/safe_browsing/old/updates/009goog-malware-shavar_a Binary files differnew file mode 100644 index 0000000..530176e --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/009goog-malware-shavar_a diff --git a/chrome/test/data/safe_browsing/old/updates/010goog-malware-shavar_a b/chrome/test/data/safe_browsing/old/updates/010goog-malware-shavar_a Binary files differnew file mode 100644 index 0000000..86aeae0 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/010goog-malware-shavar_a diff --git a/chrome/test/data/safe_browsing/old/updates/011goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/011goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..b5f45ac --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/011goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/012goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/012goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..f290c4c --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/012goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/013goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/013goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..4fd80ca --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/013goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/014goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/014goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..1d4aaf5 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/014goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/015goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/015goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..1239e9d --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/015goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/016goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/016goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..c6ed638 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/016goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/017goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/017goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..7f6b873 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/017goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/018goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/018goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..376cc76 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/018goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/019goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/019goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..77a5f13 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/019goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/020goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/020goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..b30ea59 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/020goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/021goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/021goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..19fc988 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/021goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/022goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/022goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..e2b1119 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/022goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/023goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/023goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..e0981c9 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/023goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/024goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/024goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..40da8ddf --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/024goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/025goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/025goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..1192843 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/025goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/026goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/026goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..d46be87 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/026goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/027goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/027goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..c0bd6fe --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/027goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/028goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/028goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..db057c3 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/028goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/029goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/029goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..9aab307 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/029goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/030goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/030goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..81d3e0d --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/030goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/031goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/031goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..ed17d3d --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/031goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/032goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/032goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..f3bf19d --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/032goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/033goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/033goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..bdc5225 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/033goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/034goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/034goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..7484012 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/034goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/035goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/035goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..b47101a --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/035goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/036goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/036goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..b968557 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/036goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/037goog-phish-shavar_s b/chrome/test/data/safe_browsing/old/updates/037goog-phish-shavar_s Binary files differnew file mode 100644 index 0000000..9b4c333 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/037goog-phish-shavar_s diff --git a/chrome/test/data/safe_browsing/old/updates/038goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/038goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..1010871 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/038goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/old/updates/039goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/039goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..666eeba --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/039goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/old/updates/040goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/040goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..435c037 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/040goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/old/updates/041goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/041goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..e13aab7 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/041goog-phish-shavar_a diff --git a/chrome/test/data/safe_browsing/old/updates/042goog-phish-shavar_a b/chrome/test/data/safe_browsing/old/updates/042goog-phish-shavar_a Binary files differnew file mode 100644 index 0000000..7179c57 --- /dev/null +++ b/chrome/test/data/safe_browsing/old/updates/042goog-phish-shavar_a diff --git a/chrome/test/data/save_page/1.css b/chrome/test/data/save_page/1.css new file mode 100644 index 0000000..750524d --- /dev/null +++ b/chrome/test/data/save_page/1.css @@ -0,0 +1,3 @@ +body { + font-size: 20px; +}
\ No newline at end of file diff --git a/chrome/test/data/save_page/1.png b/chrome/test/data/save_page/1.png Binary files differnew file mode 100644 index 0000000..393f0ea --- /dev/null +++ b/chrome/test/data/save_page/1.png diff --git a/chrome/test/data/save_page/a.htm b/chrome/test/data/save_page/a.htm new file mode 100644 index 0000000..986258b --- /dev/null +++ b/chrome/test/data/save_page/a.htm @@ -0,0 +1,10 @@ +<html> + <head> + <title> + Test page for saving page feature + </title> + </head> + <body> + Can you see this sentence? + </body> +</html>
\ No newline at end of file diff --git a/chrome/test/data/save_page/b.htm b/chrome/test/data/save_page/b.htm new file mode 100644 index 0000000..485468b --- /dev/null +++ b/chrome/test/data/save_page/b.htm @@ -0,0 +1,12 @@ +<html> + <head> + <title> + Test page for saving page feature + </title> + <link type="text/css" href="1.css" rel="stylesheet"> + </head> + <body> + The picture below is the back button.<br> + <img src="1.png"> </img> + </body> +</html>
\ No newline at end of file diff --git a/chrome/test/data/serializer_nested_test.js b/chrome/test/data/serializer_nested_test.js new file mode 100644 index 0000000..cfea8e8 --- /dev/null +++ b/chrome/test/data/serializer_nested_test.js @@ -0,0 +1,17 @@ +{ + "bool": true, + "dict": { + "bool": true, + "dict": { + "bees": "knees", + "cats": "meow" + }, + "foos": "bar", + "list": [ 3.4, "second", null ] + }, + "int": 42, + "list": [ 1, 2 ], + "null": null, + "real": 3.14, + "string": "hello" +} diff --git a/chrome/test/data/serializer_test.js b/chrome/test/data/serializer_test.js new file mode 100644 index 0000000..446925e --- /dev/null +++ b/chrome/test/data/serializer_test.js @@ -0,0 +1,8 @@ +{ + "bool": true, + "int": 42, + "list": [ 1, 2 ], + "null": null, + "real": 3.14, + "string": "hello" +} diff --git a/chrome/test/data/serializer_test_nowhitespace.js b/chrome/test/data/serializer_test_nowhitespace.js new file mode 100644 index 0000000..a1afdc5 --- /dev/null +++ b/chrome/test/data/serializer_test_nowhitespace.js @@ -0,0 +1 @@ +{"bool":true,"int":42,"list":[1,2],"null":null,"real":3.14,"string":"hello"}
\ No newline at end of file diff --git a/chrome/test/data/server-unavailable.html b/chrome/test/data/server-unavailable.html new file mode 100644 index 0000000..364322d --- /dev/null +++ b/chrome/test/data/server-unavailable.html @@ -0,0 +1 @@ +This file is boring; all the action's in the .mock-http-headers. diff --git a/chrome/test/data/server-unavailable.html.mock-http-headers b/chrome/test/data/server-unavailable.html.mock-http-headers new file mode 100644 index 0000000..5dd521b --- /dev/null +++ b/chrome/test/data/server-unavailable.html.mock-http-headers @@ -0,0 +1,2 @@ +HTTP/1.0 503 Service Unavailable +Content-type: text/html diff --git a/chrome/test/data/session_history/bot1.html b/chrome/test/data/session_history/bot1.html new file mode 100644 index 0000000..e213c72 --- /dev/null +++ b/chrome/test/data/session_history/bot1.html @@ -0,0 +1,6 @@ +<html> +<head><title>bot1</title></head> +<body> +This is the bottom frame #1. Tests will load here. +</body> +</html> diff --git a/chrome/test/data/session_history/bot2.html b/chrome/test/data/session_history/bot2.html new file mode 100644 index 0000000..5d0228c --- /dev/null +++ b/chrome/test/data/session_history/bot2.html @@ -0,0 +1,6 @@ +<html> +<head><title>bot2</title></head> +<body> +This is the bottom frame #2. +</body> +</html> diff --git a/chrome/test/data/session_history/bot3.html b/chrome/test/data/session_history/bot3.html new file mode 100644 index 0000000..deb7837 --- /dev/null +++ b/chrome/test/data/session_history/bot3.html @@ -0,0 +1,7 @@ +<html> +<head><title>bot3</title></head> +<body> +Bottom frame the third. +</body> +</html> + diff --git a/chrome/test/data/session_history/form.html b/chrome/test/data/session_history/form.html new file mode 100644 index 0000000..f20e02d --- /dev/null +++ b/chrome/test/data/session_history/form.html @@ -0,0 +1,31 @@ +<html> +<head> +<title>form</title> +<script> +// Simulate the user clicking on the submit button. +function submitForm(name) { + var node = document.getElementById(name); + node.click(); +} +// Simulate the user filling a form value. +function fillForm(name, value) { + var node = document.getElementById(name); + node.value = value; +} +</script> +</head> +<body> + +<form method="post" action="/echotitle"> + +<p><input name="text" id="itext"> +<p><select name="select" id="iselect"> + <option selected>a + <option>b + <option>c +</select> +<p><input type="submit" value="Submit" id="isubmit"> + +</form> +</body> +</html> diff --git a/chrome/test/data/session_history/fragment.html b/chrome/test/data/session_history/fragment.html new file mode 100644 index 0000000..b5d6601 --- /dev/null +++ b/chrome/test/data/session_history/fragment.html @@ -0,0 +1,12 @@ +<html> +<head><title>fragment</title></head> +<body> +A page with anchor fragment targets. +<p> +<a name="a">What's this? A reference fragment?</a> +<p> +<a name="b">And another!</a> +<p> +<a name="c">Last one, I promise.</a> +</body> +</html> diff --git a/chrome/test/data/session_history/frames.html b/chrome/test/data/session_history/frames.html new file mode 100644 index 0000000..a28c4e6 --- /dev/null +++ b/chrome/test/data/session_history/frames.html @@ -0,0 +1,45 @@ +<html> +<head> +<title>bot1</title> +<script> +// --- Convenience functions for testing. +function setTitle() { + var fbot = document.getElementById("fbot"); + document.title = fbot.contentDocument.title; +} +// Simulate the user clicking a link. +function clickLink(name) { + var ftop = document.getElementById("ftop"); + var node = ftop.contentDocument.getElementById(name); + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, + false, false, false, false, 0, null); + node.dispatchEvent(evt); +} +// Simulate the user filling a form value. +function fillForm(name, value) { + var fbot = document.getElementById("fbot"); + var node = fbot.contentDocument.getElementById(name); + node.value = value; +} +// Simulate the user clicking on the submit button. +function submitForm(name) { + var fbot = document.getElementById("fbot"); + var node = fbot.contentDocument.getElementById(name); + node.click(); +} +function init() { + var fbot = document.getElementById("fbot"); + // This will set our title to the bottom frame, so we can test that + // we actually navigated. + fbot.onload = setTitle; +} +</script> +</head> + +<frameset onLoad="init()" rows="20%,80%" name="main"> + <frame src="top.html" id="ftop" name="top"> + <frame src="bot1.html" id="fbot" name="bottom"> +</frameset> + +</html> diff --git a/chrome/test/data/session_history/no-title.html b/chrome/test/data/session_history/no-title.html new file mode 100644 index 0000000..ff70517 --- /dev/null +++ b/chrome/test/data/session_history/no-title.html @@ -0,0 +1 @@ +<body>no title specified</body> diff --git a/chrome/test/data/session_history/post.html b/chrome/test/data/session_history/post.html new file mode 100644 index 0000000..ab89b76 --- /dev/null +++ b/chrome/test/data/session_history/post.html @@ -0,0 +1,28 @@ +<html> +<head> +<title>post</title> +<script> +// stolen from darin's page cycler +var options = location.search.substring(1).split('&'); + +function getopt(name) { + var r = new RegExp("^" + name + "="); + for (i = 0; i < options.length; ++i) { + if (options[i].match(r)) { + return options[i].substring(name.length + 1); + } + } + return null; +} + +function checkParams() { + document.title = "post:" + getopt("text") + "," + getopt("select"); +} +checkParams(); +</script> +</head> + +<body> +Form submission accepted. Thanks for playing. +</body> +</html> diff --git a/chrome/test/data/session_history/replace.html b/chrome/test/data/session_history/replace.html new file mode 100644 index 0000000..4c79a6f --- /dev/null +++ b/chrome/test/data/session_history/replace.html @@ -0,0 +1,4 @@ +<html> +<head><title>redirecting</title></head> +<body onload="location.replace(location.search.substring(1))">redirecting...</body> +</html> diff --git a/chrome/test/data/session_history/top.html b/chrome/test/data/session_history/top.html new file mode 100644 index 0000000..70e3c71 --- /dev/null +++ b/chrome/test/data/session_history/top.html @@ -0,0 +1,8 @@ +<html> +<body> +<a href="bot1.html" id="abot1" target="bottom">bot1</a> +<a href="bot2.html" id="abot2" target="bottom">bot2</a> +<a href="bot3.html" id="abot3" target="bottom">bot3</a> +<a href="form.html" id="aform" target="bottom">form</a> +</body> +</html> diff --git a/chrome/test/data/ssl/bad_iframe.html b/chrome/test/data/ssl/bad_iframe.html new file mode 100644 index 0000000..53eff7e --- /dev/null +++ b/chrome/test/data/ssl/bad_iframe.html @@ -0,0 +1,10 @@ +<html> +<script> + window.open('google.html', name, + "status = 1, height = 300, width = 300, resizable = 0" ); +</script> + +<H1>Evil IFrame</H1> +This frame is loaded over insecure HTTPS. + +</html> diff --git a/chrome/test/data/ssl/google.html b/chrome/test/data/ssl/google.html new file mode 100644 index 0000000..3ef1ca1 --- /dev/null +++ b/chrome/test/data/ssl/google.html @@ -0,0 +1,4 @@ +<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Google</title><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{font-size:20px}.h{color:#3366cc}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{float:left;font-weight:bold;height:22px;padding-left:2px}.gbh,.gb2 div{border-top:1px solid #c9d7f1;font-size:0;height:0}.gbh{position:absolute;top:24px;width:100%}.gb2 div{margin:5px}#gbi{background:#fff;border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;font-size:13px;top:24px;z-index:1000}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}.gb2 a{display:block;padding:.2em .5em}}#gbi,.gb2{display:none;position:absolute;width:8em}.gb2{z-index:1001}#gbar a,#gbar a:active,#gbar a:visited{color:#00c;font-weight:normal}.gb2 a,.gb3 a{text-decoration:none}#gbar .gb2 a:hover{background:#36c;color:#fff;display:block}</style><script>window.google={kEI:"BuG9R7b_PI6SoASYhdTtDQ",kEXPI:"17259,17735,17870",kHL:"en"}; +function sf(){document.f.q.focus()} +window.rwt=function(b,d,e,g,h,f,i){var a=encodeURIComponent||escape,c=b.href.split("#");b.href="/url?sa=t"+(d?"&oi="+a(d):"")+(e?"&cad="+a(e):"")+"&ct="+a(g)+"&cd="+a(h)+"&url="+a(c[0]).replace(/\+/g,"%2B")+"&ei=BuG9R7b_PI6SoASYhdTtDQ"+(f?"&usg="+f:"")+i+(c[1]?"#"+c[1]:"");b.onmousedown="";return true}; +window.gbar={};(function(){var a=window.gbar,b,g,h;function l(c,f,e){c.display=h?"none":"block";c.left=f+"px";c.top=e+"px"}a.tg=function(c){var f=0,e=0,d,m=0,n,j=window.navExtra,k,i=document;g=g||i.getElementById("gbar").getElementsByTagName("span");(c||window.event).cancelBubble=!m;if(!b){b=i.createElement(Array.every||window.createPopup?"iframe":"DIV");b.frameBorder="0";b.scrolling="no";b.src="#";g[7].parentNode.appendChild(b).id="gbi";if(j&&g[7])for(n in j){k=i.createElement("span");k.appendChild(j[n]);g[7].parentNode.insertBefore(k,g[7]).className="gb2"}i.onclick=a.close}while(d=g[++m]){if(e){l(d.style,e+1,f+25);f+=d.firstChild.tagName=="DIV"?9:20}if(d.className=="gb3"){do e+=d.offsetLeft;while(d=d.offsetParent)}}b.style.height=f+"px";l(b.style,e,24);h=!h};a.close=function(c){h&&a.tg(c)}})();</script></head><body onload="sf();if(document.images){new Image().src='/images/nav_logo3.png'}" topmargin="3" alink="#ff0000" bgcolor="#ffffff" link="#0000cc" marginheight="3" text="#000000" vlink="#551a8b"><div id="gbar"><nobr><span class="gb1">Web</span> <span class="gb1"><a href="http://images.google.com/imghp?hl=en&tab=wi">Images</a></span> <span class="gb1"><a href="http://maps.google.com/maps?hl=en&tab=wl">Maps</a></span> <span class="gb1"><a href="http://news.google.com/nwshp?hl=en&tab=wn">News</a></span> <span class="gb1"><a href="http://www.google.com/prdhp?hl=en&tab=wf">Shopping</a></span> <span class="gb1"><a href="http://mail.google.com/mail/?hl=en&tab=wm">Gmail</a></span> <span class="gb3"><a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1"><u>more</u> <small>▼</small></a></span> <span class="gb2"><a href="http://video.google.com/?hl=en&tab=wv">Video</a></span> <span class="gb2"><a href="http://groups.google.com/grphp?hl=en&tab=wg">Groups</a></span> <span class="gb2"><a href="http://books.google.com/bkshp?hl=en&tab=wp">Books</a></span> <span class="gb2"><a href="http://scholar.google.com/schhp?hl=en&tab=ws">Scholar</a></span> <span class="gb2"><a href="http://finance.google.com/finance?hl=en&tab=we">Finance</a></span> <span class="gb2"><a href="http://blogsearch.google.com/?hl=en&tab=wb">Blogs</a></span> <span class="gb2"><div></div></span> <span class="gb2"><a href="http://www.youtube.com/?hl=en&tab=w1">YouTube</a></span> <span class="gb2"><a href="http://www.google.com/calendar/render?hl=en&tab=wc">Calendar</a></span> <span class="gb2"><a href="http://picasaweb.google.com/home?hl=en&tab=wq">Photos</a></span> <span class="gb2"><a href="http://docs.google.com/?hl=en&tab=wo">Documents</a></span> <span class="gb2"><a href="http://www.google.com/reader/view/?hl=en&tab=wy">Reader</a></span> <span class="gb2"><div></div></span> <span class="gb2"><a href="http://www.google.com/intl/en/options/">even more »</a></span> </nobr></div><div class="gbh" style="left: 0pt;"></div><div class="gbh" style="right: 0pt;"></div><div id="guser" style="padding: 0pt 0pt 4px; font-size: 84%;" width="100%" align="right"><nobr><b>jcampan@gmail.com</b> | <a href="http://www.google.com/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/ManageAccount">My Account</a> | <a href="http://www.google.com/accounts/Logout?continue=http://www.google.com/">Sign out</a></nobr></div><center><br id="lgpd" clear="all"><img alt="Google" src="google_files/logo.gif" height="110" width="276"><br><br><form action="/search" name="f"><table cellpadding="0" cellspacing="0"><tbody><tr valign="top"><td width="25%"> </td><td align="center" nowrap="nowrap"><input name="hl" value="en" type="hidden"><input maxlength="2048" name="q" size="55" title="Google Search" value=""><br><input name="btnG" value="Google Search" type="submit"><input name="btnI" value="I'm Feeling Lucky" type="submit"></td><td nowrap="nowrap" width="25%"><font size="-2"> <a href="http://www.google.com/advanced_search?hl=en">Advanced Search</a><br> <a href="http://www.google.com/preferences?hl=en">Preferences</a><br> <a href="http://www.google.com/language_tools?hl=en">Language Tools</a></font></td></tr></tbody></table></form><br><br><font size="-1"><a href="http://www.google.com/intl/en/ads/">Advertising Programs</a> - <a href="http://www.google.com/services/">Business Solutions</a> - <a href="http://www.google.com/intl/en/about.html">About Google</a></font><p><font size="-2">©2008 Google</font></p></center></body></html>
\ No newline at end of file diff --git a/chrome/test/data/ssl/google_files/logo.gif b/chrome/test/data/ssl/google_files/logo.gif Binary files differnew file mode 100644 index 0000000..afa22bc --- /dev/null +++ b/chrome/test/data/ssl/google_files/logo.gif diff --git a/chrome/test/data/ssl/page_with_dynamic_mixed_contents.html b/chrome/test/data/ssl/page_with_dynamic_mixed_contents.html new file mode 100644 index 0000000..9ff73bb --- /dev/null +++ b/chrome/test/data/ssl/page_with_dynamic_mixed_contents.html @@ -0,0 +1,36 @@ +<html> +<head><title>Page with dynamic mixed contents</title> + +<script> + function loadBadImage() { + var image = document.getElementById("my_image"); + image.src = "http://localhost:1337/files/ssl/google_files/logo.gif"; + checkForLoadFinished(); + } + + function checkForLoadFinished() { + var image = document.getElementById("my_image"); + if (image.complete) { + document.getElementById("status_text").innerHTML = "Bad image loaded"; + window.domAutomationController.send(true); + } else { + setTimeout("checkForLoadFinished()", 500); + } + } +</script> + +</head> +<body> + +This page has some java-script that loads some mixed contents. +<br><br> +You can also press the button below to load the image. +<br> +<input type=button value="Load image" onclick="loadBadImage();"></input> + +<div id="status_text">Contents is OK</div> +<img id="my_image" src=""/> + + +</body> +</html> diff --git a/chrome/test/data/ssl/page_with_mixed_contents.html b/chrome/test/data/ssl/page_with_mixed_contents.html new file mode 100644 index 0000000..2bf9bb24 --- /dev/null +++ b/chrome/test/data/ssl/page_with_mixed_contents.html @@ -0,0 +1,9 @@ +<html> +<head><title>Page with mixed contents</title></head> +<body> +This page contains an image which is served over an http connection, +causing mixed contents (when this page is loaded over https).<br> +<img src="http://localhost:1337/files/ssl/google_files/logo.gif"/> + +</body> +</html> diff --git a/chrome/test/data/ssl/page_with_refs.html b/chrome/test/data/ssl/page_with_refs.html new file mode 100644 index 0000000..3db0e5d --- /dev/null +++ b/chrome/test/data/ssl/page_with_refs.html @@ -0,0 +1,21 @@ +<html> +<head> +<title>This page has refs</title> +</head> +<a href="#en">English<a><br> +<a href="#fr">Francais<a><br> +<a href="#jp">Japanese<a><br> +<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<h2 id="en">Hello!</h2> +<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<h2 id="fr">Bonjour!</h2><br><br> +<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<h2 id="jp">Konnichiwa</h2><br><br> +<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> +</html> + + diff --git a/chrome/test/data/ssl/page_with_unsafe_contents.html b/chrome/test/data/ssl/page_with_unsafe_contents.html new file mode 100644 index 0000000..907c9ca --- /dev/null +++ b/chrome/test/data/ssl/page_with_unsafe_contents.html @@ -0,0 +1,30 @@ +<html> +<head><title>Page with unsafe contents</title> +<script> + var foo = null; + + function IsFooSet() { + return foo != null; + } + + function ImageWidth() { + return document.getElementById("bad_image").width; + } +</script> +<script src="https://127.0.0.1:9666/files/ssl/set_foo.js"></script> +</head> + +<body> +This page contains an image which is served over an insecure HTTPS connection...<br> +<img id="bad_image" src="https://127.0.0.1:9666/files/ssl/google_files/logo.gif"/> + +<br><br> +And an IFrame served over insecure HTTPS...<br> +<iframe id="bad_iframe" src="https://127.0.0.1:9666/files/ssl/bad_iframe.html"/> + +<br><br> +And even worse, some JavaScript served over insecure HTTPS...<br> + + +</body> +</html> diff --git a/chrome/test/data/ssl/set_foo.js b/chrome/test/data/ssl/set_foo.js new file mode 100644 index 0000000..2dbb5d12 --- /dev/null +++ b/chrome/test/data/ssl/set_foo.js @@ -0,0 +1 @@ +foo = "bar"; diff --git a/chrome/test/data/sync_xmlhttprequest.html b/chrome/test/data/sync_xmlhttprequest.html new file mode 100644 index 0000000..cf3e8d6 --- /dev/null +++ b/chrome/test/data/sync_xmlhttprequest.html @@ -0,0 +1,32 @@ +<html> +<head> +<script> +var request_success = false; + +function OnLoad() { + var request = new XMLHttpRequest(); + request.open("GET", "title1.html", false); + request.send(""); + + var my_div = document.getElementById("my_div"); + if (request.readyState == 4 && request.status == 200) { + request_success = true; + my_div.innerHTML = "Got a successful response: " + request.responseText; + } else { + my_div.innerHTML = "Request failed: ready state=" + request.readyState + + " status=" + request.status; + } +} + +function DidSyncRequestSucceed() { + return request_success; +} + +</script> +</head> +<body onload="OnLoad();"> +This page sends a synchronous XMLHttpRequest. +<br><br> +<div id="my_div"></div> +</body> +</html> diff --git a/chrome/test/data/sync_xmlhttprequest_during_unload.html b/chrome/test/data/sync_xmlhttprequest_during_unload.html new file mode 100644 index 0000000..6b726b1 --- /dev/null +++ b/chrome/test/data/sync_xmlhttprequest_during_unload.html @@ -0,0 +1,20 @@ +<html> + <head> + <title>Loading...</title> + </head> + <body onload="attachUnloadListener()"> + <script> + function attachUnloadListener() { + window.addEventListener('unload', onUnload, false); + document.title = "sync xhr on unload"; + } + + var req = new XMLHttpRequest(); + function onUnload() { + req.open('GET','download-test1.lib', false); + req.send(null); + } + </script> + <p>Navigate to another page to trigger synch xmlhttprequest</p> + </body> +</html> diff --git a/chrome/test/data/title1.html b/chrome/test/data/title1.html new file mode 100644 index 0000000..2526072 --- /dev/null +++ b/chrome/test/data/title1.html @@ -0,0 +1,4 @@ +<html> +<head></head> +<body>This page has no title.</body> +</html> diff --git a/chrome/test/data/title2.html b/chrome/test/data/title2.html new file mode 100644 index 0000000..13823c9 --- /dev/null +++ b/chrome/test/data/title2.html @@ -0,0 +1,4 @@ +<html> +<head><title>Title Of Awesomeness</title></head> +<body>This page has a title.</body> +</html> diff --git a/chrome/test/data/viewsource/test.html b/chrome/test/data/viewsource/test.html new file mode 100644 index 0000000..f27bf2f --- /dev/null +++ b/chrome/test/data/viewsource/test.html @@ -0,0 +1,11 @@ +<html> +<head> +<script> +function setCookie() { + document.cookie = 'viewsource_cookie=foo'; +} +</script> +</head> +<body onload="setCookie();"> +</body> +</html> diff --git a/chrome/test/data/window.close.html b/chrome/test/data/window.close.html new file mode 100644 index 0000000..ebe16868 --- /dev/null +++ b/chrome/test/data/window.close.html @@ -0,0 +1,53 @@ +<script> +var popup, popup2, popup3, popup4; + +// window.open, window.close should be synchronous +function test1() { + popup = window.open('title1.html', 'name'); + popup.close(); + + popup = window.open('title2.html', 'name', 'width=200,height=200'); + popup.close(); +} + +// Try opening/closing a few windows. +function test2() { + openPopups(); + closePopups(); +} + +function test3() { + openPopups(); + setTimeout(closePopups, 0); + setTimeout(test4, 1); +} + +function test4() { + openPopups(); + setTimeout(closePopupsAndDone, 250); +} + +function openPopups() { + popup = window.open('title1.html', 'name'); + popup2 = window.open('title1.html', 'name2'); + popup3 = window.open('title1.html', 'name3'); + popup4 = window.open('title1.html', 'name4'); +} + +function closePopups() { + popup.close(); + popup2.close(); + popup3.close(); + popup4.close(); +} + +function closePopupsAndDone() { + closePopups(); + document.title = "PASSED"; +} + +test1(); +test2(); +test3(); + +</script> diff --git a/chrome/test/debugger/debugger_unittests.py b/chrome/test/debugger/debugger_unittests.py new file mode 100644 index 0000000..bacaa00 --- /dev/null +++ b/chrome/test/debugger/debugger_unittests.py @@ -0,0 +1,50 @@ +# debugger_unittests.py +# +# Run chrome debugger front-end tests. +# see also chrome/test/debugger/test_protocol.js + +import optparse +import os.path +import subprocess +import sys +import time + +import google.path_utils +import google.process_utils + +def RunTests(build_dir=None): + '''This is just a simple wrapper for running the test through v8_shell. + Since v8_shell always returns 0 whether the test passes or fails, buildbot + looks at stdout to test for failure. + ''' + script_dir = google.path_utils.ScriptDir() + chrome_dir = google.path_utils.FindUpward(script_dir, "chrome") + v8_dir = google.path_utils.FindUpward(script_dir, "v8") + if build_dir: + v8_shell = os.path.join(build_dir, "v8_shell.exe") + else: + v8_shell = os.path.join(chrome_dir, "Debug", "v8_shell.exe") + # look for Debug version first + if not os.path.isfile(v8_shell): + v8_shell = os.path.join(chrome_dir, "Release", "v8_shell.exe") + cmd = [v8_shell, + "--allow-natives-syntax", + "--expose-debug-as", "debugContext", # these two are together + os.path.join(chrome_dir, "browser", "resources", "debugger_shell.js"), + os.path.join(v8_dir, "tests", "mjsunit.js"), + os.path.join(chrome_dir, "test", "debugger", "test_protocol.js") + ] + (retcode, output) = google.process_utils.RunCommandFull(cmd, + collect_output=True) + if "Success" in output: + return 0 + else: + return 1 + +if __name__ == "__main__": + parser = optparse.OptionParser("usage: %prog [--build_dir=dir]") + parser.add_option("", "--build_dir", + help="directory where v8_shell.exe was built") + (options, args) = parser.parse_args() + ret = RunTests(options.build_dir) + sys.exit(ret) diff --git a/chrome/test/debugger/debugger_unittests.sh b/chrome/test/debugger/debugger_unittests.sh new file mode 100755 index 0000000..443488d --- /dev/null +++ b/chrome/test/debugger/debugger_unittests.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +system_root=`cygpath "$SYSTEMROOT"` +export PATH="/usr/bin:$system_root/system32:$system_root:$system_root/system32/WBEM" + +exec_dir=$(dirname $0) + +"$exec_dir/../../../third_party/python_24/python.exe" \ + "$exec_dir/debugger_unittests.py" "$@" diff --git a/chrome/test/debugger/test_protocol.js b/chrome/test/debugger/test_protocol.js new file mode 100644 index 0000000..6ca0835 --- /dev/null +++ b/chrome/test/debugger/test_protocol.js @@ -0,0 +1,293 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// test_protocol.js + +/** + * @fileoverview Unit tests for testing debugger protocol betweeen front-end JS + * and back-end. + * Run with the following command line: + * v8_shell.exe --allow-natives-syntax --expose-debug-as debugContext + * chrome/browser/resources/shell.js + * v8/tests/mjsunit.js + * chrome/test/debugger/test_protocol.js + */ + + +/** + * shell() is normally a native function exposed to shell.js in Chrome that + * sets the global DebugShell (shell_) object used for the debugger front-end. + */ +function shell(sh) { + shell_ = sh; + shell_.response("{type: 'event', event: 'attach'}"); +}; + + +/** + * @class The global chrome object has some functions to control some status UI + * in the debugger window. Stub them out here. + */ +function chrome() { +}; +chrome.setDebuggerReady = function(ready) {}; +chrome.setDebuggerBreak = function(brk) {}; + + +/** + * @constructor a pseudo namespace to wrap the various functions and data for + * the test + */ +function DebuggerTest() { +}; + +/** + * initialize the member + */ +DebuggerTest.initialize = function() { + DebuggerTest.pendingCommand = null; + DebuggerTest.output = []; + + // swap out the built-in print with our own so that we can verify output + DebuggerTest.realPrint = print; + print = DebuggerTest.print; + // uncomment this to see more verbose information + //dprint = DebuggerTest.realPrint; + + debugContext.Debug.addListener(DebuggerTest.listener); +}; + +/** + * Collects calls to print() in an array for test verification. + */ +DebuggerTest.print = function(str) { + DebuggerTest.output.push(str); + // uncomment this if you need to trace what's happening while it's happening + // rather than waiting for the end + //DebuggerTest.realPrint(str); +}; + +/** + * Processes pendingCommand and sends response to shell_. Since that may in + * turn generate a new pendingCommand, repeat this until there is no + * pendingCommand. + */ +DebuggerTest.processCommands = function(dcp) { + while (DebuggerTest.pendingCommand) { + var json = DebuggerTest.pendingCommand; + DebuggerTest.pendingCommand = null; + var result = dcp.processDebugJSONRequest(json); + shell_.response(result); + } +}; + +/** + * Handles DebugEvents from the Debug object. Hooked in via addListener above. + */ +DebuggerTest.listener = function(event, exec_state, event_data, data) { + try { + if (event == debugContext.Debug.DebugEvent.Break) { + var dcp = exec_state.debugCommandProcessor(); + // process any pending commands prior to handling the breakpoint + DebuggerTest.processCommands(dcp); + var json = event_data.toJSONProtocol(); + shell_.response(json); + // response() may have added another command to process + DebuggerTest.processCommands(dcp); + } + } catch(e) { + print(e); + } +}; + +/** + * Send the next command from the command-list. + */ +DebuggerTest.sendNextCommand = function() { + var cmd = DebuggerTest.commandList.shift(); + print("$ " + cmd); + shell_.command(cmd); +}; + +/** + * Verify that the actual output matches the expected output + * depends on mjsunit + */ +DebuggerTest.verifyOutput = function() { + // restore print since mjsunit depends on it + print = DebuggerTest.realPrint; + + var out = DebuggerTest.output; + var expected = DebuggerTest.expectedOutput; + if (out.length != expected.length) { + assertTrue(out.length == expected.length, + "length mismatch: " + out.length + " == " + expected.length); + } else { + var succeeded = true; + for (var i in out) { + // match the front of the string so we can avoid testing changes in frames + // that are in the test harness + if (out[i].indexOf(expected[i]) != 0) { + assertTrue(out[i] == expected[i], + "actual '" + out[i] + "' == " + "expected '" + expected[i] + "'"); + succeeded = false; + break; + } + } + if (succeeded) + print("Success"); + } + + // useful for generating a new version of DebuggerTest.expectedOutput + for (var i in DebuggerTest.output) { + //print(" \"" + DebuggerTest.output[i] + "\","); + } +}; + + + +/** + * @class DebugShell is passed a "Tab" object that it uses to communicate with + * the debugger. This mock simulates that. + * @param {string} title + */ +DebuggerTest.TabMock = function(title) { + this.title = title; + this.attach = function() {}; + this.debugBreak = function() { + // TODO(erikkay) + }; + this.sendToDebugger = function(str) { + DebuggerTest.pendingCommand = str; + }; +}; + + +/** + * @class Uses prototype chaining to allow DebugShell methods to be overridden + * selectively. + */ +function DebugShellOverrides() { + this._origPrototype = DebugShell.prototype; +}; +DebugShellOverrides.prototype = DebugShell.prototype; +DebugShell.prototype = new DebugShellOverrides; + +/** + * Overrides DebugShell.prototype.response so that we can log the responses + * and trigger the next command to be processed. + */ +DebugShell.prototype.response = function(str) { + var msg = eval('(' + str + ')'); + print("< " + msg.type + ":" + (msg.command || msg.event)); + var sendAnother = (msg.type == "event"); + if (!sendAnother && shell_.current_command) { + sendAnother = (shell_.current_command.from_user && + msg.type == "response" && msg.command != "continue") + } + this._origPrototype.response.call(this, str) + + // Send the next command, but only if the program is paused (a continue + // command response means that we're about to be running again) and the + // command we just processed isn't a continue + if (!this.running && sendAnother) + DebuggerTest.sendNextCommand(); +}; + + +// The list of commands to be processed +// TODO(erikkay): this doesn't test the full set of debugger commands yet, +// but it should be enough to verify that the protocol is still working. +DebuggerTest.commandList = [ +"next", "step", "backtrace", "source", "print x", "args", "locals", "frame 1", +"stepout", "continue" +]; + +DebuggerTest.expectedOutput = [ + "< event:attach", + "attached to testing", + "< response:scripts", + "< event:break", + "g(), foo.html", + "60: debugger;", + "$ next", + "< response:continue", + "< event:break", + "61: f(1);", + "$ step", + "< response:continue", + "< event:break", + "f(x=1, y=undefined), foo.html", + "29: return a;", + "$ backtrace", + "< response:backtrace", + "Frames #0 to #3 of 4:", + "#00 f(x=1, y=undefined) foo.html line 29 column 3 (position 62)", + "#01 g() foo.html line 61 column 3 (position 30)", + "#02 function DebuggerTest()", // prefix + "#03 [anonymous]()", // prefix + "$ source", + "< response:source", + "24: function f(x, y) {", + "25: var a=1;", + "26: if (x == 1) {", + "27: a++;", + "28: }", + ">>>> return a;", + "30: };", + "$ print x", + "< response:evaluate", + "1", + "$ args", + "< response:frame", + "x = 1", + "y = undefined", + "$ locals", + "< response:frame", + "a = 2", + "$ frame 1", + "< response:frame", + "#1 g, foo.html", + "61: f(1);", + "$ stepout", + "< response:continue", + "< event:break", + "g(), foo.html", + "62: };", + "$ continue", + "< response:continue" +]; + + +/** + * Tests the debugger and protocol for a couple of simple scripts. + */ +DebuggerTest.testProtocol = function() { + DebuggerTest.initialize(); + + // Startup the front-end. + debug(new DebuggerTest.TabMock("testing")); + + script1 = + "function f(x, y) {\n" + // line 23 + " var a=1;\n" + // line 24 + " if (x == 1) {\n" + // line 25 + " a++;\n }\n" + // line 26 + " return a;\n" + // line 27 + "};"; // line 28 + script2 = + "function g() {\n" + // line 58 + " debugger;\n" + // line 59 + " f(1);\n" + // line 60 + "};"; // line 61 + %CompileScript(script1, "foo.html", 23, 0)(); + %CompileScript(script2, "foo.html", 58, 0)(); + + try { + g(); + } catch(e) { + print(e); + } + + DebuggerTest.verifyOutput(); +} + +DebuggerTest.testProtocol(); diff --git a/chrome/test/injection_test_dll.h b/chrome/test/injection_test_dll.h new file mode 100644 index 0000000..a3dce18 --- /dev/null +++ b/chrome/test/injection_test_dll.h @@ -0,0 +1,51 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_INJECTION_TEST_DLL_H__ +#define CHROME_TEST_INJECTION_TEST_DLL_H__ + +// This file defines the entry points for any DLL that can be loaded into the +// renderer or plugin process for the purposes of testing. The DLL code must +// define TEST_INJECTION_DLL so the entry point definitions cause the linker +// to generate exported functions. + +const char kRenderTestCall[] = "RunRendererTests"; +const char kPluginTestCall[] = "RunPluginTests"; + +extern "C" { +#ifdef TEST_INJECTION_DLL +BOOL extern __declspec(dllexport) __cdecl RunRendererTests(int* test_count); +BOOL extern __declspec(dllexport) __cdecl RunPluginTests(int* test_count); +#else +typedef BOOL (__cdecl *RunRendererTests)(int* test_count); +typedef BOOL (__cdecl *RunPluginTests)(int* test_count); +#endif +} + +#endif // CHROME_TEST_INJECTION_TEST_DLL_H__ diff --git a/chrome/test/interactive_ui/SConscript b/chrome/test/interactive_ui/SConscript new file mode 100644 index 0000000..db4fddb --- /dev/null +++ b/chrome/test/interactive_ui/SConscript @@ -0,0 +1,132 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'LIBXSLT_STATIC',
+ 'LIBXML_STATIC',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ '$CHROME_DIR/third_party/wtl/include',
+ '$LIBXSLT_DIR',
+ '$LIBXML_DIR/include',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'psapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/browser/browser_focus_uitest.cc',
+ '$CHROME_DIR/browser/views/constrained_window_impl_interactive_uitest.cc',
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BZIP2_DIR/bzip2.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+
+exe = env_test.Program(['interactive_ui_tests',
+ 'interactive_ui_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/interactive_ui/interactive_ui.vcproj b/chrome/test/interactive_ui/interactive_ui.vcproj new file mode 100644 index 0000000..56c649f --- /dev/null +++ b/chrome/test/interactive_ui/interactive_ui.vcproj @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="interactive_ui_tests" + ProjectGUID="{018D4F38-6272-448F-A864-976DA09F05D0}" + RootNamespace="manual_ui" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath="..\ui\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.h" + > + </File> + <File + RelativePath="..\ui\ui_test_suite.cc" + > + </File> + </Filter> + <Filter + Name="TestFocus" + > + <File + RelativePath="..\..\browser\browser_focus_uitest.cc" + > + </File> + <File + RelativePath="..\..\browser\views\constrained_window_impl_interactive_uitest.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/mini_installer_test/SConscript b/chrome/test/mini_installer_test/SConscript new file mode 100644 index 0000000..6a474f0 --- /dev/null +++ b/chrome/test/mini_installer_test/SConscript @@ -0,0 +1,111 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'shlwapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/installer/setup/setup_constants$OBJSUFFIX',
+ '$CHROME_DIR/installer/util/run_all_unittests$OBJSUFFIX',
+ 'chrome_mini_installer.cc',
+ 'mini_installer_test_constants.cc',
+ 'test.cc',
+]
+
+libs = [
+ '$CHROME_DIR/installer/util/util.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$BASE_DIR/base.lib',
+]
+
+exe = env_test.Program(['mini_installer_test',
+ 'mini_installer_test.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/mini_installer_test/chrome_mini_installer.cc b/chrome/test/mini_installer_test/chrome_mini_installer.cc new file mode 100644 index 0000000..c8d67c3 --- /dev/null +++ b/chrome/test/mini_installer_test/chrome_mini_installer.cc @@ -0,0 +1,310 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/mini_installer_test/chrome_mini_installer.h" + +#include "base/path_service.h" +#include "base/process_util.h" +#include "base/registry.h" +#include "base/string_util.h" +#include "chrome/installer/setup/setup_constants.h" +#include "chrome/installer/util/install_util.h" +#include "chrome/installer/util/google_update_constants.h" +#include "chrome/installer/util/util_constants.h" +#include "chrome/test/mini_installer_test/mini_installer_test_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Installs the Chrome mini-installer, checks the registry and shortcuts. +void ChromeMiniInstaller::InstallMiniInstaller(bool over_install) { + // If need to do clean installation, uninstall chrome if exists. + if (!over_install) { + UnInstall(); + } + LaunchExe(mini_installer_constants::kChromeMiniInstallerExecutable, + mini_installer_constants::kChromeMiniInstallerExecutable); + ASSERT_TRUE(CheckRegistryKey(InstallUtil::GetChromeGoogleUpdateKey())); + FindChromeShortcut(); + WaitUntilProcessStartsRunning(installer_util::kChromeExe); + if (!over_install) { + ASSERT_TRUE(CloseWindow( + mini_installer_constants::kFirstChromeUI, WM_CLOSE)); + } else { + ASSERT_TRUE(CloseWindow( + mini_installer_constants::kBrowserTabName, WM_CLOSE)); + } + VerifyChromeLaunch(); +} + +// Installs chromesetupdev.exe, waits for the install to finish and then +// checks the registry and shortcuts. +void ChromeMiniInstaller::InstallChromeSetupDev() { + // Uninstall chrome, if already installed. + UnInstall(); + + // Install older/dev version of chrome. + LaunchExe(mini_installer_constants::kChromeSetupDevExeLocation, + mini_installer_constants::kChromeSetupExecutable); + WaitUntilProcessStopsRunning( + mini_installer_constants::kChromeMiniInstallerExecutable); + std::wstring chrome_google_update_state_key( + google_update::kRegPathClientState); + chrome_google_update_state_key.append(L"\\"); + chrome_google_update_state_key.append(google_update::kChromeGuid); + ASSERT_TRUE(CheckRegistryKey(chrome_google_update_state_key)); + ASSERT_TRUE(CheckRegistryKey(InstallUtil::GetChromeGoogleUpdateKey())); + FindChromeShortcut(); + WaitUntilProcessStartsRunning(installer_util::kChromeExe); + ASSERT_TRUE(CloseWindow(mini_installer_constants::kFirstChromeUI, WM_CLOSE)); +} + +// Accepts mini/dev as parameters. If mini, installs mini_installer first. +// if dev, installs ChromeSetupDev.exe first and +// then over installs with mini_installer. +// Also, verifies if Chrome can be launched sucessfully after overinstall. +void ChromeMiniInstaller::OverInstall() { + InstallChromeSetupDev(); + // gets the registry key value before overinstall. + std::wstring reg_key_value_returned = GetRegistryKey(); + printf("\n\nPreparing to overinstall...\n"); + printf("\nOverinstall path is %ls\n", + mini_installer_constants::kChromeMiniInstallerExecutable); + InstallMiniInstaller(true); + // Get the registry key value after over install + std::wstring reg_key_value_after_overinstall = GetRegistryKey(); + ASSERT_TRUE(VerifyOverInstall( + reg_key_value_returned, reg_key_value_after_overinstall)); +} + +// This method first checks if Chrome is running. +// If yes, will close all the processes. +// Then will find and spawn uninstall path. +// Handles uninstall confirm dialog. +// Waits until setup.exe ends. +// Checks if registry key exist even after uninstall. +// Deletes App dir. +void ChromeMiniInstaller::UnInstall() { + printf("Verifying if Chrome is installed...\n"); + if (!CheckRegistryKey(InstallUtil::GetChromeGoogleUpdateKey())) { + printf("Chrome is not installed.\n"); + return; + } + + printf("\nClosing Chrome processes, if any...\n"); + CloseChromeProcesses(); + + std::wstring uninstall_path = GetUninstallPath(); + ASSERT_TRUE(file_util::PathExists(uninstall_path)); + + printf("\nUninstalling Chrome...\n"); + process_util::LaunchApp(L"\"" + uninstall_path + L"\"" + L" -uninstall", + false, false, NULL); + printf("\nLaunched setup.exe -uninstall....\n"); + ASSERT_TRUE(CloseWindow( + mini_installer_constants::kConfirmDialog, WM_COMMAND)); + WaitUntilProcessStopsRunning( + mini_installer_constants::kChromeSetupExecutable); + ASSERT_FALSE(CheckRegistryKey(InstallUtil::GetChromeGoogleUpdateKey())); + DeleteAppFolder(); + FindChromeShortcut(); + if (false == CloseWindow(mini_installer_constants::kChromeUninstallIETitle, + WM_CLOSE)) { + printf("\nFailed to close window \"%s\".", + mini_installer_constants::kChromeUninstallIETitle); + } +} + +// Takes care of Chrome uninstall dialog. +bool ChromeMiniInstaller::CloseWindow(LPCWSTR window_name, UINT message) { + int timer = 0; + bool return_val = false; + HWND hndl = FindWindow(NULL, window_name); + while (hndl== NULL && (timer < 60000)) { + hndl = FindWindow(NULL, window_name); + Sleep(200); + timer = timer + 200; + } + if (hndl != NULL) { + LRESULT _result = SendMessage(hndl, message, 1, 0); + return_val = true; + } + return return_val; +} + +// Closes Chrome browser. +void ChromeMiniInstaller::CloseChromeBrowser(LPCWSTR window_name) { + WaitUntilProcessStartsRunning(installer_util::kChromeExe); + ASSERT_TRUE(CloseWindow(window_name, WM_CLOSE)); +} + +// Checks for all running Chrome processes and kills them. +void ChromeMiniInstaller::CloseChromeProcesses() { + int timer = 0; + while ((process_util::GetProcessCount(installer_util::kChromeExe, NULL) > 0) && + (timer < 20000)) { + process_util::KillProcesses(installer_util::kChromeExe, 1, NULL); + Sleep(200); + timer = timer + 200; + } + ASSERT_EQ(0, process_util::GetProcessCount(installer_util::kChromeExe, NULL)); +} + +// Checks for Chrome registry keys. +bool ChromeMiniInstaller::CheckRegistryKey(std::wstring key_path) { + RegKey key; + if (!key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_ALL_ACCESS)) { + printf("Cannot open reg key\n"); + return false; + } + std::wstring reg_key_value_returned = GetRegistryKey(); + printf("Reg key value is%ls\n", reg_key_value_returned.c_str()); + return true; +} + +// Deletes App folder after uninstall. +void ChromeMiniInstaller::DeleteAppFolder() { + std::wstring path; + ASSERT_TRUE(PathService::Get(base::DIR_LOCAL_APP_DATA, &path)); + file_util::AppendToPath(&path, mini_installer_constants::kAppDir); + file_util::UpOneDirectory(&path); + printf("Deleting this path after uninstall%ls\n", path.c_str()); + ASSERT_TRUE(file_util::Delete(path.c_str(), true)); +} + +// Verifies if Chrome shortcut exists. +void ChromeMiniInstaller::FindChromeShortcut() { + std::wstring username, path_name, append_path, uninstall_lnk, shortcut_path; + bool return_val = false; + ASSERT_TRUE(PathService::Get(base::DIR_START_MENU, &path_name)); + file_util::AppendToPath(&path_name, L"Google Chrome"); + // Verify if path exists. + if (file_util::PathExists(path_name)) { + return_val = true; + uninstall_lnk = path_name; + file_util::AppendToPath(&path_name, L"Google Chrome.lnk"); + file_util::AppendToPath(&uninstall_lnk, L"Uninstall Google Chrome.lnk"); + ASSERT_TRUE(file_util::PathExists(path_name)); + ASSERT_TRUE(file_util::PathExists(uninstall_lnk)); + } + if (return_val) + printf("Chrome shortcuts found are:\n%ls\n%ls\n", + path_name.c_str(), uninstall_lnk.c_str()); + else + printf("Chrome shortcuts not found\n"); +} + +// Gets the path for uninstall. +std::wstring ChromeMiniInstaller::GetUninstallPath() { + std::wstring username, append_path, path; + std::wstring build_key_value = GetRegistryKey(); + PathService::Get(base::DIR_LOCAL_APP_DATA, &path); + file_util::AppendToPath(&path, mini_installer_constants::kAppDir); + file_util::AppendToPath(&path, build_key_value); + file_util::AppendToPath(&path, installer::kInstallerDir); + file_util::AppendToPath(&path, + mini_installer_constants::kChromeSetupExecutable); + printf("uninstall path is %ls\n", path.c_str()); + return path; +} + +// Reads Chrome registry key. +std::wstring ChromeMiniInstaller::GetRegistryKey() { + std::wstring build_key_value; + RegKey key(HKEY_CURRENT_USER, InstallUtil::GetChromeGoogleUpdateKey().c_str()); + if (!key.ReadValue(L"pv", &build_key_value)) + return false; + return build_key_value; +} + +// Launches a given executable and waits until it is done. +void ChromeMiniInstaller::LaunchExe(std::wstring path, + const wchar_t process_name[]) { + printf("\nBuild to be installed is: %ls\n", path.c_str()); + ASSERT_TRUE(file_util::PathExists(path)); + process_util::LaunchApp(L"\"" + path + L"\"", false, false, NULL); + printf("Waiting while this process is running %ls ....", process_name); + WaitUntilProcessStartsRunning(process_name); + WaitUntilProcessStopsRunning(process_name); +} + +// Launch Chrome to see if it works after overinstall. Then close it. +void ChromeMiniInstaller::VerifyChromeLaunch() { + std::wstring username, path, append_path; + ASSERT_TRUE(PathService::Get(base::DIR_LOCAL_APP_DATA, &path)); + file_util::AppendToPath(&path, + mini_installer_constants::kAppDir); + file_util::AppendToPath(&path, installer_util::kChromeExe); + process_util::LaunchApp(L"\"" + path + L"\"", false, false, NULL); + WaitUntilProcessStartsRunning(installer_util::kChromeExe); + Sleep(1200); +} + +// This method compares the registry keys after overinstall. +bool ChromeMiniInstaller::VerifyOverInstall( + std::wstring value_before_overinstall, + std::wstring value_after_overinstall) { + int64 reg_key_value_before_overinstall = StringToInt64( + value_before_overinstall); + int64 reg_key_value_after_overinstall = StringToInt64( + value_after_overinstall); + // Compare to see if the version is less. + printf("Reg Key value before overinstall is%ls\n", + value_before_overinstall.c_str()); + printf("Reg Key value after overinstall is%ls\n", + value_after_overinstall.c_str()); + if (reg_key_value_before_overinstall > reg_key_value_after_overinstall) { + printf("FAIL: Overinstalled a lower version of Chrome\n"); + return false; + } + return true; +} + +// Waits until the process starts running. +void ChromeMiniInstaller::WaitUntilProcessStartsRunning( + const wchar_t process_name[]) { + int timer = 0; + while ((process_util::GetProcessCount(process_name, NULL) == 0) && + (timer < 60000)) { + Sleep(200); + timer = timer + 200; + } + ASSERT_NE(0, process_util::GetProcessCount(process_name, NULL)); +} + +// Waits until the process stops running. +void ChromeMiniInstaller::WaitUntilProcessStopsRunning( + const wchar_t process_name[]) { + int timer = 0; + printf("\nWaiting for this process to end... %ls\n", process_name); + while ((process_util::GetProcessCount(process_name, NULL) > 0) && + (timer < 60000)) { + Sleep(200); + timer = timer + 200; + } + ASSERT_EQ(0, process_util::GetProcessCount(process_name, NULL)); +} diff --git a/chrome/test/mini_installer_test/chrome_mini_installer.h b/chrome/test/mini_installer_test/chrome_mini_installer.h new file mode 100644 index 0000000..27d5923 --- /dev/null +++ b/chrome/test/mini_installer_test/chrome_mini_installer.h @@ -0,0 +1,105 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_MINI_INSTALLER_TEST_CHROME_MINI_INSTALLER_H__ +#define CHROME_TEST_MINI_INSTALLER_TEST_CHROME_MINI_INSTALLER_H__ + +#include <windows.h> +#include <process.h> +#include <psapi.h> +#include <tlhelp32.h> +#include <tchar.h> +#include <errno.h> +#include <string> + +#include "base/file_util.h" + +// This class has methods to install and uninstall Chrome mini installer. +class ChromeMiniInstaller { + public: + ChromeMiniInstaller() {} + ~ChromeMiniInstaller() {} + + // Installs Chrome Mini Installer. + void InstallMiniInstaller(bool over_install = false); + + // Installs ChromeSetupDev.exe. + void InstallChromeSetupDev(); + + // This method takes care of all overinstall cases. + void OverInstall(); + + // Uninstalls Chrome. + void UnInstall(); + + // Verifies if Chrome launches after overinstall. + void VerifyChromeLaunch(); + + private: + // Closes Chrome uninstall confirm dialog window. + bool CloseWindow(LPCWSTR window_name, UINT message); + + // Closes Chrome browser. + void CloseChromeBrowser(LPCWSTR window_name); + + // Closes all running Chrome processes. + void CloseChromeProcesses(); + + // Checks for registry key. + bool CheckRegistryKey(std::wstring key_path); + + // Deletes App folder after uninstall. + void DeleteAppFolder(); + + // This method verifies Chrome shortcut. + void FindChromeShortcut(); + + // Get path for uninstall. + std::wstring GetUninstallPath(); + + // Reads registry key. + std::wstring GetRegistryKey(); + + // Launches the given EXE and waits for it to end. + void LaunchExe(std::wstring install_path, const wchar_t process_name[]); + + // Compares the registry key values after overinstall. + bool VerifyOverInstall(std::wstring reg_key_value_before_overinstall, + std::wstring reg_key_value_after_overinstall); + + // Waits until the given process starts running + void WaitUntilProcessStartsRunning(const wchar_t process_name[]); + + // Waits until the given process stops running + void WaitUntilProcessStopsRunning(const wchar_t process_name[]); + + DISALLOW_EVIL_CONSTRUCTORS(ChromeMiniInstaller); +}; + +#endif // CHROME_TEST_MINI_INSTALLER_TEST_CHROME_MINI_INSTALLER_H__ diff --git a/chrome/test/mini_installer_test/mini_installer_test.vcproj b/chrome/test/mini_installer_test/mini_installer_test.vcproj new file mode 100644 index 0000000..2a20087 --- /dev/null +++ b/chrome/test/mini_installer_test/mini_installer_test.vcproj @@ -0,0 +1,176 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="mini_installer_test" + ProjectGUID="{4B6E199A-034A-49BD-AB93-458DD37E45B1}" + RootNamespace="mini_installer_test" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)\tools\build\win\unit_test.vsprops;$(SolutionDir)\installer\util\using_util.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + IgnoreDefaultLibraryNames="" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + AdditionalManifestFiles="$(SolutionDir)installer\mini_installer\mini_installer.exe.manifest" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)\tools\build\win\unit_test.vsprops;$(SolutionDir)\installer\util\using_util.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + AdditionalManifestFiles="$(SolutionDir)installer\mini_installer\mini_installer.exe.manifest" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath=".\chrome_mini_installer.cc" + > + </File> + <File + RelativePath=".\chrome_mini_installer.h" + > + </File> + <File + RelativePath=".\mini_installer_test_constants.cc" + > + </File> + <File + RelativePath=".\mini_installer_test_constants.h" + > + </File> + <File + RelativePath="..\..\installer\util\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\..\installer\setup\setup_constants.cc" + > + </File> + <File + RelativePath=".\test.cc" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/mini_installer_test/mini_installer_test_constants.cc b/chrome/test/mini_installer_test/mini_installer_test_constants.cc new file mode 100644 index 0000000..d3f91be --- /dev/null +++ b/chrome/test/mini_installer_test/mini_installer_test_constants.cc @@ -0,0 +1,51 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/mini_installer_test/mini_installer_test_constants.h" + +namespace mini_installer_constants { + +const wchar_t kAppDir[] = L"Google\\Chrome\\Application\\"; +const wchar_t kChromeSetupExecutable[] = L"setup.exe"; +const wchar_t kChromeMiniInstallerExecutable[] = L"mini_installer.exe"; +const wchar_t kChromeInstallerType[] = L"dev"; + +const wchar_t kBrowserAppName[] = L"Google - Google Chrome"; +const wchar_t kBrowserTabName[] = L"New Tab - Google Chrome"; +const wchar_t kConfirmDialog[] = L"Google Chrome"; +const wchar_t kInstallerWindow[] = L"Google App Installer"; +const wchar_t kFirstChromeUI[] = L"Welcome to Chrome"; + +const wchar_t kChromeUninstallIETitle[] = + L"Google Chrome - Windows Internet Explorer"; + +// Chrome meta installer location. +const wchar_t kChromeSetupDevExeLocation[] = + L"\\\\172.23.44.61\\shared\\chrome_autotest\\DevTest\\ChromeSetup_en.exe"; +} diff --git a/chrome/test/mini_installer_test/mini_installer_test_constants.h b/chrome/test/mini_installer_test/mini_installer_test_constants.h new file mode 100644 index 0000000..d35c733 --- /dev/null +++ b/chrome/test/mini_installer_test/mini_installer_test_constants.h @@ -0,0 +1,54 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Constants related to the Chrome mini installer testing. + +#ifndef CHROME_TEST_MINI_INSTALLER_TEST_MINI_INSTALLER_TEST_CONSTANTS_H__ +#define CHROME_TEST_MINI_INSTALLER_TEST_MINI_INSTALLER_TEST_CONSTANTS_H__ + +namespace mini_installer_constants { + +extern const wchar_t kAppDir[]; +extern const wchar_t kChromeSetupExecutable[]; +extern const wchar_t kChromeMiniInstallerExecutable[]; +extern const wchar_t kChromeInstallerType[]; + +// Window names. +extern const wchar_t kBrowserAppName[]; +extern const wchar_t kBrowserTabName[]; +extern const wchar_t kConfirmDialog[]; +extern const wchar_t kInstallerWindow[]; +extern const wchar_t kFirstChromeUI[]; +extern const wchar_t kChromeUninstallIETitle[]; + +// Chrome meta installer location. +extern const wchar_t kChromeSetupDevExeLocation[]; +} + +#endif // CHROME_TEST_MINI_INSTALLER_TEST_MINI_INSTALLER_TEST_CONSTANTS_H__ diff --git a/chrome/test/mini_installer_test/test.cc b/chrome/test/mini_installer_test/test.cc new file mode 100644 index 0000000..cc61c86 --- /dev/null +++ b/chrome/test/mini_installer_test/test.cc @@ -0,0 +1,58 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome_mini_installer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +class MiniInstallTest : public testing::Test { + protected: + virtual void SetUp() { + // Currently no setup required + } + + virtual void TearDown() { + // Currently no tear down required + } + }; +}; + +// This test is disabled. See bug 1199175. +TEST_F(MiniInstallTest, DISABLED_MiniInstallerCleanInstallTest) { + ChromeMiniInstaller installer; + installer.InstallMiniInstaller(); + installer.UnInstall(); +} + +// This test is disabled. See bug 1199175. +TEST_F(MiniInstallTest, DISABLED_MiniInstallerOverChromeSetupDevTest) { + ChromeMiniInstaller installer; + installer.OverInstall(); + installer.UnInstall(); +} diff --git a/chrome/test/page_cycler/SConscript b/chrome/test/page_cycler/SConscript new file mode 100644 index 0000000..eb24fd4 --- /dev/null +++ b/chrome/test/page_cycler/SConscript @@ -0,0 +1,127 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'psapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+
+input_files = [
+ '$CHROME_DIR/test/perf/mem_usage$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'page_cycler_test.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+
+exe = env_test.Program(['page_cycler_tests',
+ 'page_cycler_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/page_cycler/page_cycler_test.cc b/chrome/test/page_cycler/page_cycler_test.cc new file mode 100644 index 0000000..421c665 --- /dev/null +++ b/chrome/test/page_cycler/page_cycler_test.cc @@ -0,0 +1,328 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/process_util.h" +#include "base/string_util.h" +#include "chrome/browser/url_fixer_upper.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_process_filter.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "chrome/test/perf/mem_usage.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_util.h" + +#ifndef NDEBUG +#define TEST_ITERATIONS "2" +#else +#define TEST_ITERATIONS "10" +#endif + +// URL at which data files may be found for HTTP tests. The document root of +// this URL's server should point to data/page_cycler/. +#define BASE_URL L"http://localhost:8000" + +namespace { + +class PageCyclerTest : public UITest { + public: + PageCyclerTest() { + show_window_ = true; + + // Expose garbage collection for the page cycler tests. + CommandLine::AppendSwitchWithValue(&launch_arguments_, + switches::kJavaScriptFlags, + L"--expose_gc"); + } + + // For HTTP tests, the name must be safe for use in a URL without escaping. + void RunPageCycler(const wchar_t* name, std::wstring* pages, + std::wstring* timings, bool use_http) { + GURL test_url; + if (use_http) { + std::wstring test_path(BASE_URL); + file_util::AppendToPath(&test_path, name); + file_util::AppendToPath(&test_path, L"start.html"); + test_url = GURL(test_path); + } else { + std::wstring test_path; + PathService::Get(base::DIR_EXE, &test_path); + file_util::UpOneDirectory(&test_path); + file_util::UpOneDirectory(&test_path); + file_util::AppendToPath(&test_path, L"data"); + file_util::AppendToPath(&test_path, L"page_cycler"); + file_util::AppendToPath(&test_path, name); + file_util::AppendToPath(&test_path, L"start.html"); + test_url = net_util::FilePathToFileURL(test_path); + } + + // run N iterations + GURL::Replacements replacements; + const char query_string[] = "iterations=" TEST_ITERATIONS "&auto=1"; + replacements.SetQuery( + query_string, + url_parse::Component(0, arraysize(query_string) - 1)); + test_url = test_url.ReplaceComponents(replacements); + + scoped_ptr<TabProxy> tab(GetActiveTab()); + tab->NavigateToURL(test_url); + + // Wait for the test to finish. + ASSERT_TRUE(WaitUntilCookieValue(tab.get(), test_url, "__pc_done", + 3000, UITest::test_timeout_ms(), "1")); + + std::string cookie; + ASSERT_TRUE(tab->GetCookieByName(test_url, "__pc_pages", &cookie)); + pages->swap(UTF8ToWide(cookie)); + ASSERT_FALSE(pages->empty()); + ASSERT_TRUE(tab->GetCookieByName(test_url, "__pc_timings", &cookie)); + timings->swap(UTF8ToWide(cookie)); + ASSERT_FALSE(timings->empty()); + } + + void PrintIOPerfInfo(const wchar_t* test_name) { + printf("\n"); + BrowserProcessFilter chrome_filter; + process_util::NamedProcessIterator + chrome_process_itr(chrome::kBrowserProcessExecutableName, + &chrome_filter); + + const PROCESSENTRY32* chrome_entry; + while(chrome_entry = chrome_process_itr.NextProcessEntry()) { + uint32 pid = chrome_entry->th32ProcessID; + HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, + false, + pid); + + scoped_ptr<process_util::ProcessMetrics> process_metrics; + IO_COUNTERS io_counters; + process_metrics.reset( + process_util::ProcessMetrics::CreateProcessMetrics(process_handle)); + ZeroMemory(&io_counters, sizeof(io_counters)); + + if (process_metrics.get()->GetIOCounters(&io_counters)) { + wchar_t* browser_name = L"browser"; + wchar_t* render_name = L"render"; + wchar_t* chrome_name; + if (pid == chrome_filter.browser_process_id()) { + chrome_name = browser_name; + } else { + chrome_name = render_name; + } + + // print out IO performance + wprintf(L"%s_%s_read_op = %d\n", + test_name, chrome_name, io_counters.ReadOperationCount); + wprintf(L"%s_%s_write_op = %d\n", + test_name, chrome_name, io_counters.WriteOperationCount); + wprintf(L"%s_%s_other_op = %d\n", + test_name, chrome_name, io_counters.OtherOperationCount); + wprintf(L"%s_%s_read_byte = %d K\n", + test_name, chrome_name, io_counters.ReadTransferCount / 1024); + wprintf(L"%s_%s_write_byte = %d K\n", + test_name, chrome_name, io_counters.WriteTransferCount / 1024); + wprintf(L"%s_%s_other_byte = %d K\n", + test_name, chrome_name, io_counters.OtherTransferCount / 1024); + } + } + } + + void PrintMemoryUsageInfo(const wchar_t* test_name) { + printf("\n"); + BrowserProcessFilter chrome_filter; + process_util::NamedProcessIterator + chrome_process_itr(chrome::kBrowserProcessExecutableName, + &chrome_filter); + + const PROCESSENTRY32* chrome_entry; + while(chrome_entry = chrome_process_itr.NextProcessEntry()) { + uint32 pid = chrome_entry->th32ProcessID; + size_t peak_virtual_size; + size_t current_virtual_size; + size_t peak_working_set_size; + size_t current_working_set_size; + if (GetMemoryInfo(pid, &peak_virtual_size, ¤t_virtual_size, + &peak_working_set_size, ¤t_working_set_size)) { + if (pid == chrome_filter.browser_process_id()) { + wprintf(L"%s_browser_vm_peak = %d\n", test_name, peak_virtual_size); + wprintf(L"%s_browser_vm_final = %d\n", test_name, + current_virtual_size); + wprintf(L"%s_browser_ws_peak = %d\n", test_name, + peak_working_set_size); + wprintf(L"%s_browser_ws_final = %d\n", test_name, + current_working_set_size); + } else { + wprintf(L"%s_render_vm_peak = %d\n", test_name, peak_virtual_size); + wprintf(L"%s_render_vm_final = %d\n", test_name, + current_virtual_size); + wprintf(L"%s_render_ws_peak = %d\n", test_name, + peak_working_set_size); + wprintf(L"%s_render_ws_final = %d\n", test_name, + current_working_set_size); + } + } + }; + } + + // When use_http is true, the test name passed here will be used directly in + // the path to the test data, so it must be safe for use in a URL without + // escaping. (No pound (#), question mark (?), semicolon (;), non-ASCII, or + // other funny stuff.) + void RunTest(const wchar_t* name, bool use_http) { + std::wstring pages, timings; + RunPageCycler(name, &pages, &timings, use_http); + if (timings.empty()) + return; + + PrintMemoryUsageInfo(L"__pc"); + PrintIOPerfInfo(L"__pc"); + + printf("\n"); + wprintf(L"__pc_pages = [%s]\n", pages.c_str()); + wprintf(L"__pc_timings = [%s]\n", timings.c_str()); + } +}; + +class PageCyclerReferenceTest : public PageCyclerTest { + public: + // override the browser directory that is used by UITest::SetUp to cause it + // to use the reference build instead. + void SetUp() { + std::wstring dir; + PathService::Get(chrome::DIR_TEST_TOOLS, &dir); + file_util::AppendToPath(&dir, L"reference_build"); + file_util::AppendToPath(&dir, L"chrome"); + browser_directory_ = dir; + UITest::SetUp(); + } + + void RunTest(const wchar_t* name, bool use_http) { + std::wstring pages, timings; + RunPageCycler(name, &pages, &timings, use_http); + if (timings.empty()) + return; + + PrintMemoryUsageInfo(L"__pc_reference"); + PrintIOPerfInfo(L"__pc_reference"); + + printf("\n"); + wprintf(L"__pc_reference_timings = [%s]\n", timings.c_str()); + } +}; + +} // namespace + +// file-URL tests +TEST_F(PageCyclerTest, MozFile) { + RunTest(L"moz", false); +} + +TEST_F(PageCyclerReferenceTest, MozFile) { + RunTest(L"moz", false); +} + +TEST_F(PageCyclerTest, Intl1File) { + RunTest(L"intl1", false); +} + +TEST_F(PageCyclerReferenceTest, Intl1File) { + RunTest(L"intl1", false); +} + +TEST_F(PageCyclerTest, Intl2File) { + RunTest(L"intl2", false); +} + +TEST_F(PageCyclerReferenceTest, Intl2File) { + RunTest(L"intl2", false); +} + +TEST_F(PageCyclerTest, DomFile) { + RunTest(L"dom", false); +} + +TEST_F(PageCyclerReferenceTest, DomFile) { + RunTest(L"dom", false); +} + +TEST_F(PageCyclerTest, DhtmlFile) { + RunTest(L"dhtml", false); +} + +TEST_F(PageCyclerReferenceTest, DhtmlFile) { + RunTest(L"dhtml", false); +} + +// http (localhost) tests +TEST_F(PageCyclerTest, MozHttp) { + RunTest(L"moz", true); +} + +TEST_F(PageCyclerReferenceTest, MozHttp) { + RunTest(L"moz", true); +} + +TEST_F(PageCyclerTest, Intl1Http) { + RunTest(L"intl1", true); +} + +TEST_F(PageCyclerReferenceTest, Intl1Http) { + RunTest(L"intl1", true); +} + +TEST_F(PageCyclerTest, Intl2Http) { + RunTest(L"intl2", true); +} + +TEST_F(PageCyclerReferenceTest, Intl2Http) { + RunTest(L"intl2", true); +} + +TEST_F(PageCyclerTest, DomHttp) { + RunTest(L"dom", true); +} + +TEST_F(PageCyclerReferenceTest, DomHttp) { + RunTest(L"dom", true); +} + +TEST_F(PageCyclerTest, BloatHttp) { + RunTest(L"bloat", true); +} + +TEST_F(PageCyclerReferenceTest, BloatHttp) { + RunTest(L"bloat", true); +} diff --git a/chrome/test/page_cycler/page_cycler_tests.vcproj b/chrome/test/page_cycler/page_cycler_tests.vcproj new file mode 100644 index 0000000..a3a7025 --- /dev/null +++ b/chrome/test/page_cycler/page_cycler_tests.vcproj @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="page_cycler_tests" + ProjectGUID="{C9E0BD1D-B175-4A91-8380-3FDC81FAB9D7}" + RootNamespace="page_cycler_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath="..\ui\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath="..\ui\ui_test.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.h" + > + </File> + <File + RelativePath="..\ui\ui_test_suite.cc" + > + </File> + </Filter> + <Filter + Name="MemoryUsage" + > + <File + RelativePath="..\perf\mem_usage.cc" + > + </File> + <File + RelativePath="..\perf\mem_usage.h" + > + </File> + </Filter> + <Filter + Name="TestPageCycler" + > + <File + RelativePath=".\page_cycler_test.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/perf/mem_usage.cc b/chrome/test/perf/mem_usage.cc new file mode 100644 index 0000000..c8ec78c --- /dev/null +++ b/chrome/test/perf/mem_usage.cc @@ -0,0 +1,98 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <windows.h> +#include <psapi.h> + +#include "base/basictypes.h" +#include "base/process_util.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_process_filter.h" +#include "chrome/test/perf/mem_usage.h" + +bool GetMemoryInfo(uint32 process_id, + size_t *peak_virtual_size, + size_t *current_virtual_size, + size_t *peak_working_set_size, + size_t *current_working_set_size) { + + if (!peak_virtual_size || !current_virtual_size) + return false; + + HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | + PROCESS_VM_READ, + FALSE, process_id); + if (!process_handle) + return false; + + PROCESS_MEMORY_COUNTERS_EX pmc; + bool result = false; + if (GetProcessMemoryInfo(process_handle, + reinterpret_cast<PPROCESS_MEMORY_COUNTERS>(&pmc), + sizeof(pmc))) { + *peak_virtual_size = pmc.PeakPagefileUsage; + *current_virtual_size = pmc.PagefileUsage; + *peak_working_set_size = pmc.PeakWorkingSetSize; + *current_working_set_size = pmc.WorkingSetSize; + result = true; + } + + CloseHandle(process_handle); + return result; +} + +void PrintChromeMemoryUsageInfo() { + printf("\n"); + BrowserProcessFilter chrome_filter; + process_util::NamedProcessIterator + chrome_process_itr(chrome::kBrowserProcessExecutableName, &chrome_filter); + + const PROCESSENTRY32* chrome_entry; + while(chrome_entry = chrome_process_itr.NextProcessEntry()) { + uint32 pid = chrome_entry->th32ProcessID; + size_t peak_virtual_size; + size_t current_virtual_size; + size_t peak_working_set_size; + size_t current_working_set_size; + if (GetMemoryInfo(pid, &peak_virtual_size, ¤t_virtual_size, + &peak_working_set_size, ¤t_working_set_size)) { + if (pid == chrome_filter.browser_process_id()) { + wprintf(L"browser_vm_peak = %d\n", peak_virtual_size); + wprintf(L"browser_vm_current = %d\n", current_virtual_size); + wprintf(L"browser_ws_peak = %d\n", peak_working_set_size); + wprintf(L"browser_ws_final = %d\n", current_working_set_size); + } else { + wprintf(L"render_vm_peak = %d\n", peak_virtual_size); + wprintf(L"render_vm_current = %d\n", current_virtual_size); + wprintf(L"render_ws_peak = %d\n", peak_working_set_size); + wprintf(L"render_ws_final = %d\n", current_working_set_size); + } + } + }; +} diff --git a/chrome/test/perf/mem_usage.h b/chrome/test/perf/mem_usage.h new file mode 100644 index 0000000..940a0d1 --- /dev/null +++ b/chrome/test/perf/mem_usage.h @@ -0,0 +1,64 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_PERF_MEM_USAGE_H__ +#define CHROME_TEST_PERF_MEM_USAGE_H__ + +// Get memory information for the process with given process ID. +// +// The Windows psapi provides memory information of a process through structure +// RPROCESS_MEMORY_COUNTERS_EX. Relevant fields are: +// PagefileUsage: private (not shared) committed virtual space in process. +// This is "VM Size" in task manager processes tab. +// PeakPagefileUsage: peak value of PagefileUsage. +// WorkingSetSize: physical memory allocated to process including shared pages. +// This is "Memory Usage" in task manager processes tab. +// Contrary to its name, this value is not much useful for +// tracking the memory demand of an application. +// PeakWorkingSetSize: peak value of WorkingSetSize. +// This is "Peak Memory Usage" in task manager processes +// tab. +// PrivateUsage: The current amount of memory that cannot be shared with other +// processes. Private bytes include memory that is committed and +// marked MEM_PRIVATE, data that is not mapped, and executable +// pages that have been written to. It usually gives the same +// value as PagefileUsage. No equivalent part in task manager. +// +// The measurements we use are PagefileUsage (returned by current_virtual_size) +// and PeakPagefileUsage (returned by peak_virtual_size), Working Set and +// Peak working Set. +bool GetMemoryInfo(uint32 process_id, + size_t *peak_virtual_size, + size_t *current_virtual_size, + size_t *peak_working_set_size, + size_t *current_working_set_size); + +// Get and print memory usage information for running chrome processes. +void PrintChromeMemoryUsageInfo(); +#endif // CHROME_TEST_PERF_MEM_USAGE_H__ diff --git a/chrome/test/perf/perftests.cc b/chrome/test/perf/perftests.cc new file mode 100644 index 0000000..c76bc69 --- /dev/null +++ b/chrome/test/perf/perftests.cc @@ -0,0 +1,77 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/message_loop.h" +#include "base/perftimer.h" +#include "chrome/common/chrome_paths.cc" +#include "testing/gtest/include/gtest/gtest.h" + +// TODO(darin): share code with base/run_all_perftests.cc + +int main(int argc, char **argv) { + chrome::RegisterPathProvider(); + MessageLoop main_message_loop; + + testing::InitGoogleTest(&argc, argv); + + const char log_file_switch[] = "-o"; + const char* log_filename = NULL; + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], log_file_switch) == 0) { + // found the switch for the log file, use the next arg + if (i >= argc - 1) { + fprintf(stderr, "Log file not specified"); + return 1; + } + log_filename = argv[i + 1]; + } + } + if (!log_filename) { + // use the default filename + log_filename = "perf_test.log"; + } + printf("Using output file \"%s\" (change with %s <filename>)\n", + log_filename, log_file_switch); + + if (!InitPerfLog(log_filename)) { + fprintf(stderr, "Unable to open log file\n"); + return 1; + } + + // Raise to high priority to have more precise measurements. Since we don't + // aim at 1% precision, it is not necessary to run at realtime level. + if (!IsDebuggerPresent()) { + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); + } + + int result = RUN_ALL_TESTS(); + + FinalizePerfLog(); + return result; +} diff --git a/chrome/test/perf/perftests.vcproj b/chrome/test/perf/perftests.vcproj new file mode 100644 index 0000000..44435d5 --- /dev/null +++ b/chrome/test/perf/perftests.vcproj @@ -0,0 +1,207 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="perf_tests" + ProjectGUID="{9055E088-25C6-47FD-87D5-D9DD9FD75C9F}" + RootNamespace="perf_tests" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + PreprocessorDefinitions="PERF_TEST;_CRT_RAND_S" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="shlwapi.lib rpcrt4.lib winmm.lib" + SubSystem="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + PreprocessorDefinitions="PERF_TEST;_CRT_RAND_S" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="shlwapi.lib rpcrt4.lib winmm.lib" + SubSystem="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="TestVisitedLink" + > + <File + RelativePath="..\..\browser\visitedlink_master.cc" + > + </File> + <File + RelativePath="..\..\browser\visitedlink_perftest.cc" + > + </File> + </Filter> + <Filter + Name="Common" + > + <File + RelativePath=".\perftests.cc" + > + </File> + <File + RelativePath="..\..\..\base\perftimer.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\test_file_util.h" + > + </File> + </Filter> + <Filter + Name="TestURLParser" + > + <File + RelativePath=".\url_parse_perftest.cc" + > + </File> + </Filter> + <Filter + Name="TestJSONSerializer" + > + <File + RelativePath="..\..\common\json_value_serializer_perftest.cc" + > + </File> + </Filter> + <Filter + Name="TestSafeBrowsing" + > + <File + RelativePath="..\..\browser\safe_browsing\database_perftest.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/perf/url_parse_perftest.cc b/chrome/test/perf/url_parse_perftest.cc new file mode 100644 index 0000000..2dc6153 --- /dev/null +++ b/chrome/test/perf/url_parse_perftest.cc @@ -0,0 +1,175 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/perftimer.h" +#include "googleurl/src/gurl.h" +#include "googleurl/src/url_canon.h" +#include "googleurl/src/url_canon_stdstring.h" +#include "googleurl/src/url_parse.h" +#include "testing/gtest/include/gtest/gtest.h" + +// TODO(darin): chrome code should not depend on WebCore innards +#if 0 +#pragma warning(push, 0) + +// This is because we have multiple headers called "CString.h" and KURL.cpp +// can grab the wrong one. +#include "webkit/third_party/WebCore/platform/CString.h" + +#undef USE_GOOGLE_URL_LIBRARY +#define KURL WebKitKURL +#include "KURL.h" +#include "KURL.cpp" +#pragma warning(pop) + +TEST(URLParse, FullURL) { + const char url[] = "http://me:pass@host/foo/bar.html;param?query=yes#ref"; + int url_len = static_cast<int>(strlen(url)); + + url_parse::Parsed parsed; + PerfTimeLogger timer("Full_URL_Parse_AMillion"); + + for (int i = 0; i < 1000000; i++) + url_parse::ParseStandardURL(url, url_len, &parsed); + timer.Done(); +} + +namespace { + +const char typical_url1[] = "http://www.google.com/search?q=url+parsing&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a"; +int typical_url1_len = static_cast<int>(strlen(typical_url1)); + +const char typical_url2[] = "http://www.amazon.com/Stephen-King-Thrillers-Horror-People/dp/0766012336/ref=sr_1_2/133-4144931-4505264?ie=UTF8&s=books&qid=2144880915&sr=8-2"; +int typical_url2_len = static_cast<int>(strlen(typical_url2)); + +const char typical_url3[] = "http://store.apple.com/1-800-MY-APPLE/WebObjects/AppleStore.woa/wa/RSLID?nnmm=browse&mco=578E9744&node=home/desktop/mac_pro"; +int typical_url3_len = static_cast<int>(strlen(typical_url3)); + +} + +TEST(URLParse, TypicalURLParse) { + url_parse::Parsed parsed1; + url_parse::Parsed parsed2; + url_parse::Parsed parsed3; + + // Do this 1/3 of a million times since we do 3 different URLs. + PerfTimeLogger parse_timer("Typical_URL_Parse_AMillion"); + for (int i = 0; i < 333333; i++) { + url_parse::ParseStandardURL(typical_url1, typical_url1_len, &parsed1); + url_parse::ParseStandardURL(typical_url2, typical_url2_len, &parsed2); + url_parse::ParseStandardURL(typical_url3, typical_url3_len, &parsed3); + } + parse_timer.Done(); +} + +// Includes both parsing and canonicalization with no mallocs. +TEST(URLParse, TypicalURLParseCanon) { + url_parse::Parsed parsed1; + url_parse::Parsed parsed2; + url_parse::Parsed parsed3; + + PerfTimeLogger canon_timer("Typical_Parse_Canon_AMillion"); + url_parse::Parsed out_parsed; + url_canon::RawCanonOutput<1024> output; + for (int i = 0; i < 333333; i++) { // divide by 3 so we get 1M + url_parse::ParseStandardURL(typical_url1, typical_url1_len, &parsed1); + output.set_length(0); + url_canon::CanonicalizeStandardURL(typical_url1, typical_url1_len, parsed1, + NULL, &output, &out_parsed); + + url_parse::ParseStandardURL(typical_url2, typical_url2_len, &parsed2); + output.set_length(0); + url_canon::CanonicalizeStandardURL(typical_url2, typical_url2_len, parsed2, + NULL, &output, &out_parsed); + + url_parse::ParseStandardURL(typical_url3, typical_url3_len, &parsed3); + output.set_length(0); + url_canon::CanonicalizeStandardURL(typical_url3, typical_url3_len, parsed3, + NULL, &output, &out_parsed); + } + canon_timer.Done(); +} + +// Includes both parsing and canonicalization, and mallocs for the output. +TEST(URLParse, TypicalURLParseCanonStdString) { + url_parse::Parsed parsed1; + url_parse::Parsed parsed2; + url_parse::Parsed parsed3; + + PerfTimeLogger canon_timer("Typical_Parse_Canon_AMillion"); + url_parse::Parsed out_parsed; + for (int i = 0; i < 333333; i++) { // divide by 3 so we get 1M + url_parse::ParseStandardURL(typical_url1, typical_url1_len, &parsed1); + std::string out1; + url_canon::StdStringCanonOutput output1(&out1); + url_canon::CanonicalizeStandardURL(typical_url1, typical_url1_len, parsed1, + NULL, &output1, &out_parsed); + + url_parse::ParseStandardURL(typical_url2, typical_url2_len, &parsed2); + std::string out2; + url_canon::StdStringCanonOutput output2(&out2); + url_canon::CanonicalizeStandardURL(typical_url2, typical_url2_len, parsed2, + NULL, &output2, &out_parsed); + + url_parse::ParseStandardURL(typical_url3, typical_url3_len, &parsed3); + std::string out3; + url_canon::StdStringCanonOutput output3(&out3); + url_canon::CanonicalizeStandardURL(typical_url3, typical_url3_len, parsed3, + NULL, &output3, &out_parsed); + } + canon_timer.Done(); +} + +TEST(URLParse, GURL) { + // Don't want to time creating the input strings. + std::string stdurl1(typical_url1); + std::string stdurl2(typical_url2); + std::string stdurl3(typical_url3); + + PerfTimeLogger gurl_timer("Typical_GURL_AMillion"); + for (int i = 0; i < 333333; i++) { // divide by 3 so we get 1M + GURL gurl1(stdurl1); + GURL gurl2(stdurl2); + GURL gurl3(stdurl3); + } + gurl_timer.Done(); +} + +// TODO(darin): chrome code should not depend on WebCore innards +TEST(URLParse, KURL) { + PerfTimeLogger timer_kurl("Typical_KURL_AMillion"); + for (int i = 0; i < 333333; i++) { // divide by 3 so we get 1M + WebCore::WebKitKURL kurl1(typical_url1); + WebCore::WebKitKURL kurl2(typical_url2); + WebCore::WebKitKURL kurl3(typical_url3); + } + timer_kurl.Done(); +} + +#endif
\ No newline at end of file diff --git a/chrome/test/plugin/SConscript b/chrome/test/plugin/SConscript new file mode 100644 index 0000000..6ad1cdc --- /dev/null +++ b/chrome/test/plugin/SConscript @@ -0,0 +1,130 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'LIBXSLT_STATIC',
+ 'LIBXML_STATIC',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ '$LIBXSLT_DIR',
+ '$LIBXML_DIR/includ',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"ws2_32.dll"',
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'plugin_test.cpp',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$CHROME_DIR/test/security_tests/security_tests.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+
+exe = env_test.Program(['plugin_tests',
+ 'plugin_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/plugin/plugin_test.cpp b/chrome/test/plugin/plugin_test.cpp new file mode 100644 index 0000000..c9f16c1 --- /dev/null +++ b/chrome/test/plugin/plugin_test.cpp @@ -0,0 +1,232 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Tests for the top plugins to catch regressions in our plugin host code, as +// well as in the out of process code. Currently this tests: +// Flash +// Real +// QuickTime +// Windows Media Player +// -this includes both WMP plugins. npdsplay.dll is the older one that +// comes with XP. np-mswmp.dll can be downloaded from Microsoft and +// needs SP2 or Vista. + +#include <windows.h> +#include <shellapi.h> +#include <shlobj.h> +#include <atlbase.h> +#include <comutil.h> + +#include <stdlib.h> +#include <string.h> +#include <memory.h> + +#include "base/file_util.h" +#include "base/registry.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "net/base/net_util.h" +#include "webkit/glue/plugins/plugin_list.h" + +const char kTestCompleteCookie[] = "status"; +const char kTestCompleteSuccess[] = "OK"; +const int kShortWaitTimeout = 10 * 1000; +const int kLongWaitTimeout = 30 * 1000; + +class PluginTest : public UITest { + protected: + virtual void SetUp() { + const testing::TestInfo* const test_info = + testing::UnitTest::GetInstance()->current_test_info(); + if (strcmp(test_info->name(), "MediaPlayerNew") == 0) { + // The installer adds our process names to the registry key below. Since + // the installer might not have run on this machine, add it manually. + RegKey regkey; + if (regkey.Open(HKEY_LOCAL_MACHINE, + L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList", + KEY_WRITE)) { + regkey.CreateKey(L"CHROME.EXE", KEY_READ); + } + if (!launch_arguments_.empty()) + launch_arguments_.append(L" "); + launch_arguments_.append(L"--" kNoNativeActiveXShimSwitch); + + } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) { + // When testing the old WMP plugin, we need to force Chrome to not load + // the new plugin. + if (!launch_arguments_.empty()) + launch_arguments_.append(L" "); + + launch_arguments_.append(L"--" kUseOldWMPPluginSwitch); + launch_arguments_.append(L" "); + launch_arguments_.append(L"--" kNoNativeActiveXShimSwitch); + } else if (strcmp(test_info->name(), "FlashSecurity") == 0) { + if (!launch_arguments_.empty()) + launch_arguments_.append(L" "); + + launch_arguments_.append(L"--"); + launch_arguments_.append(switches::kTestSandbox); + launch_arguments_.append(L"="); + launch_arguments_.append(L"security_tests.dll"); + } + + UITest::SetUp(); + } + + void TestPlugin(const std::wstring& test_case, int timeout) { + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish(timeout); + } + + // Generate the URL for testing a particular test. + // HTML for the tests is all located in test_directory\plugin\<testcase> + GURL GetTestUrl(const std::wstring &test_case) { + std::wstring path; + PathService::Get(chrome::DIR_TEST_DATA, &path); + file_util::AppendToPath(&path, L"plugin"); + file_util::AppendToPath(&path, test_case); + return net_util::FilePathToFileURL(path); + } + + // Waits for the test case to finish. + void WaitForFinish(const int wait_time) { + const int kSleepTime = 500; // 2 times per second + const int kMaxIntervals = wait_time / kSleepTime; + + GURL url = GetTestUrl(L"done"); + scoped_ptr<TabProxy> tab(GetActiveTab()); + + std::string done_str; + for (int i = 0; i < kMaxIntervals; ++i) { + Sleep(kSleepTime); + + // The webpage being tested has javascript which sets a cookie + // which signals completion of the test. + std::string cookieName = kTestCompleteCookie; + tab->GetCookieByName(url, cookieName, &done_str); + if (!done_str.empty()) + break; + } + + EXPECT_EQ(kTestCompleteSuccess, done_str); + } +}; + +TEST_F(PluginTest, Quicktime) { + TestPlugin(L"quicktime.html", kShortWaitTimeout); +} + +TEST_F(PluginTest, MediaPlayerNew) { + TestPlugin(L"wmp_new.html", kShortWaitTimeout); +} + +TEST_F(PluginTest, MediaPlayerOld) { + TestPlugin(L"wmp_old.html", kLongWaitTimeout); +} + +TEST_F(PluginTest, Real) { + TestPlugin(L"real.html", kShortWaitTimeout); +} + +TEST_F(PluginTest, Flash) { + TestPlugin(L"flash.html", kShortWaitTimeout); +} + +TEST_F(PluginTest, FlashOctetStream) { + TestPlugin(L"flash-octet-stream.html", kShortWaitTimeout); +} + +TEST_F(PluginTest, FlashSecurity) { + TestPlugin(L"flash.html", kShortWaitTimeout); +} + +TEST_F(PluginTest, Java) { + TestPlugin(L"Java.html", kShortWaitTimeout); +} + +TEST_F(PluginTest, Silverlight) { + TestPlugin(L"silverlight.html", kShortWaitTimeout); +} + +typedef HRESULT (__stdcall* DllRegUnregServerFunc)(); + +class ActiveXTest : public PluginTest { + public: + ActiveXTest() { + dll_registered = false; + } + protected: + void TestActiveX(const std::wstring& test_case, int timeout, bool reg_dll) { + if (reg_dll) { + RegisterTestControl(true); + dll_registered = true; + } + TestPlugin(test_case, timeout); + } + virtual void TearDown() { + PluginTest::TearDown(); + if (dll_registered) + RegisterTestControl(false); + } + void RegisterTestControl(bool register_server) { + std::wstring test_control_path = browser_directory_ + + L"\\activex_test_control.dll"; + HMODULE h = LoadLibrary(test_control_path.c_str()); + ASSERT_TRUE(h != NULL) << "Failed to load activex_test_control.dll"; + const char* func_name = register_server ? + "DllRegisterServer" : "DllUnregisterServer"; + DllRegUnregServerFunc func = reinterpret_cast<DllRegUnregServerFunc>( + GetProcAddress(h, func_name)); + // This should never happen actually. + ASSERT_TRUE(func != NULL) << "Failed to find reg/unreg function."; + HRESULT hr = func(); + const char* error_message = register_server ? "Failed to register dll." + : "Failed to unregister dll"; + ASSERT_TRUE(SUCCEEDED(hr)) << error_message; + FreeLibrary(h); + } + private: + bool dll_registered; +}; + +TEST_F(ActiveXTest, EmbeddedWMP) { + TestActiveX(L"activex_embedded_wmp.html", kLongWaitTimeout, false); +} + +TEST_F(ActiveXTest, WMP) { + TestActiveX(L"activex_wmp.html", kLongWaitTimeout, false); +} + +TEST_F(ActiveXTest, CustomScripting) { + TestActiveX(L"activex_custom_scripting.html", kShortWaitTimeout, true); +} + diff --git a/chrome/test/plugin/plugin_tests.vcproj b/chrome/test/plugin/plugin_tests.vcproj new file mode 100644 index 0000000..f8fca50 --- /dev/null +++ b/chrome/test/plugin/plugin_tests.vcproj @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="plugin_tests" + ProjectGUID="{A1CAA831-C507-4B2E-87F3-AEC63C9907F9}" + RootNamespace="plugin_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath=".\plugin_test.cpp" + > + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath="..\ui\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath="..\ui\ui_test.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.h" + > + </File> + <File + RelativePath="..\ui\ui_test_suite.cc" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/reliability/SConscript b/chrome/test/reliability/SConscript new file mode 100644 index 0000000..e0b0a32 --- /dev/null +++ b/chrome/test/reliability/SConscript @@ -0,0 +1,125 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'RELIABILITY_TEST', # seems to be unused
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'psapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/perf/mem_usage$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'page_load_test.cc',
+ 'run_all_unittests.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+
+exe = env_test.Program(['reliability_tests',
+ 'reliability_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/reliability/page_load_test.cc b/chrome/test/reliability/page_load_test.cc new file mode 100644 index 0000000..ee59ad6 --- /dev/null +++ b/chrome/test/reliability/page_load_test.cc @@ -0,0 +1,600 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// This file provides reliablity test which runs under UI test framework. The +// test is intended to run within QEMU environment. +// +// Usage 1: reliability_test +// Upon invocation, it visits a hard coded list of URLs. This is mainly used +// by buildbot, to verify reliability_test itself runs ok. +// +// Usage 2: reliability_test --site=url --startpage=start --endpage=end [...] +// Upon invocation, it visits a list of URLs constructed as +// "http://url/page?id=k". (start <= k <= end). +// +// Usage 3: reliability_test --list=file --startline=start --endline=end [...] +// Upon invocation, it visits each of the URLs on line numbers between start +// and end, inclusive, stored in the input file. The line number starts from 1. +// +// If both "--site" and "--list" are provided, the "--site" set of arguments +// are ignored. +// +// Optional Switches: +// --iterations=num: goes through the list of URLs constructed in usage 2 or 3 +// num times. +// --continuousload: continuously visits the list of URLs without restarting +// browser for each page load. +// --memoryusage: prints out memory usage when visiting each page. +// --endurl=url: visits the specified url in the end. +// --logfile=filepath: saves the visit log to the specified path. +// --timeout=millisecond: time out as specified in millisecond during each +// page load. +// --nopagedown: won't simulate page down key presses after page load. + +#include <fstream> +#include <iostream> + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "chrome/browser/url_fixer_upper.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/test/automation/automation_messages.h" +#include "chrome/test/automation/automation_proxy.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "chrome/test/perf/mem_usage.h" +#include "chrome/test/reliability/page_load_test.h" +#include "net/base/net_util.h" + +namespace { + +// See comments at the beginning of the file for the definition of switches. +const wchar_t kSiteSwitch[] = L"site"; +const wchar_t kStartPageSwitch[] = L"startpage"; +const wchar_t kEndPageSwitch[] = L"endpage"; +const wchar_t kListSwitch[] = L"list"; +const wchar_t kStartIndexSwitch[] = L"startline"; +const wchar_t kEndIndexSwitch[] = L"endline"; +const wchar_t kIterationSwitch[] = L"iterations"; +const wchar_t kContinuousLoadSwitch[] = L"continuousload"; +const wchar_t kMemoryUsageSwitch[] = L"memoryusage"; +const wchar_t kEndURLSwitch[] = L"endurl"; +const wchar_t kLogFileSwitch[] = L"logfile"; +const wchar_t kTimeoutSwitch[] = L"timeout"; +const wchar_t kNoPageDownSwitch[] = L"nopagedown"; + +std::wstring server_url = L"http://urllist.com"; +const wchar_t test_url_1[] = L"http://www.google.com"; +const wchar_t test_url_2[] = L"about:crash"; +const wchar_t test_url_3[] = L"http://www.youtube.com"; +bool append_page_id = false; +int32 start_page; +int32 end_page; +std::wstring url_file_path; +int32 start_index = 1; +int32 end_index = kint32max; +int32 iterations = 1; +bool memory_usage = false; +bool continuous_load = false; +bool browser_existing = false; +bool page_down = true; +std::wstring end_url; +std::wstring log_file_path; +uint32 timeout_ms = INFINITE; + +int kWaitForActionMsec = 4000; + +class PageLoadTest : public UITest { + public: + enum NavigationResult { + NAVIGATION_ERROR = 0, + NAVIGATION_SUCCESS, + NAVIGATION_AUTH_NEEDED, + NAVIGATION_TIME_OUT, + }; + + typedef struct { + // These are results from the test automation that drives Chrome + NavigationResult result; + int crash_dump_count; + // These are stability metrics recorded by Chrome itself + bool browser_clean_exit; + int browser_launch_count; + int page_load_count; + int browser_crash_count; + int renderer_crash_count; + int plugin_crash_count; + } NavigationMetrics; + + PageLoadTest() { + show_window_ = true; + } + + void NavigateToURLLogResult(const GURL& url, std::ofstream& log_file, + NavigationMetrics* metrics_output) { + NavigationMetrics metrics = {NAVIGATION_ERROR}; + + if (!continuous_load && !browser_existing) { + LaunchBrowserAndServer(); + browser_existing = true; + } + + bool is_timeout = false; + int result = AUTOMATION_MSG_NAVIGATION_ERROR; + // This is essentially what NavigateToURL does except we don't fire + // assertion when page loading fails. We log the result instead. + { + // TabProxy should be released before Browser is closed. + scoped_ptr<TabProxy> tab_proxy(GetActiveTab()); + if (tab_proxy.get()) { + result = tab_proxy->NavigateToURLWithTimeout(url, timeout_ms, + &is_timeout); + } + + if (!is_timeout && result == AUTOMATION_MSG_NAVIGATION_SUCCESS) { + if (page_down) { + // Page down twice. + scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + if (browser.get()) { + scoped_ptr<WindowProxy> window( + automation()->GetWindowForBrowser(browser.get())); + if (window.get()) { + bool activation_timeout; + browser->BringToFrontWithTimeout(kWaitForActionMsec, + &activation_timeout); + if (!activation_timeout) { + window->SimulateOSKeyPress(VK_NEXT, 0); + Sleep(kWaitForActionMsec); + window->SimulateOSKeyPress(VK_NEXT, 0); + Sleep(kWaitForActionMsec); + } + } + } + } + } + } + + if (!continuous_load) { + CloseBrowserAndServer(); + browser_existing = false; + } + + // Get navigation result and metrics, and optionally write to the log file + // provided. The log format is: + // <url> <navigation_result> <browser_crash_count> <renderer_crash_count> + // <plugin_crash_count> <crash_dump_count> crash_dump=<path> + if (is_timeout) { + metrics.result = NAVIGATION_TIME_OUT; + // After timeout, the test automation is in the transition state since + // there might be pending IPC messages and the browser (automation + // provider) is still working on the request. Here we just skip the url + // and send the next request. The pending IPC messages will be properly + // discarded by automation message filter. The browser will accept the + // new request and visit the next URL. + // We will revisit the issue if we encounter the situation where browser + // needs to be restarted after timeout. + } else { + switch (result) { + case AUTOMATION_MSG_NAVIGATION_ERROR: + metrics.result = NAVIGATION_ERROR; + break; + case AUTOMATION_MSG_NAVIGATION_SUCCESS: + metrics.result = NAVIGATION_SUCCESS; + break; + case AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED: + metrics.result = NAVIGATION_AUTH_NEEDED; + break; + default: + metrics.result = NAVIGATION_ERROR; + break; + } + } + + if (log_file.is_open()) { + log_file << url.spec(); + switch (metrics.result) { + case NAVIGATION_ERROR: + log_file << " error"; + break; + case NAVIGATION_SUCCESS: + log_file << " success"; + break; + case NAVIGATION_AUTH_NEEDED: + log_file << " auth_needed"; + break; + case NAVIGATION_TIME_OUT: + log_file << " timeout"; + break; + default: + break; + } + } + + // Get stability metrics recorded by Chrome itself. + GetStabilityMetrics(&metrics); + + if (log_file.is_open()) { + log_file << " " << metrics.browser_crash_count \ + // The renderer crash count is flaky due to 1183283. + // Ignore the count since we also catch crash by + // crash_dump_count. + << " " << 0 \ + << " " << metrics.plugin_crash_count \ + << " " << metrics.crash_dump_count; + } + + // Get crash dumps. + LogOrDeleteNewCrashDumps(log_file, &metrics); + + if (log_file.is_open()) { + log_file << std::endl; + } + + if (metrics_output) { + *metrics_output = metrics; + } + } + + void NavigateThroughPageID(std::ofstream& log_file) { + if (append_page_id) { + // For usage 2 + for (int i = start_page; i <= end_page; ++i) { + std::wstring test_page_url( + StringPrintf(L"%s/page?id=%d", server_url.c_str(), i)); + NavigateToURLLogResult(GURL(test_page_url), log_file, NULL); + } + } else { + // Don't run if single process mode. + if (in_process_renderer()) + return; + // For usage 1 + NavigationMetrics metrics; + if (timeout_ms == INFINITE) + timeout_ms = 30000; + + NavigateToURLLogResult(GURL(test_url_1), log_file, &metrics); + // Verify everything is fine + EXPECT_EQ(NAVIGATION_SUCCESS, metrics.result); + EXPECT_EQ(0, metrics.crash_dump_count); + EXPECT_EQ(true, metrics.browser_clean_exit); + EXPECT_EQ(1, metrics.browser_launch_count); + // Both starting page and test_url_1 are loaded. + EXPECT_EQ(2, metrics.page_load_count); + EXPECT_EQ(0, metrics.browser_crash_count); + EXPECT_EQ(0, metrics.renderer_crash_count); + EXPECT_EQ(0, metrics.plugin_crash_count); + + // Go to "about:crash" + uint32 crash_timeout_ms = timeout_ms / 2; + std::swap(timeout_ms, crash_timeout_ms); + NavigateToURLLogResult(GURL(test_url_2), log_file, &metrics); + std::swap(timeout_ms, crash_timeout_ms); + // Page load crashed and test automation timed out. + EXPECT_EQ(NAVIGATION_TIME_OUT, metrics.result); + // Found a crash dump + EXPECT_EQ(1, metrics.crash_dump_count); + // Browser did not crash, and exited cleanly. + EXPECT_EQ(true, metrics.browser_clean_exit); + EXPECT_EQ(1, metrics.browser_launch_count); + // Only starting page was loaded. + EXPECT_EQ(1, metrics.page_load_count); + EXPECT_EQ(0, metrics.browser_crash_count); + // Renderer crashed. + EXPECT_EQ(1, metrics.renderer_crash_count); + EXPECT_EQ(0, metrics.plugin_crash_count); + + uint32 youtube_timeout_ms = timeout_ms * 2; + std::swap(timeout_ms, youtube_timeout_ms); + NavigateToURLLogResult(GURL(test_url_3), log_file, &metrics); + std::swap(timeout_ms, youtube_timeout_ms); + // The data on previous crash should be cleared and we should get + // metrics for a successful page load. + EXPECT_EQ(NAVIGATION_SUCCESS, metrics.result); + EXPECT_EQ(0, metrics.crash_dump_count); + EXPECT_EQ(true, metrics.browser_clean_exit); + EXPECT_EQ(1, metrics.browser_launch_count); + EXPECT_EQ(0, metrics.browser_crash_count); + EXPECT_EQ(0, metrics.renderer_crash_count); + EXPECT_EQ(0, metrics.plugin_crash_count); + + // Verify metrics service does what we need when browser process crashes. + HANDLE browser_process; + LaunchBrowserAndServer(); + { + // TabProxy should be released before Browser is closed. + scoped_ptr<TabProxy> tab_proxy(GetActiveTab()); + if (tab_proxy.get()) { + tab_proxy->NavigateToURL(GURL(test_url_1)); + } + } + // Kill browser process. + browser_process = process(); + TerminateProcess(browser_process, 0); + + GetStabilityMetrics(&metrics); + // This is not a clean shutdown. + EXPECT_EQ(false, metrics.browser_clean_exit); + EXPECT_EQ(1, metrics.browser_crash_count); + EXPECT_EQ(0, metrics.renderer_crash_count); + EXPECT_EQ(0, metrics.plugin_crash_count); + // Relaunch browser so UITest does not fire assertion during TearDown. + LaunchBrowserAndServer(); + } + } + + // For usage 3 + void NavigateThroughURLList(std::ofstream& log_file) { + std::ifstream file(url_file_path.c_str()); + ASSERT_TRUE(file.is_open()); + + for (int line_index = 1; + line_index <= end_index && !file.eof(); + ++line_index) { + std::string url_str; + std::getline(file, url_str); + + if (file.fail()) + break; + + if (start_index <= line_index) { + NavigateToURLLogResult(GURL(url_str), log_file, NULL); + } + } + + file.close(); + } + + protected: + // Call the base class's SetUp method and initialize our own class members. + virtual void SetUp() { + UITest::SetUp(); + browser_existing = true; + + // Initialize crash_dumps_dir_path_. + PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dumps_dir_path_); + // Initialize crash_dumps_. + WIN32_FIND_DATAW find_data; + HANDLE find_handle; + std::wstring dir_spec(crash_dumps_dir_path_); + dir_spec.append(L"\\*"); // list all files in the directory + find_handle = FindFirstFileW(dir_spec.c_str(), &find_data); + if (find_handle != INVALID_HANDLE_VALUE) { + if (wcsstr(find_data.cFileName, L".dmp")) + crash_dumps_[std::wstring(find_data.cFileName)] = true; + while (FindNextFile(find_handle, &find_data)) { + if (wcsstr(find_data.cFileName, L".dmp")) + crash_dumps_[std::wstring(find_data.cFileName)] = true; + } + FindClose(find_handle); + } + } + + // If a log_file is provided, log the crash dump with the given path; + // otherwise, delete the crash dump file. + void LogOrDeleteCrashDump(std::ofstream& log_file, + std::wstring crash_dump_file_name) { + + std::wstring crash_dump_file_path(crash_dumps_dir_path_); + crash_dump_file_path.append(L"\\"); + crash_dump_file_path.append(crash_dump_file_name); + std::wstring crash_text_file_path(crash_dump_file_path); + crash_text_file_path.replace(crash_text_file_path.length() - 3, + 3, L"txt"); + + if (log_file.is_open()) { + crash_dumps_[crash_dump_file_name] = true; + log_file << " crash_dump=" << crash_dump_file_path; + } else { + ASSERT_TRUE(DeleteFileW(crash_dump_file_path.c_str())); + ASSERT_TRUE(DeleteFileW(crash_text_file_path.c_str())); + } + } + + // Check whether there are new .dmp files. Additionally, write + // " crash_dump=<full path name of the .dmp file>" + // to log_file. + void LogOrDeleteNewCrashDumps(std::ofstream& log_file, + NavigationMetrics* metrics) { + WIN32_FIND_DATAW find_data; + HANDLE find_handle; + int num_dumps = 0; + + std::wstring dir_spec(crash_dumps_dir_path_); + dir_spec.append(L"\\*"); // list all files in the directory + find_handle = FindFirstFileW(dir_spec.c_str(), &find_data); + if (find_handle != INVALID_HANDLE_VALUE) { + if (wcsstr(find_data.cFileName, L".dmp") && + !crash_dumps_[std::wstring(find_data.cFileName)]) { + LogOrDeleteCrashDump(log_file, find_data.cFileName); + num_dumps++; + } + while (FindNextFile(find_handle, &find_data)) { + if (wcsstr(find_data.cFileName, L".dmp") && + !crash_dumps_[std::wstring(find_data.cFileName)]) { + LogOrDeleteCrashDump(log_file, find_data.cFileName); + num_dumps++; + } + } + FindClose(find_handle); + } + + if (metrics) + metrics->crash_dump_count = num_dumps; + } + + // Get a PrefService whose contents correspond to the Local State file + // that was saved by the app as it closed. The caller takes ownership of the + // returned PrefService object. + PrefService* GetLocalState() { + std::wstring local_state_path = user_data_dir(); + file_util::AppendToPath(&local_state_path, chrome::kLocalStateFilename); + + PrefService* local_state(new PrefService(local_state_path)); + return local_state; + } + + void GetStabilityMetrics(NavigationMetrics* metrics) { + if (!metrics) + return; + scoped_ptr<PrefService> local_state(GetLocalState()); + if (!local_state.get()) + return; + local_state->RegisterBooleanPref(prefs::kStabilityExitedCleanly, false); + local_state->RegisterIntegerPref(prefs::kStabilityLaunchCount, -1); + local_state->RegisterIntegerPref(prefs::kStabilityPageLoadCount, -1); + local_state->RegisterIntegerPref(prefs::kStabilityCrashCount, 0); + local_state->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0); + + metrics->browser_clean_exit = + local_state->GetBoolean(prefs::kStabilityExitedCleanly); + metrics->browser_launch_count = + local_state->GetInteger(prefs::kStabilityLaunchCount); + metrics->page_load_count = + local_state->GetInteger(prefs::kStabilityPageLoadCount); + metrics->browser_crash_count = + local_state->GetInteger(prefs::kStabilityCrashCount); + metrics->renderer_crash_count = + local_state->GetInteger(prefs::kStabilityRendererCrashCount); + // TODO(huanr) + metrics->plugin_crash_count = 0; + + if (!metrics->browser_clean_exit) + metrics->browser_crash_count++; + } + + // The pathname of Chrome's crash dumps directory. + std::wstring crash_dumps_dir_path_; + + // The set of all the crash dumps we have seen. Each crash generates a + // .dmp and a .txt file in the crash dumps directory. We only store the + // .dmp files in this set. + // + // The set is implemented as a std::map. The key is the file name, and + // the value is false (the file is not in the set) or true (the file is + // in the set). The initial value for any key in std::map is 0 (false), + // which in this case means a new file is not in the set initially, + // exactly the semantics we want. + std::map<std::wstring, bool> crash_dumps_; +}; + +} // namespace + +TEST_F(PageLoadTest, Reliability) { + std::ofstream log_file; + + if (!log_file_path.empty()) { + log_file.open(log_file_path.c_str()); + } + + for (int k = 0; k < iterations; ++k) { + if (url_file_path.empty()) { + NavigateThroughPageID(log_file); + } else { + NavigateThroughURLList(log_file); + } + + if (memory_usage) + PrintChromeMemoryUsageInfo(); + } + + if (!end_url.empty()) { + NavigateToURLLogResult(GURL(end_url), log_file, NULL); + } + + log_file.close(); +} + +void SetPageRange(const CommandLine& parsed_command_line) { + if (parsed_command_line.HasSwitch(kStartPageSwitch)) { + ASSERT_TRUE(parsed_command_line.HasSwitch(kEndPageSwitch)); + start_page = + _wtoi(parsed_command_line.GetSwitchValue(kStartPageSwitch).c_str()); + end_page = + _wtoi(parsed_command_line.GetSwitchValue(kEndPageSwitch).c_str()); + ASSERT_TRUE(start_page > 0 && end_page > 0); + ASSERT_TRUE(start_page < end_page); + append_page_id = true; + } else { + ASSERT_FALSE(parsed_command_line.HasSwitch(kEndPageSwitch)); + } + + if (parsed_command_line.HasSwitch(kSiteSwitch)) + server_url.assign(parsed_command_line.GetSwitchValue(kSiteSwitch)); + + if (parsed_command_line.HasSwitch(kStartIndexSwitch)) { + start_index = + _wtoi(parsed_command_line.GetSwitchValue(kStartIndexSwitch).c_str()); + ASSERT_TRUE(start_index > 0); + } + + if (parsed_command_line.HasSwitch(kEndIndexSwitch)) { + end_index = + _wtoi(parsed_command_line.GetSwitchValue(kEndIndexSwitch).c_str()); + ASSERT_TRUE(end_index > 0); + } + + ASSERT_TRUE(end_index >= start_index); + + if (parsed_command_line.HasSwitch(kListSwitch)) + url_file_path.assign(parsed_command_line.GetSwitchValue(kListSwitch)); + + if (parsed_command_line.HasSwitch(kIterationSwitch)) { + iterations = + _wtoi(parsed_command_line.GetSwitchValue(kIterationSwitch).c_str()); + ASSERT_TRUE(iterations > 0); + } + + if (parsed_command_line.HasSwitch(kMemoryUsageSwitch)) + memory_usage = true; + + if (parsed_command_line.HasSwitch(kContinuousLoadSwitch)) + continuous_load = true; + + if (parsed_command_line.HasSwitch(kEndURLSwitch)) + end_url.assign(parsed_command_line.GetSwitchValue(kEndURLSwitch)); + + if (parsed_command_line.HasSwitch(kLogFileSwitch)) + log_file_path.assign(parsed_command_line.GetSwitchValue(kLogFileSwitch)); + + if (parsed_command_line.HasSwitch(kTimeoutSwitch)) { + timeout_ms = + _wtoi(parsed_command_line.GetSwitchValue(kTimeoutSwitch).c_str()); + ASSERT_TRUE(timeout_ms > 0); + } + + if (parsed_command_line.HasSwitch(kNoPageDownSwitch)) + page_down = false; +} diff --git a/chrome/test/reliability/page_load_test.h b/chrome/test/reliability/page_load_test.h new file mode 100644 index 0000000..8f3c2da --- /dev/null +++ b/chrome/test/reliability/page_load_test.h @@ -0,0 +1,41 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// This file declares helper functions necessary to run reliablity test under +// UI test framework. + +#ifndef CHROME_TEST_RELIABILITY_PAGE_LOAD_TEST_H__ +#define CHROME_TEST_RELIABILITY_PAGE_LOAD_TEST_H__ + +#include "base/command_line.h" + +// Parse the command line options and set the page range accordingly. +void SetPageRange(const CommandLine&); + +#endif // CHROME_TEST_RELIABILITY_PAGE_LOAD_TEST_H__ diff --git a/chrome/test/reliability/reliability_test_suite.h b/chrome/test/reliability/reliability_test_suite.h new file mode 100644 index 0000000..1e971e6 --- /dev/null +++ b/chrome/test/reliability/reliability_test_suite.h @@ -0,0 +1,50 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_RELIABILITY_RELIABILITY_TEST_SUITE_H_ +#define CHROME_TEST_RELIABILITY_RELIABILITY_TEST_SUITE_H_ + +#include "chrome/test/reliability/page_load_test.h" +#include "chrome/test/ui/ui_test_suite.h" + +class ReliabilityTestSuite : public UITestSuite { +public: + ReliabilityTestSuite(int argc, char** argv) : UITestSuite(argc, argv) { + } + +protected: + + virtual void Initialize() { + UITestSuite::Initialize(); + + SetPageRange(parsed_command_line_); + } +}; + +#endif // CHROME_TEST_RELIABILITY_RELIABILITY_TEST_SUITE_H_ diff --git a/chrome/test/reliability/reliability_tests.vcproj b/chrome/test/reliability/reliability_tests.vcproj new file mode 100644 index 0000000..04f0ef9 --- /dev/null +++ b/chrome/test/reliability/reliability_tests.vcproj @@ -0,0 +1,218 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="reliability_tests" + ProjectGUID="{8A3E1774-1DE9-445C-982D-3EE37C8A752A}" + RootNamespace="reliability_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;..\..\tools\build\win\reliability_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;..\..\tools\build\win\reliability_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath=".\reliability_test_suite.h" + > + </File> + <File + RelativePath=".\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath="..\ui\ui_test.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.h" + > + </File> + <File + RelativePath="..\ui\ui_test_suite.cc" + > + </File> + </Filter> + <Filter + Name="MemoryUsage" + > + <File + RelativePath="..\perf\mem_usage.cc" + > + </File> + <File + RelativePath="..\perf\mem_usage.h" + > + </File> + </Filter> + <Filter + Name="TestPageLoader" + > + <File + RelativePath=".\page_load_test.cc" + > + </File> + <File + RelativePath=".\page_load_test.h" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/reliability/run_all_unittests.cc b/chrome/test/reliability/run_all_unittests.cc new file mode 100644 index 0000000..a5d3da3 --- /dev/null +++ b/chrome/test/reliability/run_all_unittests.cc @@ -0,0 +1,34 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/reliability/reliability_test_suite.h" + +int main(int argc, char **argv) { + return ReliabilityTestSuite(argc, argv).Run(); +} diff --git a/chrome/test/security_tests/SConscript b/chrome/test/security_tests/SConscript new file mode 100644 index 0000000..39300c8 --- /dev/null +++ b/chrome/test/security_tests/SConscript @@ -0,0 +1,91 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env')
+
+env = env.Clone()
+
+
+env.Prepend(
+ CPPPATH = [
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+
+ '/MANIFEST',
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+
+ '/DEBUG',
+ ],
+ LIBS = [
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+#/MANIFESTFILE:"C:\src\trunk-vs\chrome\Debug\obj\test_chrome_plugin\test_chrome_plugin.dll.intermediate.manifest"
+#/PDB:"c:\src\trunk-vs\chrome\Debug\test_chrome_plugin.pdb"
+
+input_files = [
+ 'ipc_security_tests.cc',
+ 'security_tests.cc',
+ '$SANDBOX_DIR/tests/validation_tests/commands${OBJSUFFIX}',
+]
+
+dll = env.SharedLibrary('security_tests', input_files)
+
+i = env.Install('$TARGET_ROOT', dll)
+env.Alias('chrome', i)
diff --git a/chrome/test/security_tests/ipc_security_tests.cc b/chrome/test/security_tests/ipc_security_tests.cc new file mode 100644 index 0000000..e85e09b --- /dev/null +++ b/chrome/test/security_tests/ipc_security_tests.cc @@ -0,0 +1,217 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <windows.h> +#include <string> +#include <sstream> + +#include "chrome/test/security_tests/ipc_security_tests.h" + +namespace { + +// Debug output messages prefix. +const char kODSMgPrefix[] = "[security] "; +// Format of the Chrome browser pipe for plugins. +const wchar_t kChromePluginPipeFmt[] = L"\\\\.\\pipe\\chrome.%s.p%d"; +// Size for the in/out pipe buffers. +const int kBufferSize = 1024; + +// Define the next symbol if you want to have tracing of errors. +#ifdef PIPE_SECURITY_DBG +// Generic debug output function. +void ODSMessageGLE(const char* txt) { + DWORD gle = ::GetLastError(); + std::ostringstream oss; + oss << kODSMgPrefix << txt << " 0x" << std::hex << gle; + ::OutputDebugStringA(oss.str().c_str()); +} +#else +void ODSMessageGLE(const char* txt) { +} +#endif + +// Retrieves the renderer pipe name from the command line. Returns true if the +// name was found. +bool PipeNameFromCommandLine(std::wstring* pipe_name) { + std::wstring cl(::GetCommandLineW()); + const wchar_t key_name[] = L"--channel"; + std::wstring::size_type pos = cl.find(key_name, 0); + if (std::wstring::npos == pos) { + return false; + } + pos = cl.find(L"=", pos); + if (std::wstring::npos == pos) { + return false; + } + ++pos; + size_t dst = cl.length() - pos; + if (dst <4) { + return false; + } + for (; dst != 0; --dst) { + if (!isspace(cl[pos])) { + break; + } + ++pos; + } + if (0 == dst) { + return false; + } + std::wstring::size_type pos2 = pos; + for (; dst != 0; --dst) { + if (isspace(cl[pos2])) { + break; + } + ++pos2; + } + *pipe_name = cl.substr(pos, pos2); + return true; +} + +// Extracts the browser process id and the channel id given the renderer +// pipe name. +bool InfoFromPipeName(const std::wstring& pipe_name, std::wstring* parent_id, + std::wstring* channel_id) { + std::wstring::size_type pos = pipe_name.find(L".", 0); + if (std::wstring::npos == pos) { + return false; + } + *parent_id = pipe_name.substr(0, pos); + *channel_id = pipe_name.substr(pos + 1); + return true; +} + +// Creates a server pipe, in byte mode. +HANDLE MakeServerPipeBase(const wchar_t* pipe_name) { + HANDLE pipe = ::CreateNamedPipeW(pipe_name, PIPE_ACCESS_DUPLEX, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 3, + kBufferSize, kBufferSize, 5000, NULL); + if (INVALID_HANDLE_VALUE == pipe) { + ODSMessageGLE("pipe creation failed"); + } + return pipe; +} + +// Creates a chrome plugin server pipe. +HANDLE MakeServerPluginPipe(const std::wstring& prefix, int channel) { + wchar_t pipe_name[MAX_PATH]; + swprintf_s(pipe_name, kChromePluginPipeFmt, prefix.c_str(), channel); + return MakeServerPipeBase(pipe_name); +} + +struct Context { + HANDLE pipe; + Context(HANDLE arg_pipe) : pipe(arg_pipe) { + } +}; + +// This function is called from a thread that has a security context that is +// higher than the renderer security context. This can be the plugin security +// context or the browser security context. +void DoEvilThings(Context* context) { + // To make the test fail we simply trigger a breakpoint in the renderer. + ::DisconnectNamedPipe(context->pipe); + __debugbreak(); +} + +// This is a pipe server thread routine. +DWORD WINAPI PipeServerProc(void* thread_param) { + if (NULL == thread_param) { + return 0; + } + Context* context = static_cast<Context*>(thread_param); + HANDLE server_pipe = context->pipe; + + char buffer[4]; + DWORD bytes_read = 0; + + for (;;) { + // The next call blocks until a connection is made. + if (!::ConnectNamedPipe(server_pipe, NULL)) { + if (GetLastError() != ERROR_PIPE_CONNECTED) { + ODSMessageGLE("== connect named pipe failed =="); + continue; + } + } + // return value of ReadFile is unimportant. + ::ReadFile(server_pipe, buffer, 1, &bytes_read, NULL); + if (::ImpersonateNamedPipeClient(server_pipe)) { + ODSMessageGLE("impersonation obtained"); + DoEvilThings(context); + break; + } else { + ODSMessageGLE("impersonation failed"); + } + ::DisconnectNamedPipe(server_pipe); + } + delete context; + return 0; +} +} // namespace + +// Implements a pipe impersonation attack resulting on a privilege elevation on +// the chrome pipe-based IPC. +// When a web-page that has a plug-in is loaded, chrome will do the following +// steps: +// 1) Creates a server pipe with name 'chrome.<pid>.p<n>'. Initially n = 1. +// 2) Launches chrome with command line --type=plugin --channel=<pid>.p<n> +// 3) The new (plugin) process connects to the pipe and sends a 'hello' +// message. +// The attack creates another server pipe with the same name before step one +// so when the plugin connects it connects to the renderer instead. Once the +// connection is acepted and at least a byte is read from the pipe, the +// renderer can impersonate the plugin process which has a more relaxed +// security context (privilege elevation). +// +// Note that the attack can also be peformed after step 1. In this case we need +// another thread which used to connect to the existing server pipe so the +// plugin does not connect to chrome but to our pipe. +bool PipeImpersonationAttack() { + std::wstring pipe_name; + if (!PipeNameFromCommandLine(&pipe_name)) { + return false; + } + std::wstring parent_id; + std::wstring channel_id; + if (!InfoFromPipeName(pipe_name, &parent_id, &channel_id)) { + return false; + } + HANDLE plugin_pipe = MakeServerPluginPipe(parent_id, 1); + if (INVALID_HANDLE_VALUE == plugin_pipe) { + return true; + } + + HANDLE thread = ::CreateThread(NULL, 0, PipeServerProc, + new Context(plugin_pipe), 0, NULL); + if (NULL == thread) { + return false; + } + ::CloseHandle(thread); + return true; +} diff --git a/chrome/test/security_tests/ipc_security_tests.h b/chrome/test/security_tests/ipc_security_tests.h new file mode 100644 index 0000000..8706570 --- /dev/null +++ b/chrome/test/security_tests/ipc_security_tests.h @@ -0,0 +1,39 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_SECURITY_TESTS_IPC_SECURITY_TESTS_H__ +#define CHROME_TEST_SECURITY_TESTS_IPC_SECURITY_TESTS_H__ + +// Impersonates a chrome server pipe. See the implementation for details. +// Returns false if the attack could not be set. If it returns true then +// it spawns a thread that will terminate the renderer if the attack is +// successful. +bool PipeImpersonationAttack(); + +#endif // CHROME_TEST_SECURITY_TESTS_IPC_SECURITY_TESTS_H__ diff --git a/chrome/test/security_tests/security_tests.cc b/chrome/test/security_tests/security_tests.cc new file mode 100644 index 0000000..e86df13 --- /dev/null +++ b/chrome/test/security_tests/security_tests.cc @@ -0,0 +1,87 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <windows.h> +#include <string> + +#define TEST_INJECTION_DLL +#include "chrome/test/injection_test_dll.h" +#include "chrome/test/security_tests/ipc_security_tests.h" +#include "sandbox/tests/common/controller.h" +#include "sandbox/tests/validation_tests/commands.h" + +#define SECURITY_CHECK(x) (*test_count)++; \ + if (SBOX_TEST_DENIED != x) { \ + return FALSE; \ + }; + +BOOL APIENTRY DllMain(HMODULE module, DWORD ul_reason_for_call, + LPVOID lpReserved) { + return TRUE; +} + +// Runs the security tests of sandbox for the renderer process. +// If a test fails, the return value is FALSE and test_count contains the +// number of tests executed, including the failing test. +BOOL __declspec(dllexport) __cdecl RunRendererTests(int *test_count) { + using namespace sandbox; + *test_count = 0; + SECURITY_CHECK(TestOpenReadFile(L"%SystemDrive%")); + SECURITY_CHECK(TestOpenReadFile(L"%SystemRoot%")); + SECURITY_CHECK(TestOpenReadFile(L"%ProgramFiles%")); + SECURITY_CHECK(TestOpenReadFile(L"%SystemRoot%\\System32")); + SECURITY_CHECK(TestOpenReadFile(L"%SystemRoot%\\explorer.exe")); + SECURITY_CHECK(TestOpenReadFile(L"%SystemRoot%\\Cursors\\arrow_i.cur")); + SECURITY_CHECK(TestOpenReadFile(L"%AllUsersProfile%")); + SECURITY_CHECK(TestOpenReadFile(L"%Temp%")); + SECURITY_CHECK(TestOpenReadFile(L"%AppData%")); + SECURITY_CHECK(TestOpenKey(HKEY_LOCAL_MACHINE, L"")); + SECURITY_CHECK(TestOpenKey(HKEY_CURRENT_USER, L"")); + SECURITY_CHECK(TestOpenKey(HKEY_USERS, L"")); + SECURITY_CHECK(TestOpenKey(HKEY_LOCAL_MACHINE, + L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon")); + // Test below run on a separate thread because they cannot block the + // renderer process. Therefore they do not return a meaningful value. + PipeImpersonationAttack(); + return TRUE; +} + +// Runs the security tests of sandbox for the plugin process. +// If a test fails, the return value is FALSE and test_count contains the +// number of tests executed, including the failing test. +BOOL __declspec(dllexport) __cdecl RunPluginTests(int *test_count) { + using namespace sandbox; + *test_count = 0; + SECURITY_CHECK(TestOpenWriteFile(L"%SystemRoot%")); + SECURITY_CHECK(TestOpenWriteFile(L"%ProgramFiles%")); + SECURITY_CHECK(TestOpenWriteFile(L"%SystemRoot%\\System32")); + SECURITY_CHECK(TestOpenWriteFile(L"%SystemRoot%\\explorer.exe")); + SECURITY_CHECK(TestOpenWriteFile(L"%SystemRoot%\\Cursors\\arrow_i.cur")); + return TRUE; +} diff --git a/chrome/test/security_tests/security_tests.vcproj b/chrome/test/security_tests/security_tests.vcproj new file mode 100644 index 0000000..1149b68 --- /dev/null +++ b/chrome/test/security_tests/security_tests.vcproj @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="security_tests" + ProjectGUID="{E750512D-FC7C-4C98-BF04-0A0DAF882055}" + RootNamespace="security_tests" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="2" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="2" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath="..\..\..\sandbox\tests\validation_tests\commands.cc" + > + </File> + <File + RelativePath="..\..\..\sandbox\tests\validation_tests\commands.h" + > + </File> + <File + RelativePath="..\injection_test_dll.h" + > + </File> + <File + RelativePath=".\ipc_security_tests.cc" + > + </File> + <File + RelativePath=".\ipc_security_tests.h" + > + </File> + <File + RelativePath=".\security_tests.cc" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/selenium/README b/chrome/test/selenium/README new file mode 100644 index 0000000..a9e60f6 --- /dev/null +++ b/chrome/test/selenium/README @@ -0,0 +1,2 @@ +This directory contains code to automate the selenium core test suite found +under chrome/test/third_party/selenium_core/. diff --git a/chrome/test/selenium/SConscript b/chrome/test/selenium/SConscript new file mode 100644 index 0000000..eaa1b6e --- /dev/null +++ b/chrome/test/selenium/SConscript @@ -0,0 +1,122 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'selenium_test.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+exe = env_test.Program(['selenium_tests',
+ 'selenium_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/selenium/expected_failures.txt b/chrome/test/selenium/expected_failures.txt new file mode 100644 index 0000000..455ac71 --- /dev/null +++ b/chrome/test/selenium/expected_failures.txt @@ -0,0 +1 @@ +46.type diff --git a/chrome/test/selenium/selenium_test.cc b/chrome/test/selenium/selenium_test.cc new file mode 100644 index 0000000..043def8 --- /dev/null +++ b/chrome/test/selenium/selenium_test.cc @@ -0,0 +1,196 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a gTest-based test that runs the Selenium Core testsuite in Chrome +// using the UITest automation. The number of total and failed tests are +// written to stdout. +// +// TODO(darin): output the names of the failed tests so we can easily track +// deviations from the expected output. + +#include <list> +#include <set> + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/rand_util.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "net/base/net_util.h" + +// Uncomment this to exercise this test without actually running the selenium +// test, which can take a while to run. This define is useful when modifying +// the analysis code. +//#define SIMULATE_RUN 1 + +namespace { + +// This file is a comma separated list of tests that are currently failing. +const wchar_t kExpectedFailuresFileName[] = L"expected_failures.txt"; + +class SeleniumTest : public UITest { + public: + SeleniumTest() { + show_window_ = true; + } + typedef std::list<std::string> ResultsList; + typedef std::set<std::string> ResultsSet; + + // Parses a selenium results string, which is of the form: + // "5.selectFrame,6.click,24.selectAndWait,24.verifyTitle" + void ParseResults(const std::string& input, ResultsSet* output) { + if (input.empty()) + return; + + std::vector<std::string> tokens; + SplitString(input, ',', &tokens); + for (size_t i = 0; i < tokens.size(); ++i) { + TrimWhitespace(tokens[i], TRIM_ALL, &tokens[i]); + output->insert(tokens[i]); + } + } + + // Find the elements of "b" that are not in "a" + void CompareSets(const ResultsSet& a, const ResultsSet& b, + ResultsList* only_in_b) { + ResultsSet::const_iterator it = b.begin(); + for (; it != b.end(); ++it) { + if (a.find(*it) == a.end()) + only_in_b->push_back(*it); + } + } + + // The results file is in trunk/chrome/test/selenium/ + std::wstring GetResultsFilePath() { + std::wstring results_path; + PathService::Get(chrome::DIR_TEST_DATA, &results_path); + file_util::UpOneDirectory(&results_path); + file_util::AppendToPath(&results_path, L"selenium"); + + file_util::AppendToPath(&results_path, kExpectedFailuresFileName); + return results_path; + } + + bool ReadExpectedResults(std::string* results) { + std::wstring results_path = GetResultsFilePath(); + return file_util::ReadFileToString(results_path, results); + } + + void RunSelenium(std::wstring* total, std::wstring* failed) { +#ifdef SIMULATE_RUN + *total = L"100"; + const wchar_t* kBogusFailures[] = { + L"5.selectFrame,6.click,24.selectAndWait,24.verifyTitle", + L"5.selectFrame,6.click,13.verifyLocation,13.verifyLocation,13.click,24.selectAndWait,24.verifyTitle", + L"5.selectFrame,6.click,24.selectAndWait" + }; + *failed = kBogusFailures[rand_util::RandInt(0, 2)]; +#else + std::wstring test_path; + PathService::Get(chrome::DIR_TEST_DATA, &test_path); + file_util::UpOneDirectory(&test_path); + file_util::UpOneDirectory(&test_path); + file_util::UpOneDirectory(&test_path); + file_util::AppendToPath(&test_path, L"data"); + file_util::AppendToPath(&test_path, L"selenium_core"); + file_util::AppendToPath(&test_path, L"core"); + file_util::AppendToPath(&test_path, L"TestRunner.html"); + + GURL test_url(net_util::FilePathToFileURL(test_path)); + scoped_ptr<TabProxy> tab(GetActiveTab()); + tab->NavigateToURL(test_url); + + // Wait for the test to finish. + ASSERT_TRUE(WaitUntilCookieValue(tab.get(), test_url, "__tests_finished", + 3000, UITest::test_timeout_ms(), "1")); + + std::string cookie; + ASSERT_TRUE(tab->GetCookieByName(test_url, "__num_tests_total", &cookie)); + total->swap(UTF8ToWide(cookie)); + ASSERT_FALSE(total->empty()); + ASSERT_TRUE(tab->GetCookieByName(test_url, "__tests_failed", &cookie)); + failed->swap(UTF8ToWide(cookie)); + // The __tests_failed cookie will be empty if all the tests pass. +#endif + } + + void RunTest(ResultsList* new_passes_list, ResultsList* new_failures_list) { + std::string expected_failures; + bool have_expected_results = ReadExpectedResults(&expected_failures); + ASSERT_TRUE(have_expected_results); + + std::wstring total, failed; + RunSelenium(&total, &failed); + if (total.empty()) + return; + + printf("\n"); + wprintf(L"__num_tests_total = [%s]\n", total.c_str()); + wprintf(L"__tests_failed = [%s]\n", failed.c_str()); + + std::string cur_failures = WideToUTF8(failed); + + ResultsSet expected_failures_set; + ParseResults(expected_failures, &expected_failures_set); + + ResultsSet cur_failures_set; + ParseResults(cur_failures, &cur_failures_set); + + // Compute the list of new passes and failures + CompareSets(cur_failures_set, expected_failures_set, new_passes_list); + CompareSets(expected_failures_set, cur_failures_set, new_failures_list); + } +}; + +} // namespace + +TEST_F(SeleniumTest, Core) { + ResultsList new_passes_list, new_failures_list; + RunTest(&new_passes_list, &new_failures_list); + + if (!new_failures_list.empty()) { + ADD_FAILURE(); + printf("new tests failing:\n"); + ResultsList::const_iterator it = new_failures_list.begin(); + for (; it != new_failures_list.end(); ++it) + printf(" %s\n", it->c_str()); + printf("\n"); + } + + if (!new_passes_list.empty()) { + printf("new tests passing:\n"); + ResultsList::const_iterator it = new_passes_list.begin(); + for (; it != new_passes_list.end(); ++it) + printf(" %s\n", it->c_str()); + printf("\n"); + } +} diff --git a/chrome/test/selenium/selenium_tests.vcproj b/chrome/test/selenium/selenium_tests.vcproj new file mode 100644 index 0000000..572819c --- /dev/null +++ b/chrome/test/selenium/selenium_tests.vcproj @@ -0,0 +1,198 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="selenium_tests" + ProjectGUID="{E3749617-BA3D-4230-B54C-B758E56D9FA5}" + RootNamespace="selenium_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath="..\ui\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath="..\ui\ui_test.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.h" + > + </File> + <File + RelativePath="..\ui\ui_test_suite.cc" + > + </File> + </Filter> + <Filter + Name="TestSelenium" + > + <File + RelativePath=".\selenium_test.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/startup/SConscript b/chrome/test/startup/SConscript new file mode 100644 index 0000000..4f48ee5 --- /dev/null +++ b/chrome/test/startup/SConscript @@ -0,0 +1,121 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'feature_startup_test.cc',
+ 'startup_test.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+exe = env_test.Program(['startup_tests',
+ 'startup_tests.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/startup/feature_startup_test.cc b/chrome/test/startup/feature_startup_test.cc new file mode 100644 index 0000000..3173fca --- /dev/null +++ b/chrome/test/startup/feature_startup_test.cc @@ -0,0 +1,159 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <windows.h> + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/perftimer.h" +#include "base/time.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/win_util.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "net/base/net_util.h" + +namespace { + +// Returns the directory name where the "typical" user data is that we use for +// testing. +std::wstring ComputeTypicalUserDataSource() { + std::wstring source_history_file; + EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, + &source_history_file)); + file_util::AppendToPath(&source_history_file, L"profiles"); + file_util::AppendToPath(&source_history_file, L"typical_history"); + return source_history_file; +} + +class NewTabUIStartupTest : public UITest { + public: + NewTabUIStartupTest() { + show_window_ = true; + } + + void SetUp() {} + void TearDown() {} + + static const int kNumCycles = 5; + + void PrintTimings(const char* label, TimeDelta timings[kNumCycles]) { + printf("\n%s = [", label); + for (int i = 0; i < kNumCycles; ++i) { + if (i > 0) + printf(","); + printf("%.2f", timings[i].InMillisecondsF()); + } + printf("]\n"); + } + + // Run the test, by bringing up a browser and timing the new tab startup. + // |want_warm| is true if we should output warm-disk timings, false if + // we should report cold timings. + void RunStartupTest(bool want_warm) { + // Install the location of the test profile file. + set_template_user_data(ComputeTypicalUserDataSource()); + + TimeDelta timings[kNumCycles]; + for (int i = 0; i < kNumCycles; ++i) { + UITest::SetUp(); + + // Switch to the "new tab" tab, which should be any new tab after the + // first (the first is about:blank). + BrowserProxy* window = automation()->GetBrowserWindow(0); + ASSERT_TRUE(window); + int old_tab_count = -1; + ASSERT_TRUE(window->GetTabCount(&old_tab_count)); + ASSERT_EQ(1, old_tab_count); + + // Hit ctl-t and wait for the tab to load. + window->ApplyAccelerator(IDC_NEWTAB); + int new_tab_count = -1; + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + ASSERT_EQ(2, new_tab_count); + int load_time; + ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time)); + timings[i] = TimeDelta::FromMilliseconds(load_time); + + if (want_warm) { + // Bring up a second tab, now that we've already shown one tab. + old_tab_count = new_tab_count; + new_tab_count = -1; + window->ApplyAccelerator(IDC_NEWTAB); + ASSERT_TRUE(window->WaitForTabCountToChange(old_tab_count, &new_tab_count, + 5000)); + ASSERT_EQ(3, new_tab_count); + ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time)); + timings[i] = TimeDelta::FromMilliseconds(load_time); + } + + delete window; + UITest::TearDown(); + } + + // The buildbot log-scraper looks for this "__.._pages" line to tell when + // the test has completed and how many pages it loaded. + printf("\n__ts_pages = [about:blank]\n"); + PrintTimings("__ts_timings", timings); + } +}; + +// The name of this test is important, since the buildbot runs with a gTest +// filter. +typedef NewTabUIStartupTest NewTabUIStartupTestReference; + +} // namespace + +TEST_F(NewTabUIStartupTest, PerfCold) { + RunStartupTest(false); +} + +TEST_F(NewTabUIStartupTest, DISABLED_PerfWarm) { + RunStartupTest(true); +} + +TEST_F(NewTabUIStartupTestReference, FakePerfForLogScraperCold) { + // Print an empty reference-test result line so the log-scraper is happy. + // TODO(pamg): really run the test with a reference build? + TimeDelta timings[kNumCycles]; + for (int i = 0; i < kNumCycles; ++i) + timings[i] = TimeDelta::FromMilliseconds(0); + PrintTimings("__ts_reference_timings", timings); +} + +TEST_F(NewTabUIStartupTestReference, FakePerfForLogScraperWarm) { + // Print an empty reference-test result line so the log-scraper is happy. + // TODO(pamg): really run the test with a reference build? + TimeDelta timings[kNumCycles]; + for (int i = 0; i < kNumCycles; ++i) + timings[i] = TimeDelta::FromMilliseconds(0); + PrintTimings("__ts_reference_timings", timings); +}
\ No newline at end of file diff --git a/chrome/test/startup/startup_test.cc b/chrome/test/startup/startup_test.cc new file mode 100644 index 0000000..018faf8 --- /dev/null +++ b/chrome/test/startup/startup_test.cc @@ -0,0 +1,152 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/time.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/ui/ui_test.h" +#include "net/base/net_util.h" + +namespace { + +class StartupTest : public UITest { + public: + StartupTest() { + show_window_ = true; + pages_ = "about:blank"; + } + void SetUp() {} + void TearDown() {} + + void RunStartupTest(const char* label, bool test_cold) { + const int kNumCycles = 20; + + // Make a backup of gears.dll so we can overwrite the original, which + // flushes the disk cache for that file. + std::wstring chrome_dll, chrome_dll_copy; + ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &chrome_dll)); + file_util::AppendToPath(&chrome_dll, L"chrome.dll"); + chrome_dll_copy = chrome_dll + L".copy"; + ASSERT_TRUE(file_util::CopyFile(chrome_dll, chrome_dll_copy)); + + std::wstring gears_dll, gears_dll_copy; + ASSERT_TRUE(PathService::Get(chrome::FILE_GEARS_PLUGIN, &gears_dll)); + gears_dll_copy = gears_dll + L".copy"; + ASSERT_TRUE(file_util::CopyFile(gears_dll, gears_dll_copy)); + + TimeDelta timings[kNumCycles]; + for (int i = 0; i < kNumCycles; ++i) { + if (test_cold) { + ASSERT_TRUE(file_util::CopyFile(chrome_dll_copy, chrome_dll)); + ASSERT_TRUE(file_util::CopyFile(gears_dll_copy, gears_dll)); + } + + UITest::SetUp(); + TimeTicks end_time = TimeTicks::Now(); + timings[i] = end_time - browser_launch_time_; + // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we + // do, we crash. + Sleep(50); + UITest::TearDown(); + + if (i == 0) { + // Re-use the profile data after first run so that the noise from + // creating databases doesn't impact all the runs. + clear_profile_ = false; + } + } + + ASSERT_TRUE(file_util::Delete(chrome_dll_copy, false)); + ASSERT_TRUE(file_util::Delete(gears_dll_copy, false)); + + printf("\n__ts_pages = [%s]\n", pages_.c_str()); + printf("\n%s = [", label); + for (int i = 0; i < kNumCycles; ++i) { + if (i > 0) + printf(","); + printf("%.2f", timings[i].InMillisecondsF()); + } + printf("]\n"); + } + + protected: + std::string pages_; +}; + +class StartupReferenceTest : public StartupTest { + public: + // override the browser directory that is used by UITest::SetUp to cause it + // to use the reference build instead. + void SetUp() { + std::wstring dir; + PathService::Get(chrome::DIR_TEST_TOOLS, &dir); + file_util::AppendToPath(&dir, L"reference_build"); + file_util::AppendToPath(&dir, L"chrome"); + browser_directory_ = dir; + } +}; + +class StartupFileTest : public StartupTest { + public: + // Load a file on startup rather than about:blank. This tests a longer + // startup path, including resource loading and the loading of gears.dll. + void SetUp() { + std::wstring file_url; + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &file_url)); + file_util::AppendToPath(&file_url, L"empty.html"); + ASSERT_TRUE(file_util::PathExists(file_url)); + launch_arguments_ += file_url; + + pages_ = WideToUTF8(file_url); + } +}; +} // namespace + +TEST_F(StartupTest, Perf) { + RunStartupTest("__ts_timings", false); +} + +TEST_F(StartupReferenceTest, Perf) { + RunStartupTest("__ts_reference_timings", false); +} + +// TODO(mpcomplete): Should we have reference timings for all these? + +TEST_F(StartupTest, PerfCold) { + RunStartupTest("__ts_cold_timings", true); +} + +TEST_F(StartupFileTest, PerfGears) { + RunStartupTest("__ts_gears_timings", false); +} + +TEST_F(StartupFileTest, PerfColdGears) { + RunStartupTest("__ts_cold_gears_timings", true); +} diff --git a/chrome/test/startup/startup_tests.vcproj b/chrome/test/startup/startup_tests.vcproj new file mode 100644 index 0000000..e7f38a2 --- /dev/null +++ b/chrome/test/startup/startup_tests.vcproj @@ -0,0 +1,206 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="startup_tests" + ProjectGUID="{D3E6C0FD-54C7-4FF2-9AE1-72F2DAFD820C}" + RootNamespace="startup_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\tools\build\win\precompiled.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled.h" + > + </File> + <File + RelativePath="..\ui\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\test_file_util.h" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath="..\ui\ui_test.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.h" + > + </File> + <File + RelativePath="..\ui\ui_test_suite.cc" + > + </File> + </Filter> + <Filter + Name="TestStartup" + > + <File + RelativePath=".\feature_startup_test.cc" + > + </File> + <File + RelativePath=".\startup_test.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/tab_switching/SConscript b/chrome/test/tab_switching/SConscript new file mode 100644 index 0000000..d825fa3 --- /dev/null +++ b/chrome/test/tab_switching/SConscript @@ -0,0 +1,125 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'UI_TEST',
+ 'UNIT_TEST',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$GTEST_DIR/include',
+ '$GTEST_DIR',
+ '$SKIA_DIR/include',
+ '$SKIA_DIR/include/corecg',
+ '$SKIA_DIR/platform',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'winmm.lib',
+ 'psapi.lib',
+ 'rpcrt4.lib',
+ 'oleacc.lib',
+ 'comsupp.lib',
+
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ '$CHROME_DIR/test/ui/run_all_unittests$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test$OBJSUFFIX',
+ '$CHROME_DIR/test/ui/ui_test_suite$OBJSUFFIX',
+ '$CHROME_DIR/test/test_file_util$OBJSUFFIX',
+ 'tab_switching_test.cc',
+]
+
+libs = [
+ '$GOOGLEURL_DIR/googleurl.lib',
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$TESTING_DIR/gtest.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$CHROME_DIR/common/common.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$MODP_B64_DIR/modp_b64.lib',
+ '$CHROME_DIR/browser/browser.lib',
+ '$NET_DIR/net.lib',
+ '$BASE_DIR/base.lib',
+ '$CHROME_DIR/test/automation/automation.lib',
+]
+
+#"..\..\Debug\obj\tab_switching_test\precompiled_wtl.obj"
+
+exe = env_test.Program(['tab_switching_test',
+ 'tab_switching_test.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/test/tab_switching/tab_switching.vcproj b/chrome/test/tab_switching/tab_switching.vcproj new file mode 100644 index 0000000..d9a9b03 --- /dev/null +++ b/chrome/test/tab_switching/tab_switching.vcproj @@ -0,0 +1,198 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="tab_switching_test" + ProjectGUID="{A34770EA-A574-43E8-9327-F79C04770E98}" + RootNamespace="tab_switching_test" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath="..\ui\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath="..\ui\ui_test.cc" + > + </File> + <File + RelativePath="..\ui\ui_test.h" + > + </File> + <File + RelativePath="..\ui\ui_test_suite.cc" + > + </File> + </Filter> + <Filter + Name="TabSwitchingTest" + > + <File + RelativePath=".\tab_switching_test.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/tab_switching/tab_switching_test.cc b/chrome/test/tab_switching/tab_switching_test.cc new file mode 100644 index 0000000..2b96bc8 --- /dev/null +++ b/chrome/test/tab_switching/tab_switching_test.cc @@ -0,0 +1,170 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/time.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_util.h" + +#define NUMBER_OF_ITERATIONS 5 + +namespace { + +// This Automated UI test opens static files in different tabs in a proxy +// browser. After all the tabs have opened, it switches between tabs, and notes +// time taken for each switch. It then prints out the times on the console, +// with the aim that the page cycler parser can interpret these numbers to +// draw graphs for page cycler Tab Switching Performance. +// Usage Flags: -enable-logging -dump-histograms-on-exit +class TabSwitchingUITest : public UITest { + public: + TabSwitchingUITest() { + PathService::Get(base::DIR_EXE, &path_prefix_); + file_util::UpOneDirectory(&path_prefix_); + file_util::UpOneDirectory(&path_prefix_); + file_util::AppendToPath(&path_prefix_, L"data"); + file_util::AppendToPath(&path_prefix_, L"tab_switching"); + path_prefix_ += file_util::kPathSeparator; + + show_window_ = true; + } + + void RunTabSwitchingUITest() { + // Create a browser proxy. + browser_proxy_.reset(automation()->GetBrowserWindow(0)); + + // Open all the tabs. + int initial_tab_count = 0; + ASSERT_TRUE(browser_proxy_->GetTabCount(&initial_tab_count)); + int new_tab_count = OpenTabs(); + int final_tab_count = 0; + ASSERT_TRUE(browser_proxy_->WaitForTabCountToChange(initial_tab_count, + &final_tab_count, + 10000)); + ASSERT_TRUE(final_tab_count == initial_tab_count + new_tab_count); + + // Switch linearly between tabs. + browser_proxy_->ActivateTab(0); + for (int i = initial_tab_count; i < final_tab_count; ++i) { + browser_proxy_->ActivateTab(i); + ASSERT_TRUE(browser_proxy_->WaitForTabToBecomeActive(i, 10000)); + } + + // Close the browser to force a dump of log. + bool application_closed = false; + EXPECT_TRUE(CloseBrowser(browser_proxy_.get(), &application_closed)); + + // Now open the corresponding log file and collect average and std dev from + // the histogram stats generated for RenderWidgetHostHWND_WhiteoutDuration + std::wstring log_file_name; + PathService::Get(chrome::DIR_LOGS, &log_file_name); + file_util::AppendToPath(&log_file_name, L"chrome_debug.log"); + + bool log_has_been_dumped = false; + std::string contents; + do { + log_has_been_dumped = file_util::ReadFileToString(log_file_name, + &contents); + } while (!log_has_been_dumped); + + // Parse the contents to get average and std deviation. + std::string average("0.0"), std_dev("0.0"); + const std::string average_str("average = "); + const std::string std_dev_str("standard deviation = "); + std::string::size_type pos = contents.find( + "Histogram: RenderWidgetHostHWND_WhiteoutDuration", 0); + std::string::size_type comma_pos; + std::string::size_type number_length; + if (pos != std::string::npos) { + // Get the average. + pos = contents.find(average_str, pos); + comma_pos = contents.find(",", pos); + pos += average_str.length(); + number_length = comma_pos - pos; + average = contents.substr(pos, number_length); + + // Get the std dev. + pos = contents.find(std_dev_str, pos); + pos += std_dev_str.length(); + comma_pos = contents.find(" ", pos); + number_length = comma_pos - pos; + std_dev = contents.substr(pos, number_length); + } + + // Print the average and standard deviation. + // Format: __tsw_timings = [512.00, 419.17] + // Where 512.00 = average + // 419.17 = std dev. + printf("__tsw_timings = [%s,%s]\n", average.c_str(), std_dev.c_str()); + } + + protected: + // Opens new tabs. Returns the number of tabs opened. + int OpenTabs() { + // Add tabs. + static const wchar_t* files[] = { L"espn.go.com", L"bugzilla.mozilla.org", + L"news.cnet.com", L"www.amazon.com", + L"kannada.chakradeo.net", L"allegro.pl", + L"ml.wikipedia.org", L"www.bbc.co.uk", + L"126.com", L"www.altavista.com"}; + int number_of_new_tabs_opened = 0; + std::wstring file_name; + for (int i = 0; i < arraysize(files); ++i) { + file_name = path_prefix_; + file_name += files[i]; + file_name += file_util::kPathSeparator; + file_name += L"index.html"; + browser_proxy_->AppendTab(net_util::FilePathToFileURL(file_name)); + number_of_new_tabs_opened++; + } + + return number_of_new_tabs_opened; + } + + std::wstring path_prefix_; + int number_of_tabs_to_open_; + scoped_ptr<BrowserProxy> browser_proxy_; + + private: + DISALLOW_EVIL_CONSTRUCTORS(TabSwitchingUITest); +}; + +} // namespace + +TEST_F(TabSwitchingUITest, GenerateTabSwitchStats) { + RunTabSwitchingUITest(); +} diff --git a/chrome/test/test_file_util.cc b/chrome/test/test_file_util.cc new file mode 100644 index 0000000..55917f2 --- /dev/null +++ b/chrome/test/test_file_util.cc @@ -0,0 +1,124 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <vector> +#include <windows.h> + +#include "chrome/test/test_file_util.h" + +#include "base/file_util.h" +#include "chrome/common/win_util.h" + +namespace file_util { + +bool EvictFileFromSystemCache(const wchar_t* file) { + // Request exclusive access to the file and overwrite it with no buffering. + win_util::ScopedHandle hfile( + CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, + NULL)); + if (!hfile) + return false; + + // Execute in chunks. It could be optimized. We want to do few of these since + // these opterations will be slow without the cache. + char buffer[4096]; + int total_bytes = 0; + DWORD bytes_read; + for (;;) { + bytes_read = 0; + ReadFile(hfile, buffer, sizeof(buffer), &bytes_read, NULL); + if (bytes_read == 0) + break; + + SetFilePointer(hfile, total_bytes, 0, FILE_BEGIN); + if (!WriteFile(hfile, buffer, bytes_read, &bytes_read, NULL)) + return false; + total_bytes += bytes_read; + } + return true; +} + +// Like CopyFileNoCache but recursively copies all files and subdirectories +// in the given input directory to the output directory. +bool CopyRecursiveDirNoCache(const std::wstring& source_dir, + const std::wstring& dest_dir) { + // Try to create the directory if it doesn't already exist. + if (!CreateDirectory(dest_dir)) { + if (GetLastError() != ERROR_ALREADY_EXISTS) + return false; + } + + std::vector<std::wstring> files_copied; + + std::wstring src(source_dir); + file_util::AppendToPath(&src, L"*"); + + WIN32_FIND_DATA fd; + HANDLE fh = FindFirstFile(src.c_str(), &fd); + if (fh == INVALID_HANDLE_VALUE) + return false; + + do { + std::wstring cur_file(fd.cFileName); + if (cur_file == L"." || cur_file == L"..") + continue; // Skip these special entries. + + std::wstring cur_source_path(source_dir); + file_util::AppendToPath(&cur_source_path, cur_file); + + std::wstring cur_dest_path(dest_dir); + file_util::AppendToPath(&cur_dest_path, cur_file); + + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + // Recursively copy a subdirectory. We stripped "." and ".." already. + if (!CopyRecursiveDirNoCache(cur_source_path, cur_dest_path)) { + FindClose(fh); + return false; + } + } else { + // Copy the file. + if (!::CopyFile(cur_source_path.c_str(), cur_dest_path.c_str(), false)) { + FindClose(fh); + return false; + } + + // We don't check for errors from this function, often, we are copying + // files that are in the repository, and they will have read-only set. + // This will prevent us from evicting from the cache, but these don't + // matter anyway. + EvictFileFromSystemCache(cur_dest_path.c_str()); + } + } while (FindNextFile(fh, &fd)); + + FindClose(fh); + return true; +} + +} // namespace file_util diff --git a/chrome/test/test_file_util.h b/chrome/test/test_file_util.h new file mode 100644 index 0000000..dcc7c22 --- /dev/null +++ b/chrome/test/test_file_util.h @@ -0,0 +1,55 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_TEST_FILE_UTIL_H__ +#define CHROME_TEST_TEST_FILE_UTIL_H__ + +// File utility functions used only by tests. + +#include <string> + +namespace file_util { + +// Clear a specific file from the system cache using a neat trick. After this +// call, trying to access this file will result in a cold load from the hard +// drive. +bool EvictFileFromSystemCache(const wchar_t* file); + +// Like CopyFileNoCache but recursively copies all files and subdirectories +// in the given input directory to the output directory. Any files in the +// destination that already exist will be overwritten. +// +// Returns true on success. False means there was some error copying, so the +// state of the destination is unknown. +bool CopyRecursiveDirNoCache(const std::wstring& source_dir, + const std::wstring& dest_dir); + +} // namespace file_util + +#endif // CHROME_TEST_TEST_FILE_UTIL_H__ diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h new file mode 100644 index 0000000..2ccd7e0 --- /dev/null +++ b/chrome/test/testing_browser_process.h @@ -0,0 +1,151 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// An implementation of BrowserProcess for unit tests that fails for most +// services. By preventing creation of services, we reduce dependencies and +// keep the profile clean. Clients of this class must handle the NULL return +// value, however. + +#ifndef CHROME_TEST_TESTING_BROWSER_PROCESS_H__ +#define CHROME_TEST_TESTING_BROWSER_PROCESS_H__ + +#include <string> + +#include "base/string_util.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/notification_service.h" +#include "base/logging.h" + +class TestingBrowserProcess : public BrowserProcess { + public: + TestingBrowserProcess() {} + virtual ~TestingBrowserProcess() { + } + + virtual void EndSession() { + } + + virtual ResourceDispatcherHost* resource_dispatcher_host() { + return NULL; + } + + virtual MetricsService* metrics_service() { + return NULL; + } + + virtual Thread* io_thread() { + return NULL; + } + + virtual Thread* file_thread() { + return NULL; + } + + virtual Thread* db_thread() { + return NULL; + } + + virtual ProfileManager* profile_manager() { + return NULL; + } + + virtual PrefService* local_state() { + return NULL; + } + + virtual WebAppInstallerService* web_app_installer_service() { + return NULL; + } + + virtual IconManager* icon_manager() { + return NULL; + } + + virtual sandbox::BrokerServices* broker_services() { + return NULL; + } + + virtual DebuggerWrapper* debugger_wrapper() { + return NULL; + } + + virtual ClipboardService* clipboard_service() { + return NULL; + } + + virtual GoogleURLTracker* google_url_tracker() { + return NULL; + } + + virtual void InitBrokerServices(sandbox::BrokerServices*) { + } + + virtual AutomationProviderList* InitAutomationProviderList() { + return NULL; + } + + virtual void InitDebuggerWrapper(int port) { + } + + virtual unsigned int AddRefModule() { + return 1; + } + virtual unsigned int ReleaseModule() { + return 1; + } + + virtual bool IsShuttingDown() { + return false; + } + + virtual ChromeViews::AcceleratorHandler* accelerator_handler() { + return NULL; + } + + virtual printing::PrintJobManager* print_job_manager() { + return NULL; + } + + virtual const std::wstring& GetApplicationLocale() { + static std::wstring* value = NULL; + if (!value) + value = new std::wstring(L"en"); + return *value; + } + + virtual MemoryModel memory_model() { return HIGH_MEMORY_MODEL; } + + virtual SuspendController* suspend_controller() { return NULL; } + + private: + NotificationService notification_service_; + DISALLOW_EVIL_CONSTRUCTORS(TestingBrowserProcess); +}; + +#endif // CHROME_TEST_TESTING_BROWSER_PROCESS_H__ diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc new file mode 100644 index 0000000..ac9e9f7 --- /dev/null +++ b/chrome/test/testing_profile.cc @@ -0,0 +1,69 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/testing_profile.h" + +TestingProfile::~TestingProfile() { + DestroyHistoryService(); +} + +void TestingProfile::CreateHistoryService() { + DCHECK(!history_service_.get()); + + PathService::Get(base::DIR_TEMP, &history_dir_); + file_util::AppendToPath(&history_dir_, L"HistoryTest"); + file_util::Delete(history_dir_, true); + file_util::CreateDirectory(history_dir_); + history_service_ = new HistoryService(); + history_service_->Init(history_dir_); +} + +void TestingProfile::DestroyHistoryService() { + if (!history_service_.get()) + return; + + history_service_->NotifyRenderProcessHostDestruction(0); + history_service_->SetOnBackendDestroyTask(new MessageLoop::QuitTask); + history_service_->Cleanup(); + history_service_ = NULL; + + // Wait for the backend class to terminate before deleting the files and + // moving to the next test. Note: if this never terminates, somebody is + // probably leaking a reference to the history backend, so it never calls + // our destroy task. + MessageLoop::current()->Run(); + + // Try to clean up the database file. + file_util::Delete(history_dir_, true); + + // Make sure we don't have any event pending that could disrupt the next + // test. + MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask); + MessageLoop::current()->Run(); +} diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h new file mode 100644 index 0000000..ae6c356 --- /dev/null +++ b/chrome/test/testing_profile.h @@ -0,0 +1,176 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_TESTING_PROFILE_H__ +#define CHROME_TEST_TESTING_PROFILE_H__ + +#include "base/base_paths.h" +#include "base/path_service.h" +#include "base/file_util.h" +#include "chrome/browser/browser_prefs.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/profile.h" +#include "chrome/common/pref_service.h" + +class TestingProfile : public Profile { + public: + TestingProfile() : start_time_(Time::Now()) {} + virtual ~TestingProfile(); + + // Creates the HistoryService. Normally there is no HistoryService. + void CreateHistoryService(); + + virtual std::wstring GetPath() { + return std::wstring(); + } + virtual bool IsOffTheRecord() { + return false; + } + virtual Profile* GetOffTheRecordProfile() { + return NULL; + } + virtual Profile* GetOriginalProfile() { + return this; + } + virtual VisitedLinkMaster* GetVisitedLinkMaster() { + return NULL; + } + virtual HistoryService* GetHistoryService(ServiceAccessType access) { + return history_service_.get(); + } + virtual bool HasHistoryService() const { + return (history_service_.get() != NULL); + } + virtual WebDataService* GetWebDataService(ServiceAccessType access) { + return NULL; + } + virtual PrefService* GetPrefs() { + std::wstring prefs_filename; + PathService::Get(base::DIR_TEMP, &prefs_filename); + file_util::AppendToPath(&prefs_filename, L"TestPreferences"); + if (!prefs_.get()) { + prefs_.reset(new PrefService(prefs_filename)); + Profile::RegisterUserPrefs(prefs_.get()); + browser::RegisterAllPrefs(prefs_.get(), prefs_.get()); + } + return prefs_.get(); + } + virtual TemplateURLModel* GetTemplateURLModel() { + return NULL; + } + virtual TemplateURLFetcher* GetTemplateURLFetcher() { + return NULL; + } + virtual DownloadManager* GetDownloadManager() { + return NULL; + } + virtual bool HasCreatedDownloadManager() const { + return false; + } + virtual URLRequestContext* GetRequestContext() { + return NULL; + } + virtual SessionService* GetSessionService() { + return NULL; + } + virtual void ShutdownSessionService() { + } + virtual bool HasSessionService() const { + return false; + } + virtual std::wstring GetName() { + return std::wstring(); + } + virtual void SetName(const std::wstring& name) { + } + virtual std::wstring GetID() { + return std::wstring(); + } + virtual void SetID(const std::wstring& id) { + } + virtual void RegisterNavigationController( + NavigationController* controller) { + } + virtual void UnregisterNavigationController( + NavigationController* controller) { + } + virtual const ProfileControllerSet& GetNavigationControllers() { + return controllers_; + } + virtual bool DidLastSessionExitCleanly() { + return true; + } + virtual void MergeResourceString(int message_id, + std::wstring* output_string) { + } + virtual void MergeResourceInteger(int message_id, int* output_value) { + } + virtual void MergeResourceBoolean(int message_id, bool* output_value) { + } + virtual bool HasBookmarkBarModel() { + return false; + } + virtual BookmarkBarModel* GetBookmarkBarModel() { + return NULL; + } + virtual bool Profile::IsSameProfile(Profile *p) { + return this == p; + } + virtual Time GetStartTime() const { + return start_time_; + } + virtual TabRestoreService* GetTabRestoreService() { + return NULL; + } + virtual void ResetTabRestoreService() { + } + virtual SpellChecker* GetSpellChecker() { + return NULL; + } + virtual void MarkAsCleanShutdown() { + } + + protected: + Time start_time_; + ProfileControllerSet controllers_; + scoped_ptr<PrefService> prefs_; + + private: + // If the history service has been created, it is destroyed. This is invoked + // from the destructor. + void DestroyHistoryService(); + + // Directory for the history service. + std::wstring history_dir_; + + // The history service. Only created if CreateHistoryService is invoked. + scoped_refptr<HistoryService> history_service_; +}; + +#endif // CHROME_TEST_TESTING_PROFILE_H__ diff --git a/chrome/test/ui/inspector_controller_uitest.cc b/chrome/test/ui/inspector_controller_uitest.cc new file mode 100644 index 0000000..6ca6a91 --- /dev/null +++ b/chrome/test/ui/inspector_controller_uitest.cc @@ -0,0 +1,73 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/command_line.h" +#include "base/no_windows2000_unittest.h" +#include "base/win_util.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "net/url_request/url_request_unittest.h" + +// This test does not work on win2k. See http://b/1070036 +class InspectorControllerTest : public NoWindows2000Test<UITest> { + protected: + TabProxy* GetActiveTabProxy() { + scoped_ptr<BrowserProxy> window_proxy(automation()->GetBrowserWindow(0)); + EXPECT_TRUE(window_proxy.get()); + + int active_tab_index = 0; + EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index)); + return window_proxy->GetTab(active_tab_index); + } + + void NavigateTab(TabProxy* tab_proxy, const GURL& url) { + ASSERT_TRUE(tab_proxy->NavigateToURL(url)); + } +}; + +// This test also does not work in single process. See http://b/1214920 +TEST_F(InspectorControllerTest, InspectElement) { + if (IsTestCaseDisabled()) + return; + + if (CommandLine().HasSwitch(switches::kSingleProcess)) + return; + + TestServer server(L"chrome/test/data"); + ::scoped_ptr<TabProxy> tab(GetActiveTabProxy()); + // We don't track resources until we've opened the inspector. + NavigateTab(tab.get(), server.TestServerPageW(L"files/inspector/test1.html")); + tab->InspectElement(0, 0); + NavigateTab(tab.get(), server.TestServerPageW(L"files/inspector/test1.html")); + EXPECT_EQ(1, tab->InspectElement(0, 0)); + NavigateTab(tab.get(), server.TestServerPageW(L"files/inspector/test2.html")); + EXPECT_EQ(2, tab->InspectElement(0, 0)); +} diff --git a/chrome/test/ui/layout_plugin_uitest.cpp b/chrome/test/ui/layout_plugin_uitest.cpp new file mode 100644 index 0000000..1a3e973 --- /dev/null +++ b/chrome/test/ui/layout_plugin_uitest.cpp @@ -0,0 +1,73 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/ui/ui_test.h" + +#include "base/file_util.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/automation/tab_proxy.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_util.h" + +namespace { + +class LayoutPluginTester : public UITest { +}; + +} // namespace + +// Make sure that navigating away from a plugin referenced by JS doesn't +// crash. +TEST_F(LayoutPluginTester, UnloadNoCrash) { + // We need to copy our test-plugin into the plugins directory so that + // the browser can load it. + std::wstring plugins_directory = browser_directory_ + L"\\plugins"; + std::wstring plugin_src = browser_directory_ + L"\\npapi_layout_test_plugin.dll"; + std::wstring plugin_dest = plugins_directory + L"\\npapi_layout_test_plugin.dll"; + + CreateDirectory(plugins_directory.c_str(), NULL); + CopyFile(plugin_src.c_str(), plugin_dest.c_str(), true /* overwrite */); + + std::wstring path; + PathService::Get(chrome::DIR_TEST_DATA, &path); + file_util::AppendToPath(&path, L"npapi/layout_test_plugin.html"); + NavigateToURL(net_util::FilePathToFileURL(path)); + + std::wstring title; + TabProxy* tab = GetActiveTab(); + ASSERT_TRUE(tab); + EXPECT_TRUE(tab->GetTabTitle(&title)); + EXPECT_EQ(L"Layout Test Plugin Test", title); + + ASSERT_TRUE(tab->GoBack()); + EXPECT_TRUE(tab->GetTabTitle(&title)); + EXPECT_EQ(L"", title); + + delete tab; +} diff --git a/chrome/test/ui/npapi_uitest.cpp b/chrome/test/ui/npapi_uitest.cpp new file mode 100644 index 0000000..cf81db6 --- /dev/null +++ b/chrome/test/ui/npapi_uitest.cpp @@ -0,0 +1,281 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +// NPAPI UnitTests. +// + +// windows headers +#include <windows.h> +#include <shellapi.h> +#include <shlobj.h> +#include <atlbase.h> +#include <comutil.h> + +// runtime headers +#include <stdlib.h> +#include <string.h> +#include <memory.h> + +#include <ostream> + +#include "base/file_util.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "net/base/net_util.h" + +const char kTestCompleteCookie[] = "status"; +const char kTestCompleteSuccess[] = "OK"; +const int kLongWaitTimeout = 30*1000; +const int kShortWaitTimeout = 5*1000; + +std::ostream& operator<<(std::ostream& out, const CComBSTR &str) +{ + // I love strings. I really do. That's why I make sure + // to need 4 different types of strings to stream one out. + TCHAR szFinal[1024]; + _bstr_t bstrIntermediate(str); + _stprintf_s(szFinal, _T("%s"), (LPCTSTR)bstrIntermediate); + return out << szFinal; +} + + +class NPAPITester : public UITest { + protected: + NPAPITester() : UITest() + { + } + + virtual void SetUp() + { + // We need to copy our test-plugin into the plugins directory so that + // the browser can load it. + std::wstring plugins_directory = browser_directory_ + L"\\plugins"; + std::wstring plugin_src = browser_directory_ + L"\\npapi_test_plugin.dll"; + plugin_dll_ = plugins_directory + L"\\npapi_test_plugin.dll"; + + CreateDirectory(plugins_directory.c_str(), NULL); + CopyFile(plugin_src.c_str(), plugin_dll_.c_str(), FALSE); + + UITest::SetUp(); + } + + virtual void TearDown() + { + DeleteFile(plugin_dll_.c_str()); + UITest::TearDown(); + } + +protected: + // Generate the URL for testing a particular test. + // HTML for the tests is all located in test_directory\npapi\<testcase> + GURL GetTestUrl(const std::wstring &test_case) { + std::wstring path; + PathService::Get(chrome::DIR_TEST_DATA, &path); + file_util::AppendToPath(&path, L"npapi"); + file_util::AppendToPath(&path, test_case); + return net_util::FilePathToFileURL(path); + } + + // Waits for the test case to finish. + // ASSERTS if there are test failures. + void WaitForFinish(const std::string &name, const std::string &id, + const GURL &url, const int wait_time) + { + const int kSleepTime = 250; // 4 times per second + const int kMaxIntervals = wait_time / kSleepTime; + + scoped_ptr<TabProxy> tab(GetActiveTab()); + + std::string done_str; + for (int i = 0; i < kMaxIntervals; ++i) { + Sleep(kSleepTime); + + // The webpage being tested has javascript which sets a cookie + // which signals completion of the test. The cookie name is + // a concatenation of the test name and the test id. This allows + // us to run multiple tests within a single webpage and test + // that they all c + std::string cookieName = name; + cookieName.append("."); + cookieName.append(id); + cookieName.append("."); + cookieName.append(kTestCompleteCookie); + tab->GetCookieByName(url, cookieName, &done_str); + if (!done_str.empty()) + break; + } + + EXPECT_EQ(kTestCompleteSuccess, done_str); + } + +private: + std::wstring plugin_dll_; +}; + +class NPAPIVisiblePluginTester : public NPAPITester { + protected: + virtual void SetUp() { + show_window_ = true; + NPAPITester::SetUp(); + } +}; + +// Test passing arguments to a plugin. +TEST_F(NPAPITester, Arguments) { + std::wstring test_case = L"arguments.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("arguments", "1", url, kShortWaitTimeout); +} + + +// Test invoking many plugins within a single page. +TEST_F(NPAPITester, ManyPlugins) { + std::wstring test_case = L"many_plugins.html"; + GURL url(GetTestUrl(test_case)); + NavigateToURL(url); + WaitForFinish("arguments", "1", url, kShortWaitTimeout); + WaitForFinish("arguments", "2", url, kShortWaitTimeout); + WaitForFinish("arguments", "3", url, kShortWaitTimeout); + WaitForFinish("arguments", "4", url, kShortWaitTimeout); + WaitForFinish("arguments", "5", url, kShortWaitTimeout); + WaitForFinish("arguments", "6", url, kShortWaitTimeout); + WaitForFinish("arguments", "7", url, kShortWaitTimeout); + WaitForFinish("arguments", "8", url, kShortWaitTimeout); + WaitForFinish("arguments", "9", url, kShortWaitTimeout); + WaitForFinish("arguments", "10", url, kShortWaitTimeout); + WaitForFinish("arguments", "11", url, kShortWaitTimeout); + WaitForFinish("arguments", "12", url, kShortWaitTimeout); + WaitForFinish("arguments", "13", url, kShortWaitTimeout); + WaitForFinish("arguments", "14", url, kShortWaitTimeout); + WaitForFinish("arguments", "15", url, kShortWaitTimeout); +} + +// Test various calls to GetURL from a plugin. +TEST_F(NPAPITester, GetURL) { + std::wstring test_case = L"geturl.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("geturl", "1", url, kShortWaitTimeout); +} + +// Test various calls to GetURL for javascript URLs with +// non NULL targets from a plugin. +TEST_F(NPAPITester, GetJavaScriptURL) { + std::wstring test_case = L"get_javascript_url.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("getjavascripturl", "1", url, kShortWaitTimeout); +} + + +// Tests that if an NPObject is proxies back to its original process, the +// original pointer is returned and not a proxy. If this fails the plugin +// will crash. +TEST_F(NPAPITester, NPObjectProxy) { + std::wstring test_case = L"npobject_proxy.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("npobject_proxy", "1", url, kShortWaitTimeout); +} + +// Tests if a plugin executing a self deleting script using NPN_GetURL +// works without crashing or hanging +TEST_F(NPAPITester, SelfDeletePluginGetUrl) { + std::wstring test_case = L"self_delete_plugin_geturl.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("self_delete_plugin_geturl", "1", url, kShortWaitTimeout); +} + +// Tests if a plugin executing a self deleting script using Invoke +// works without crashing or hanging +TEST_F(NPAPITester, SelfDeletePluginInvoke) { + std::wstring test_case = L"self_delete_plugin_invoke.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("self_delete_plugin_invoke", "1", url, kShortWaitTimeout); +} + +// Tests if a plugin executing a self deleting script in the context of +// a synchronous paint event works correctly +TEST_F(NPAPIVisiblePluginTester, SelfDeletePluginInvokeInSynchronousPaint) { + if (!UITest::in_process_plugins() && !UITest::in_process_renderer()) { + show_window_ = true; + std::wstring test_case = L"execute_script_delete_in_paint.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("execute_script_delete_in_paint", "1", url, kShortWaitTimeout); + } +} + +TEST_F(NPAPIVisiblePluginTester, SelfDeletePluginInNewStream) { + show_window_ = true; + std::wstring test_case = L"self_delete_plugin_stream.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("self_delete_plugin_stream", "1", url, kShortWaitTimeout); +} + +// Tests if a plugin has a non zero window rect. +TEST_F(NPAPIVisiblePluginTester, VerifyPluginWindowRect) { + show_window_ = true; + std::wstring test_case = L"verify_plugin_window_rect.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("checkwindowrect", "1", url, kShortWaitTimeout); +} + +TEST_F(NPAPIVisiblePluginTester, VerifyNPObjectLifetimeTest) { + if (!UITest::in_process_plugins() && !UITest::in_process_renderer()) { + show_window_ = true; + std::wstring test_case = L"npobject_lifetime_test.html"; + GURL url = GetTestUrl(test_case); + NavigateToURL(url); + WaitForFinish("npobject_lifetime_test", "1", url, kShortWaitTimeout); + } +} + +// Tests that we don't crash or assert if NPP_New fails +TEST_F(NPAPIVisiblePluginTester, NewFails) { + GURL url = GetTestUrl(L"new_fails.html"); + NavigateToURL(url); + WaitForFinish("new_fails", "1", url, kShortWaitTimeout); +} + +TEST_F(NPAPIVisiblePluginTester, SelfDeletePluginInNPNEvaluate) { + if (!UITest::in_process_plugins() && !UITest::in_process_renderer()) { + GURL url = GetTestUrl(L"execute_script_delete_in_npn_evaluate.html"); + NavigateToURL(url); + WaitForFinish("npobject_delete_plugin_in_evaluate", "1", url, + kShortWaitTimeout); + } +}
\ No newline at end of file diff --git a/chrome/test/ui/omnibox_uitest.cc b/chrome/test/ui/omnibox_uitest.cc new file mode 100644 index 0000000..933810e --- /dev/null +++ b/chrome/test/ui/omnibox_uitest.cc @@ -0,0 +1,203 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <stdio.h> + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/perftimer.h" +#include "base/string_util.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/libxml_utils.h" +#include "chrome/test/automation/autocomplete_edit_proxy.h" +#include "chrome/test/automation/automation_proxy.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/ui/ui_test.h" + +const wchar_t kRunOmniboxTest[] = L"run_omnibox_test"; + +class OmniboxTest : public UITest { + public: + + double score_; + double max_score_; + + int query_count_; + int query_timeouts_; + int64 time_squared_; + int64 time_sum_; + int64 time_min_; + int64 time_max_; + + OmniboxTest() : UITest() { + show_window_ = true; + query_count_ = 0; + query_timeouts_ = 0; + score_ = 0; + max_score_ = 0; + time_squared_ = 0; + time_sum_ = 0; + time_min_ = 0; + time_max_ = 0; + } + + // Many times a user may enter something like "google.com". If + // http://www.google.com/ is suggested that should be considered a match. + // This could probably be accomplished with regex as well. Note that this + // method is called even when suggestion isn't a URL. + bool IsMatch(const std::wstring& input_test, const std::wstring& suggestion); + // Runs a query chain. This sends each proper prefix of the input to the + // omnibox and scores the autocompelte results returned. + void RunQueryChain(const std::wstring& input_text); +}; + +bool OmniboxTest::IsMatch(const std::wstring& input_text, + const std::wstring& suggestion) { + // This prefix list comes from the list used in history_url_provider.cc withiff + // the exception of "ftp." and "www.". + std::wstring prefixes[] = {L"", L"ftp://", L"http://", L"https://", + L"ftp.", L"www.", L"ftp://www.", L"ftp://ftp.", + L"http://www.", L"https://www."}; + std::wstring postfixes[] = {L"", L"/"}; + for (int i = 0; i < sizeof(prefixes) / sizeof(std::wstring); ++i) { + for (int j = 0; j < sizeof(postfixes) / sizeof(std::wstring); ++j) { + if (prefixes[i] + input_text + postfixes[j] == suggestion) + return true; + } + } + return false; +} + +void OmniboxTest::RunQueryChain(const std::wstring& input_text) { + // Get a handle on the omnibox and give it focus. + scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + scoped_ptr<WindowProxy> window( + automation()->GetWindowForBrowser(browser.get())); + scoped_ptr<AutocompleteEditProxy> autocomplete_edit( + automation()->GetAutocompleteEditForBrowser(browser.get())); + ASSERT_TRUE(browser->ApplyAccelerator(IDC_FOCUS_LOCATION)); + + // Try every proper prefix of input_text. There's no use trying + // input_text itself since the autocomplete results will always contain it. + for (size_t i = 1; i < input_text.size(); ++i) { + Matches matches; + + // We're only going to count the time elapsed waiting for autocomplete + // matches to be returned to us. + ASSERT_TRUE(autocomplete_edit->SetText(input_text.substr(0, i))); + PerfTimer timer; + if (autocomplete_edit->WaitForQuery(30000)) { + ASSERT_TRUE(autocomplete_edit->GetAutocompleteMatches(&matches)); + int64 time_elapsed = timer.Elapsed().InMilliseconds(); + + // Adjust statistic trackers. + if (query_count_ == 0) + time_min_ = time_max_ = time_elapsed; + ++query_count_; + time_squared_ += time_elapsed * time_elapsed; + time_sum_ += time_elapsed; + if (time_elapsed < time_min_) + time_min_ = time_elapsed; + if (time_elapsed > time_max_) + time_max_ = time_elapsed; + } else { + ++query_timeouts_; + } + wprintf(L"query: %d\n", query_count_); + + // Check if any suggestions match the input text. Stop if a match is + // found. + for (Matches::const_iterator j(matches.begin()); j != matches.end(); ++j) { + if (IsMatch(input_text, j->fill_into_edit)) { + score_ += i; + break; + } + } + max_score_ += i; + } +} + +// This test reads in the omnibox_tests.xml file and performs the tests +// within. The current format of xml is fairly simple. Nothing is currently +// done with the provider information. +// <omnibox_tests> +// Zero or more test elements. +// <test query='%query%'> +// Zero or more provider elements. +// <provider name='%expected_provider_name%'/> +// </test> +// </omnibox_tests> + +TEST_F(OmniboxTest, Measure) { + if (!CommandLine().HasSwitch(kRunOmniboxTest)) return; + + std::wstring omnibox_tests_path; + PathService::Get(chrome::DIR_TEST_DATA, &omnibox_tests_path); + file_util::AppendToPath(&omnibox_tests_path, L"omnibox_tests.xml"); + + XmlReader reader; + ASSERT_TRUE(reader.LoadFile(WideToASCII(omnibox_tests_path))); + while (reader.SkipToElement()) { + ASSERT_EQ("omnibox_tests", reader.NodeName()); + reader.Read(); + while (reader.SkipToElement()) { + ASSERT_EQ("test", reader.NodeName()); + std::string query; + std::vector<std::string> expected_providers; + ASSERT_TRUE(reader.NodeAttribute("query", &query)); + reader.Read(); + while (reader.SkipToElement()) { + ASSERT_EQ("provider", reader.NodeName()); + std::string provider; + ASSERT_TRUE(reader.NodeAttribute("provider", &provider)); + expected_providers.push_back(provider); + reader.Read(); + } + RunQueryChain(ASCIIToWide(query)); + reader.Read(); + } + reader.Read(); + } + + // Output results. + ASSERT_GT(query_count_, 0); + int64 mean = time_sum_ / query_count_; + wprintf(L"__om_query_count = %d\n", query_count_); + wprintf(L"__om_query_timeouts = %d\n", query_timeouts_); + wprintf(L"__om_time_per_query_avg = %d\n", mean); + // Use the equation stddev = sqrt(Sum(x_i^2)/N - mean^2). + wprintf(L"__om_time_per_query_stddev = %d\n", static_cast<int64>( + sqrt(1.0 * time_squared_ / query_count_ - mean * mean))); + wprintf(L"__om_time_per_query_max = %d\n", time_max_); + wprintf(L"__om_time_per_query_min = %d\n", time_min_); + wprintf(L"__om_score = %.4f\n", 100.0 * score_ / max_score_); +} diff --git a/chrome/test/ui/run_all_unittests.cc b/chrome/test/ui/run_all_unittests.cc new file mode 100644 index 0000000..737a7be --- /dev/null +++ b/chrome/test/ui/run_all_unittests.cc @@ -0,0 +1,35 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/ui/ui_test_suite.h" + +int main(int argc, char **argv) { + Thread::SetThreadName("Tests_Main", GetCurrentThreadId()); + return UITestSuite(argc, argv).Run(); +} diff --git a/chrome/test/ui/sandbox_uitests.cc b/chrome/test/ui/sandbox_uitests.cc new file mode 100644 index 0000000..2c30ba8 --- /dev/null +++ b/chrome/test/ui/sandbox_uitests.cc @@ -0,0 +1,51 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <windows.h> +#include <string> + +#include "base/command_line.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/ui/ui_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +class SandboxTest : public UITest { + protected: + // Launches chrome with the --test-sandbox=security_tests.dll flag. + SandboxTest() : UITest() { + CommandLine::AppendSwitchWithValue(&launch_arguments_, + switches::kTestSandbox, + L"security_tests.dll"); + } +}; + +// Verifies that chrome is running properly. +TEST_F(SandboxTest, ExecuteDll) { + EXPECT_EQ(1, GetTabCount()); +} diff --git a/chrome/test/ui/ui_test.cc b/chrome/test/ui/ui_test.cc new file mode 100644 index 0000000..f5ce685 --- /dev/null +++ b/chrome/test/ui/ui_test.cc @@ -0,0 +1,554 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <set> +#include <vector> + +#include "chrome/test/ui/ui_test.h" + +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/process_util.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "base/time.h" +#include "chrome/browser/url_fixer_upper.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_process_filter.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/debug_flags.h" +#include "chrome/common/logging_chrome.h" +#include "chrome/common/json_value_serializer.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/test_file_util.h" + +bool UITest::in_process_renderer_ = false; +bool UITest::in_process_plugins_ = false; +bool UITest::no_sandbox_ = false; +bool UITest::full_memory_dump_ = false; +bool UITest::safe_plugins_ = false; +bool UITest::show_error_dialogs_ = true; +bool UITest::default_use_existing_browser_ = false; +bool UITest::dump_histograms_on_exit_ = false; +bool UITest::enable_dcheck_ = false; +bool UITest::silent_dump_on_dcheck_ = false; +int UITest::timeout_ms_ = 20 * 60 * 1000; + +// Uncomment this line to have the spawned process wait for the debugger to +// attach. +// #define WAIT_FOR_DEBUGGER_ON_OPEN 1 + +// static +bool UITest::DieFileDie(const std::wstring& file, bool recurse) { + if (!file_util::PathExists(file)) + return true; + + // Sometimes Delete fails, so try a few more times. + for (int i = 0; i < 10; ++i) { + if (file_util::Delete(file, recurse)) + return true; + Sleep(kWaitForActionMaxMsec / 10); + } + return false; +} + +UITest::UITest() + : testing::Test(), + expected_errors_(0), + expected_crashes_(0), + wait_for_initial_loads_(true), + homepage_(L"about:blank"), + dom_automation_enabled_(false), + process_(NULL), + show_window_(false), + clear_profile_(true), + include_testing_id_(true), + use_existing_browser_(default_use_existing_browser_) { + PathService::Get(chrome::DIR_APP, &browser_directory_); + PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); + GetSystemTimeAsFileTime(&test_start_time_); +} + +void UITest::SetUp() { + if (!use_existing_browser_) { + AssertAppNotRunning(L"Please close any other instances " + L"of the app before testing."); + } + + LaunchBrowserAndServer(); +} + +void UITest::TearDown() { + CloseBrowserAndServer(); + + // Make sure that we didn't encounter any assertion failures + logging::AssertionList assertions; + logging::GetFatalAssertions(&assertions); + + // If there were errors, get all the error strings for display. + std::wstring failures = + L"The following error(s) occurred in the application during this test:"; + if (static_cast<int>(assertions.size()) > expected_errors_) { + logging::AssertionList::const_iterator iter = assertions.begin(); + for (; iter != assertions.end(); ++iter) { + failures.append(L"\n\n"); + failures.append(*iter); + } + } + EXPECT_EQ(expected_errors_, assertions.size()) << failures; + + // Check for crashes during the test + std::wstring crash_dump_path; + PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path); + // Each crash creates two dump files, so we divide by two here. + int actual_crashes = + file_util::CountFilesCreatedAfter(crash_dump_path, test_start_time_) / 2; + std::wstring error_msg = + L"Encountered an unexpected crash in the program during this test."; + if (expected_crashes_ > 0 && actual_crashes == 0) + error_msg += L" Have you started crash_service.exe?"; + EXPECT_EQ(expected_crashes_, actual_crashes) << error_msg; +} + +void UITest::LaunchBrowserAndServer() { + // Set up IPC testing interface server. + server_.reset(new AutomationProxy); + + LaunchBrowser(launch_arguments_, clear_profile_); + if (wait_for_initial_loads_) + ASSERT_TRUE(server_->WaitForInitialLoads()); + else + Sleep(2000); + + automation()->SetFilteredInet(true); +} + +void UITest::CloseBrowserAndServer() { + QuitBrowser(); + CleanupAppProcesses(); + + // Shut down IPC testing interface. + server_.reset(); +} + +void UITest::LaunchBrowser(const std::wstring& arguments, bool clear_profile) { + std::wstring command_line(browser_directory_); + file_util::AppendToPath(&command_line, + chrome::kBrowserProcessExecutableName); + + // We need cookies on file:// for things like the page cycler. + CommandLine::AppendSwitch(&command_line, switches::kEnableFileCookies); + + if (dom_automation_enabled_) + CommandLine::AppendSwitch(&command_line, + switches::kDomAutomationController); + + if (include_testing_id_) { + if (use_existing_browser_) { + // TODO(erikkay): The new switch depends on a browser instance already + // running, it won't open a new browser window if it's not. We could fix + // this by passing an url (e.g. about:blank) on the command line, but + // I decided to keep using the old switch in the existing use case to + // minimize changes in behavior. + CommandLine::AppendSwitchWithValue(&command_line, + switches::kAutomationClientChannelID, + server_->channel_id()); + } else { + CommandLine::AppendSwitchWithValue(&command_line, + switches::kTestingChannelID, + server_->channel_id()); + } + } + + if (!show_error_dialogs_) + CommandLine::AppendSwitch(&command_line, switches::kNoErrorDialogs); + if (in_process_renderer_) + CommandLine::AppendSwitch(&command_line, switches::kSingleProcess); + if (in_process_plugins_) + CommandLine::AppendSwitch(&command_line, switches::kInProcessPlugins); + if (no_sandbox_) + CommandLine::AppendSwitch(&command_line, switches::kNoSandbox); + if (full_memory_dump_) + CommandLine::AppendSwitch(&command_line, switches::kFullMemoryCrashReport); + if (safe_plugins_) + CommandLine::AppendSwitch(&command_line, switches::kSafePlugins); + if (enable_dcheck_) + CommandLine::AppendSwitch(&command_line, switches::kEnableDCHECK); + if (silent_dump_on_dcheck_) + CommandLine::AppendSwitch(&command_line, switches::kSilentDumpOnDCHECK); + if (!homepage_.empty()) + CommandLine::AppendSwitchWithValue(&command_line, + switches::kHomePage, + homepage_); + PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_); + if (!user_data_dir_.empty()) + CommandLine::AppendSwitchWithValue(&command_line, + switches::kUserDataDir, + user_data_dir_); + + CommandLine::AppendSwitch(&command_line, switches::kDisableMetricsReporting); + + // We always want to enable chrome logging + CommandLine::AppendSwitch(&command_line, switches::kEnableLogging); + + if (dump_histograms_on_exit_) + CommandLine::AppendSwitch(&command_line, switches::kDumpHistogramsOnExit); + +#ifdef WAIT_FOR_DEBUGGER_ON_OPEN + CommandLine::AppendSwitch(&command_line, switches::kDebugOnStart); +#endif + + DebugFlags::ProcessDebugFlags(&command_line, DebugFlags::UNKNOWN, false); + command_line.append(L" " + arguments); + + // Clear user data directory to make sure test environment is consistent + // We balk on really short (absolute) user_data_dir directory names, because + // we're worried that they'd accidentally be root or something. + ASSERT_LT(10, static_cast<int>(user_data_dir_.size())) << + "The user data directory name passed into this test was too " + "short to delete safely. Please check the user-data-dir " + "argument and try again."; + if (clear_profile) + ASSERT_TRUE(DieFileDie(user_data_dir_, true)); + + if (!template_user_data_.empty()) { + // Recursively copy the template directory to the user_data_dir. + ASSERT_TRUE(file_util::CopyRecursiveDirNoCache(template_user_data_, + user_data_dir_)); + } + + browser_launch_time_ = TimeTicks::Now(); + + bool started = process_util::LaunchApp( + command_line, + false, // Don't wait for process object (doesn't work for + // us) + !show_window_, + &process_); + ASSERT_EQ(started, true); + + if (use_existing_browser_) { + DWORD pid = 0; + HWND hwnd = FindWindowEx(HWND_MESSAGE, NULL, chrome::kMessageWindowClass, + user_data_dir_.c_str()); + GetWindowThreadProcessId(hwnd, &pid); + // This mode doesn't work if we wound up launching a new browser ourselves. + ASSERT_NE(pid, process_util::GetProcId(process_)); + CloseHandle(process_); + process_ = OpenProcess(SYNCHRONIZE, false, pid); + } +} + +void UITest::QuitBrowser() { + typedef std::vector<HWND> HandleVector; + + // There's nothing to do here if the browser is not running. + if (IsBrowserRunning()) { + automation()->SetFilteredInet(false); + HandleVector handles; + + // Build up a list of HWNDs; we do this as a separate step so that closing + // the windows doesn't mess up the iteration. + int window_count = 0; + EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); + + for (int i = 0; i < window_count; ++i) { + HWND window_handle; + scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(i)); + scoped_ptr<WindowProxy> window( + automation()->GetWindowForBrowser(browser.get())); + EXPECT_TRUE(window->GetHWND(&window_handle)); + handles.push_back(window_handle); + } + + for (HandleVector::iterator iter = handles.begin(); iter != handles.end(); + ++iter) { + ::PostMessage(*iter, WM_CLOSE, 0, 0); + } + + // Wait for the browser process to quit. It should quit once all tabs have + // been closed. + int timeout = 5000; +#ifdef WAIT_FOR_DEBUGGER_ON_OPEN + timeout = 500000; +#endif + if (WAIT_TIMEOUT == WaitForSingleObject(process_, timeout)) { + // We need to force the browser to quit because it didn't quit fast + // enough. Take no chance and kill every chrome processes. + CleanupAppProcesses(); + } + } + + // Don't forget to close the handle + CloseHandle(process_); + process_ = NULL; +} + +void UITest::AssertAppNotRunning(const std::wstring& error_message) { + ASSERT_EQ(0, GetBrowserProcessCount()) << error_message; +} + +void UITest::CleanupAppProcesses() { + BrowserProcessFilter filter; + + // Make sure that no instances of the browser remain. + const int kExitTimeoutMs = 5000; + const int kExitCode = 1; + process_util::CleanupProcesses( + chrome::kBrowserProcessExecutableName, kExitTimeoutMs, kExitCode, + &filter); + + // Suppress spammy failures that seem to be occurring when running + // the UI tests in single-process mode. + // TODO(jhughes): figure out why this is necessary at all, and fix it + if (!in_process_renderer_) { + AssertAppNotRunning(L"Unable to quit all browser processes."); + } +} + +TabProxy* UITest::GetActiveTab() { + scoped_ptr<BrowserProxy> window_proxy(automation()->GetBrowserWindow(0)); + if (!window_proxy.get()) + return NULL; + + int active_tab_index = -1; + EXPECT_TRUE(window_proxy->GetActiveTabIndex(&active_tab_index)); + if (active_tab_index == -1) + return NULL; + + return window_proxy->GetTab(active_tab_index); +} + +void UITest::NavigateToURL(const GURL& url) { + scoped_ptr<TabProxy> tab_proxy(GetActiveTab()); + ASSERT_TRUE(tab_proxy.get()); + if (!tab_proxy.get()) + return; + + bool is_timeout = true; + ASSERT_TRUE(tab_proxy->NavigateToURLWithTimeout(url, kMaxTestExecutionTime, + &is_timeout)) << url.spec(); + ASSERT_FALSE(is_timeout) << url.spec(); +} + +bool UITest::WaitForDownloadShelfVisible(TabProxy* tab) { + const int kCycles = 20; + for (int i = 0; i < kCycles; i++) { + bool visible = false; + if (!tab->IsShelfVisible(&visible)) + return false; // Some error. + if (visible) + return true; // Got the download shelf. + + // Give it a chance to catch up. + Sleep(kWaitForActionMaxMsec / kCycles); + } + return false; +} + +GURL UITest::GetActiveTabURL() { + scoped_ptr<TabProxy> tab_proxy(GetActiveTab()); + if (!tab_proxy.get()) + return GURL(); + + GURL url; + if (!tab_proxy->GetCurrentURL(&url)) + return GURL(); + return url; +} + +std::wstring UITest::GetActiveTabTitle() { + std::wstring title; + scoped_ptr<TabProxy> tab_proxy(GetActiveTab()); + if (!tab_proxy.get()) + return title; + + EXPECT_TRUE(tab_proxy->GetTabTitle(&title)); + return title; +} + +bool UITest::IsBrowserRunning() { + return CrashAwareSleep(0); +} + +bool UITest::CrashAwareSleep(int time_out_ms) { + return WAIT_TIMEOUT == WaitForSingleObject(process_, time_out_ms); +} + +/*static*/ +int UITest::GetBrowserProcessCount() { + BrowserProcessFilter filter; + return process_util::GetProcessCount(chrome::kBrowserProcessExecutableName, + &filter); +} + +static DictionaryValue* LoadDictionaryValueFromPath(const std::wstring& path) { + if (path.empty()) + return NULL; + + JSONFileValueSerializer serializer(path); + Value* root_value = NULL; + if (serializer.Deserialize(&root_value) && + root_value->GetType() != Value::TYPE_DICTIONARY) { + delete root_value; + return NULL; + } + return static_cast<DictionaryValue*>(root_value); +} + +DictionaryValue* UITest::GetLocalState() { + std::wstring local_state_path; + PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); + return LoadDictionaryValueFromPath(local_state_path); +} + +DictionaryValue* UITest::GetDefaultProfilePreferences() { + std::wstring path; + PathService::Get(chrome::DIR_USER_DATA, &path); + file_util::AppendToPath(&path, chrome::kNotSignedInProfile); + file_util::AppendToPath(&path, chrome::kPreferencesFilename); + return LoadDictionaryValueFromPath(path); +} + +int UITest::GetTabCount() { + scoped_ptr<BrowserProxy> first_window(automation()->GetBrowserWindow(0)); + if (!first_window.get()) + return 0; + + int result = 0; + EXPECT_TRUE(first_window->GetTabCount(&result)); + + return result; +} + +bool UITest::WaitUntilCookieValue(TabProxy* tab, + const GURL& url, + const char* cookie_name, + int interval_ms, + int time_out_ms, + const char* expected_value) { + const int kMaxIntervals = time_out_ms / interval_ms; + + std::string cookie_value; + bool completed = false; + for (int i = 0; i < kMaxIntervals; ++i) { + bool browser_survived = CrashAwareSleep(interval_ms); + + tab->GetCookieByName(url, cookie_name, &cookie_value); + + if (cookie_value == expected_value) { + completed = true; + break; + } + EXPECT_TRUE(browser_survived); + if (!browser_survived) { + // The browser process died. + break; + } + } + return completed; +} + +std::string UITest::WaitUntilCookieNonEmpty(TabProxy* tab, + const GURL& url, + const char* cookie_name, + int interval_ms, + int time_out_ms) { + const int kMaxIntervals = time_out_ms / interval_ms; + + std::string cookie_value; + for (int i = 0; i < kMaxIntervals; ++i) { + bool browser_survived = CrashAwareSleep(interval_ms); + + tab->GetCookieByName(url, cookie_name, &cookie_value); + + if (!cookie_value.empty()) + break; + + EXPECT_TRUE(browser_survived); + if (!browser_survived) { + // The browser process died. + break; + } + } + + return cookie_value; +} + +void UITest::WaitUntilTabCount(int tab_count) { + for (int i = 0; i < 10; ++i) { + Sleep(kWaitForActionMaxMsec / 10); + if (GetTabCount() == tab_count) + break; + } + EXPECT_EQ(tab_count, GetTabCount()); +} + +std::wstring UITest::GetDownloadDirectory() { + scoped_ptr<TabProxy> tab_proxy(GetActiveTab()); + if (!tab_proxy.get()) + return false; + + std::wstring download_directory; + EXPECT_TRUE(tab_proxy->GetDownloadDirectory(&download_directory)); + return download_directory; +} + +bool UITest::CloseBrowser(BrowserProxy* browser, + bool* application_closed) const { + DCHECK(application_closed); + if (!browser->is_valid() || !browser->handle()) + return false; + + IPC::Message* response = NULL; + bool succeeded = server_->SendAndWaitForResponse( + new AutomationMsg_CloseBrowserRequest(0, browser->handle()), + &response, AutomationMsg_CloseBrowserResponse__ID); + + if (!succeeded) + return false; + + void* iter = NULL; + bool result = true; + response->ReadBool(&iter, &result); + response->ReadBool(&iter, application_closed); + + if (*application_closed) { + // Let's wait until the process dies (if it is not gone already). + int r = WaitForSingleObject(process_, INFINITE); + DCHECK(r != WAIT_FAILED); + } + + delete response; + return result; +} diff --git a/chrome/test/ui/ui_test.h b/chrome/test/ui/ui_test.h new file mode 100644 index 0000000..daaff3d --- /dev/null +++ b/chrome/test/ui/ui_test.h @@ -0,0 +1,344 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_UI_UI_TEST_H__ +#define CHROME_TEST_UI_UI_TEST_H__ + +// This file provides a common base for running UI unit tests, which operate +// the entire browser application in a separate process for holistic +// functional testing. +// +// Tests should #include this file, subclass UITest, and use the TEST_F macro +// to declare individual test cases. This provides a running browser window +// during the test, accessible through the window_ member variable. The window +// will close when the test ends, regardless of whether the test passed. +// +// Tests which need to launch the browser with a particular set of command-line +// arguments should set the value of launch_arguments_ in their constructors. + +#include <windows.h> +#include <string> + +#include "base/path_service.h" +#include "base/scoped_ptr.h" +#include "base/time.h" +#include "chrome/test/automation/automation_proxy.h" +#include "googleurl/src/gurl.h" +#include "testing/gtest/include/gtest/gtest.h" + +class DictionaryValue; +class TabProxy; + +class UITest : public testing::Test { + protected: + // Delay to let browser complete a requested action. + static const int kWaitForActionMsec = 2000; + static const int kWaitForActionMaxMsec = 10000; + // Delay to let the browser complete the test. + static const int kMaxTestExecutionTime = 30000; + + // Tries to delete the specified file/directory returning true on success. + // This differs from file_util::Delete in that it repeatedly invokes Delete + // until successful, or a timeout is reached. Returns true on success. + static bool DieFileDie(const std::wstring& file, bool recurse); + + // Constructor + UITest(); + + // Starts the browser using the arguments in launch_arguments_, and + // sets up member variables. + virtual void SetUp(); + + // Closes the browser window. + virtual void TearDown(); + + // ********* Utility functions ********* + + // Launches the browser and IPC testing server. + void LaunchBrowserAndServer(); + + // Closes the browser and IPC testing server. + void CloseBrowserAndServer(); + + // Launches the browser with the given arguments. + void LaunchBrowser(const std::wstring& arguments, bool clear_profile); + + // Exits out browser instance. + void QuitBrowser(); + + // Tells the browser to navigate to the given URL in the active tab + // of the first app window. + // This method doesn't return until the navigation is complete. + void NavigateToURL(const GURL& url); + + // Returns the URL of the currently active tab. If there is no active tab, + // or some other error, the returned URL will be empty. + GURL GetActiveTabURL(); + + // Returns the title of the currently active tab. + std::wstring GetActiveTabTitle(); + + // Returns true when the browser process is running, independent if any + // renderer process exists or not. It will returns false if an user closed the + // window or if the browser process died by itself. + bool IsBrowserRunning(); + + // Returns true when time_out_ms milliseconds have elapsed. + // Returns false if the browser process died while waiting. + bool CrashAwareSleep(int time_out_ms); + + // Returns the number of tabs in the first window. If no windows exist, + // causes a test failure and returns 0. + int GetTabCount(); + + // Polls the tab for the cookie_name cookie and returns once one of the + // following conditions hold true: + // - The cookie is of expected_value. + // - The browser process died. + // - The time_out value has been exceeded. + bool WaitUntilCookieValue(TabProxy* tab, const GURL& url, + const char* cookie_name, + int interval_ms, + int time_out_ms, + const char* expected_value); + // Polls the tab for the cookie_name cookie and returns once one of the + // following conditions hold true: + // - The cookie is set to any value. + // - The browser process died. + // - The time_out value has been exceeded. + std::string WaitUntilCookieNonEmpty(TabProxy* tab, + const GURL& url, + const char* cookie_name, + int interval_ms, + int time_out_ms); + + // Polls up to kWaitForActionMaxMsec ms to attain a specific tab count. Will + // assert that the tab count is valid at the end of the wait. + void WaitUntilTabCount(int tab_count); + + // Checks whether the download shelf is visible in the current tab, giving it + // a chance to appear (we don't know the exact timing) while finishing as soon + // as possible. + bool WaitForDownloadShelfVisible(TabProxy* tab); + + // Closes the specified browser. Returns true if the browser was closed. + // This call is blocking. |application_closed| is set to true if this was + // the last browser window (and therefore as a result of it closing the + // browser process terminated). Note that in that case this method returns + // after the browser process has terminated. + bool CloseBrowser(BrowserProxy* browser, bool* application_closed) const; + + // Gets the directory for the currently active profile in the browser. + std::wstring GetDownloadDirectory(); + + // Get the handle of browser process connected to the automation. This + // function only retruns a reference to the handle so the caller does not + // own the handle returned. + HANDLE process() { return process_; } + + public: + // Get/Set a flag to run the renderer in process when running the + // tests. + static bool in_process_renderer() { return in_process_renderer_; } + static void set_in_process_renderer(bool value) { + in_process_renderer_ = value; + } + + // Get/Set a flag to run the plugins in the renderer process when running the + // tests. + static bool in_process_plugins() { return in_process_plugins_; } + static void set_in_process_plugins(bool value) { + in_process_plugins_ = value; + } + + // Get/Set a flag to run the renderer outside the sandbox when running the + // tests + static bool no_sandbox() { return no_sandbox_; } + static void set_no_sandbox(bool value) { + no_sandbox_ = value; + } + + // Get/Set a flag to run with DCHECKs enabled in release. + static bool enable_dcheck() { return enable_dcheck_; } + static void set_enable_dcheck(bool value) { + enable_dcheck_ = value; + } + + // Get/Set a flag to dump the process memory without crashing on DCHECKs. + static bool silent_dump_on_dcheck() { return silent_dump_on_dcheck_; } + static void set_silent_dump_on_dcheck(bool value) { + silent_dump_on_dcheck_ = value; + } + + // Get/Set a flag to run the plugin processes inside the sandbox when running + // the tests + static bool safe_plugins() { return safe_plugins_; } + static void set_safe_plugins(bool value) { + safe_plugins_ = value; + } + + static bool show_error_dialogs() { return show_error_dialogs_; } + static void set_show_error_dialogs(bool value) { + show_error_dialogs_ = value; + } + + static bool full_memory_dump() { return full_memory_dump_; } + static void set_full_memory_dump(bool value) { + full_memory_dump_ = value; + } + + static bool use_existing_browser() { return default_use_existing_browser_; } + static void set_use_existing_browser(bool value) { + default_use_existing_browser_ = value; + } + + static bool dump_histograms_on_exit() { return dump_histograms_on_exit_; } + static void set_dump_histograms_on_exit(bool value) { + dump_histograms_on_exit_ = value; + } + + static int test_timeout_ms() { return timeout_ms_; } + static void set_test_timeout_ms(int value) { + timeout_ms_ = value; + } + + // Called by some tests that wish to have a base profile to start from. This + // "user data directory" (containing one or more profiles) will be recursively + // copied into the user data directory for the test and the files will be + // evicted from the OS cache. To start with a blank profile, supply an empty + // string (the default). + std::wstring template_user_data() const { return template_user_data_; } + void set_template_user_data(const std::wstring& template_user_data) { + template_user_data_ = template_user_data; + } + + // Return the user data directory being used by the browser instance in + // UITest::SetUp(). + std::wstring user_data_dir() const { return user_data_dir_; } + + // Count the number of active browser processes. This function only counts + // browser processes that share the same profile directory as the current + // process. The count includes browser sub-processes. + static int GetBrowserProcessCount(); + + // Returns a copy of local state preferences. The caller is responsible for + // deleting the returned object. Returns NULL if there is an error. + DictionaryValue* GetLocalState(); + + // Returns a copy of the default profile preferences. The caller is + // responsible for deleting the returned object. Returns NULL if there is an + // error. + DictionaryValue* GetDefaultProfilePreferences(); + + private: + // Check that no processes related to Chrome exist, displaying + // the given message if any do. + void AssertAppNotRunning(const std::wstring& error_message); + + protected: + AutomationProxy* automation() { + EXPECT_TRUE(server_.get()); + return server_.get(); + } + + // Wait a certain amount of time for all the app processes to exit, + // forcibly killing them if they haven't exited by then. + // It has the side-effect of killing every browser window opened in your + // session, even those unrelated in the test. + void CleanupAppProcesses(); + + // Returns the proxy for the currently active tab, or NULL if there is no + // tab or there was some kind of error. The returned pointer MUST be + // deleted by the caller if non-NULL. + TabProxy* GetActiveTab(); + + // ********* Member variables ********* + + std::wstring browser_directory_; // Path to the browser executable, + // with no trailing slash + std::wstring test_data_directory_; // Path to the unit test data, + // with no trailing slash + std::wstring launch_arguments_; // Arguments to the browser on launch. + int expected_errors_; // The number of errors expected during + // the run (generally 0). + int expected_crashes_; // The number of crashes expected during + // the run (generally 0). + std::wstring homepage_; // Homepage used for testing. + bool wait_for_initial_loads_; // Wait for initial loads to complete + // in SetUp() before running test body. + TimeTicks browser_launch_time_; // Time when the browser was run. + bool dom_automation_enabled_; // This can be set to true to have the + // test run the dom automation case. + std::wstring template_user_data_; // See set_template_user_data(). + HANDLE process_; // Handle the the first Chrome process. + std::wstring user_data_dir_; // User data directory used for the test + static bool in_process_renderer_; // true if we're in single process mode + bool show_window_; // Determines if the window is shown or + // hidden. Defaults to hidden. + bool clear_profile_; // If true the profile is cleared before + // launching. Default is true. + bool include_testing_id_; // Should we supply the testing channel + // id on the command line? Default is + // true. + bool use_existing_browser_; // Duplicate of the static version. + // Default value comes from static. + + private: + FILETIME test_start_time_; // Time the test was started + // (so we can check for new crash dumps) + static bool in_process_plugins_; + static bool no_sandbox_; + static bool safe_plugins_; + static bool full_memory_dump_; // If true, write full memory dump + // during crash. + static bool show_error_dialogs_; // If true, a user is paying attention + // to the test, so show error dialogs. + static bool default_use_existing_browser_; // The test connects to an already + // running browser instance. + static bool dump_histograms_on_exit_; // Include histograms in log on exit. + static bool enable_dcheck_; // Enable dchecks in release mode. + static bool silent_dump_on_dcheck_; // Dump process memory on dcheck without + // crashing. + static int timeout_ms_; // Timeout in milliseconds to wait + // for an test to finish. + ::scoped_ptr<AutomationProxy> server_; +}; + +// These exist only to support the gTest assertion macros, and +// shouldn't be used in normal program code. +#ifdef UNIT_TEST +std::ostream& operator<<(std::ostream& out, const std::wstring& wstr); + +template<typename T> +std::ostream& operator<<(std::ostream& out, const ::scoped_ptr<T>& ptr) { + return out << ptr.get(); +} +#endif // UNIT_TEST + +#endif // CHROME_TEST_UI_UI_TEST_H__ diff --git a/chrome/test/ui/ui_test_suite.cc b/chrome/test/ui/ui_test_suite.cc new file mode 100644 index 0000000..408330a --- /dev/null +++ b/chrome/test/ui/ui_test_suite.cc @@ -0,0 +1,36 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/ui/ui_test_suite.h" + +// Force a test to use an already running browser instance. UI tests only. +const wchar_t UITestSuite::kUseExistingBrowser[] = L"use-existing-browser"; + +// Timeout for the test in milliseconds. UI tests only. +const wchar_t UITestSuite::kTestTimeout[] = L"test-timeout"; diff --git a/chrome/test/ui/ui_test_suite.h b/chrome/test/ui/ui_test_suite.h new file mode 100644 index 0000000..7631def --- /dev/null +++ b/chrome/test/ui/ui_test_suite.h @@ -0,0 +1,81 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_UI_UI_TEST_SUITE_H_ +#define CHROME_TEST_UI_UI_TEST_SUITE_H_ + +#include "chrome/test/ui/ui_test.h" +#include "chrome/test/unit/chrome_test_suite.h" + +class UITestSuite : public ChromeTestSuite { + public: + UITestSuite(int argc, char** argv) : ChromeTestSuite(argc, argv) { + } + + protected: + + virtual void Initialize() { + ChromeTestSuite::Initialize(); + + UITest::set_in_process_renderer( + parsed_command_line_.HasSwitch(switches::kSingleProcess)); + UITest::set_in_process_plugins( + parsed_command_line_.HasSwitch(switches::kInProcessPlugins)); + UITest::set_no_sandbox( + parsed_command_line_.HasSwitch(switches::kNoSandbox)); + UITest::set_full_memory_dump( + parsed_command_line_.HasSwitch(switches::kFullMemoryCrashReport)); + UITest::set_safe_plugins( + parsed_command_line_.HasSwitch(switches::kSafePlugins)); + UITest::set_use_existing_browser( + parsed_command_line_.HasSwitch(UITestSuite::kUseExistingBrowser)); + UITest::set_dump_histograms_on_exit( + parsed_command_line_.HasSwitch(switches::kDumpHistogramsOnExit)); + UITest::set_enable_dcheck( + parsed_command_line_.HasSwitch(switches::kEnableDCHECK)); + UITest::set_silent_dump_on_dcheck( + parsed_command_line_.HasSwitch(switches::kSilentDumpOnDCHECK)); + std::wstring test_timeout = + parsed_command_line_.GetSwitchValue(UITestSuite::kTestTimeout); + if (!test_timeout.empty()) { + UITest::set_test_timeout_ms(_wtoi(test_timeout.c_str())); + } + } + + virtual void SuppressErrorDialogs() { + TestSuite::SuppressErrorDialogs(); + UITest::set_show_error_dialogs(false); + } + + private: + static const wchar_t kUseExistingBrowser[]; + static const wchar_t kTestTimeout[]; +}; + +#endif // CHROME_TEST_UI_UI_TEST_SUITE_H_ diff --git a/chrome/test/ui/ui_tests.vcproj b/chrome/test/ui/ui_tests.vcproj new file mode 100644 index 0000000..4c9ffac --- /dev/null +++ b/chrome/test/ui/ui_tests.vcproj @@ -0,0 +1,528 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="ui_tests" + ProjectGUID="{76235B67-1C27-4627-8A33-4B2E1EF93EDE}" + RootNamespace="ui_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)\tools\build\win\js_engine.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(OutDir)\obj\generated_resources"" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\libxslt\build\using_libxslt.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)\tools\build\win\js_engine.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(OutDir)\obj\generated_resources"" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath=".\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\test_file_util.cc" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath=".\ui_test.cc" + > + </File> + <File + RelativePath=".\ui_test.h" + > + </File> + <File + RelativePath=".\ui_test_suite.cc" + > + </File> + <File + RelativePath=".\ui_test_suite.h" + > + </File> + <File + RelativePath="..\..\..\net\url_request\url_request_test_job.cc" + > + </File> + <File + RelativePath="..\..\..\net\url_request\url_request_test_job.h" + > + </File> + </Filter> + <Filter + Name="TestChromeMain" + > + <File + RelativePath="..\..\app\chrome_main_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestErrorPage" + > + <File + RelativePath="..\..\browser\errorpage_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestBrowser" + > + <File + RelativePath="..\..\browser\browser_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestChromeLogging" + > + <File + RelativePath="..\..\common\logging_chrome_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestDownload" + > + <File + RelativePath="..\..\browser\download_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestImages" + > + <File + RelativePath="..\..\browser\images_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestIFrame" + > + <File + RelativePath="..\..\browser\iframe_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestCache" + > + <File + RelativePath="..\..\common\net\cache_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestSanity" + > + <File + RelativePath="..\..\browser\sanity_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestAutomationProxy" + > + <File + RelativePath="..\automation\automation_proxy_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestNPAPI" + > + <File + RelativePath=".\layout_plugin_uitest.cpp" + > + </File> + <File + RelativePath=".\npapi_uitest.cpp" + > + </File> + </Filter> + <Filter + Name="TestSessionHistory" + > + <File + RelativePath="..\..\browser\session_history_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestSessionRestore" + > + <File + RelativePath="..\..\browser\session_restore_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestTabRestore" + > + <File + RelativePath="..\..\browser\tab_restore_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestAuthentication" + > + <File + RelativePath="..\..\browser\login_prompt_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestPreferences" + > + <File + RelativePath="..\..\common\pref_service_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestViewSource" + > + <File + RelativePath="..\..\browser\view_source_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestRedirects" + > + <File + RelativePath="..\..\browser\history\redirect_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestResourceDispatcherHost" + > + <File + RelativePath="..\..\browser\resource_dispatcher_host_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestFindInPage" + > + <File + RelativePath="..\..\browser\find_in_page_controller_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestPageLoader" + > + <File + RelativePath="..\perf\mem_usage.cc" + > + </File> + <File + RelativePath="..\perf\mem_usage.h" + > + </File> + <File + RelativePath="..\reliability\page_load_test.cc" + > + </File> + <File + RelativePath="..\reliability\page_load_test.h" + > + </File> + </Filter> + <Filter + Name="TestSandbox" + > + <File + RelativePath=".\sandbox_uitests.cc" + > + </File> + </Filter> + <Filter + Name="TestInspector" + > + <File + RelativePath=".\inspector_controller_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestLocalizedBuilds" + > + <File + RelativePath="..\..\browser\locale_tests_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestMetricsService" + > + <File + RelativePath="..\..\browser\metrics_service_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestInterstitialPage" + > + <File + RelativePath="..\..\browser\interstitial_page_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestSSL" + > + <File + RelativePath="..\..\browser\ssl_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestAccessibility" + > + <File + RelativePath="..\accessibility\accessibility_tests.cc" + > + </File> + <Filter + Name="Accessibility Client" + > + <File + RelativePath="..\accessibility\accessibility_util.cc" + > + </File> + <File + RelativePath="..\accessibility\accessibility_util.h" + > + </File> + <File + RelativePath="..\accessibility\browser_impl.cc" + > + </File> + <File + RelativePath="..\accessibility\browser_impl.h" + > + </File> + <File + RelativePath="..\accessibility\constants.h" + > + </File> + <File + RelativePath="..\accessibility\keyboard_util.cc" + > + </File> + <File + RelativePath="..\accessibility\keyboard_util.h" + > + </File> + <File + RelativePath="..\accessibility\registry_util.cc" + > + </File> + <File + RelativePath="..\accessibility\registry_util.h" + > + </File> + <File + RelativePath="..\accessibility\tab_impl.cc" + > + </File> + <File + RelativePath="..\accessibility\tab_impl.h" + > + </File> + </Filter> + </Filter> + <Filter + Name="TestCrashRecovery" + > + <File + RelativePath="..\..\browser\crash_recovery_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestPrinting" + > + <File + RelativePath="..\..\browser\printing\printing_layout_uitest.cc" + > + </File> + <File + RelativePath="..\..\browser\printing\printing_test.h" + > + </File> + </Filter> + <Filter + Name="TestSavePage" + > + <File + RelativePath="..\..\browser\save_page_uitest.cc" + > + </File> + </Filter> + <Filter + Name="TestOmnibox" + > + <File + RelativePath=".\omnibox_uitest.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/unit/chrome_test_suite.h b/chrome/test/unit/chrome_test_suite.h new file mode 100644 index 0000000..1c659f8 --- /dev/null +++ b/chrome/test/unit/chrome_test_suite.h @@ -0,0 +1,90 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_UNIT_CHROME_TEST_SUITE_H_ +#define CHROME_TEST_UNIT_CHROME_TEST_SUITE_H_ + +#include "base/stats_table.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/test_suite.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/resource_bundle.h" +#include "chrome/test/testing_browser_process.h" + +class ChromeTestSuite : public TestSuite { +public: + ChromeTestSuite(int argc, char** argv) : TestSuite(argc, argv) { + } + + virtual ~ChromeTestSuite() { + ResourceBundle::CleanupSharedInstance(); + + delete g_browser_process; + g_browser_process = NULL; + + // Tear down shared StatsTable; prevents unit_tests from leaking it. + StatsTable::set_current(NULL); + delete stats_table_; + } + +protected: + + virtual void Initialize() { + TestSuite::Initialize(); + + chrome::RegisterPathProvider(); + g_browser_process = new TestingBrowserProcess; + + // Notice a user data override, and otherwise default to using a custom + // user data directory that lives alongside the current app. + // NOTE: The user data directory will be erased before each UI test that + // uses it, in order to ensure consistency. + std::wstring user_data_dir = + parsed_command_line_.GetSwitchValue(switches::kUserDataDir); + if (user_data_dir.empty() && + PathService::Get(base::DIR_EXE, &user_data_dir)) + file_util::AppendToPath(&user_data_dir, L"test_user_data"); + if (!user_data_dir.empty()) + PathService::Override(chrome::DIR_USER_DATA, user_data_dir); + + ResourceBundle::InitSharedInstance(std::wstring()); + ResourceBundle::GetSharedInstance().LoadThemeResources(); + + // initialize the global StatsTable for unit_tests + stats_table_ = new StatsTable(L"unit_tests", 20, 200); + StatsTable::set_current(stats_table_); + } + + StatsTable* stats_table_; +}; + +#endif // CHROME_TEST_UNIT_CHROME_TEST_SUITE_H_
\ No newline at end of file diff --git a/chrome/test/unit/run_all_unittests.cc b/chrome/test/unit/run_all_unittests.cc new file mode 100644 index 0000000..f8d6fea --- /dev/null +++ b/chrome/test/unit/run_all_unittests.cc @@ -0,0 +1,34 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/unit/chrome_test_suite.h" + +int main(int argc, char **argv) { + return ChromeTestSuite(argc, argv).Run(); +} diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj new file mode 100644 index 0000000..dfea76e --- /dev/null +++ b/chrome/test/unit/unittests.vcproj @@ -0,0 +1,924 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="unit_tests" + ProjectGUID="{ECFC2BEC-9FC0-4AD9-9649-5F26793F65FC}" + RootNamespace="unit_tests" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;..\..\..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops;..\..\third_party\hunspell\using_hunspell.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + AdditionalIncludeDirectories="$(SolutionDir)..;"$(IntDir)";"$(IntDir)";"$(SolutionDir)";"$(IntDir)\..\"" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;..\..\..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops;..\..\third_party\hunspell\using_hunspell.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + AdditionalIncludeDirectories="$(SolutionDir)..;"$(IntDir)";"$(IntDir)";"$(SolutionDir)";"$(IntDir)\..\"" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winmm.lib" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + > + <File + RelativePath="..\..\browser\browser_resources.h" + > + </File> + <File + RelativePath="..\..\browser\browser_resources.rc" + > + </File> + <File + RelativePath=".\chrome_test_suite.h" + > + </File> + <File + RelativePath=".\multiprocess_test.h" + > + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.cc" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tools\build\win\precompiled_wtl.h" + > + </File> + <File + RelativePath=".\run_all_unittests.cc" + > + </File> + <File + RelativePath="..\testing_browser_process.h" + > + </File> + <File + RelativePath="..\testing_profile.cc" + > + </File> + <File + RelativePath="..\testing_profile.h" + > + </File> + <File + RelativePath="..\..\..\net\url_request\url_request_test_job.cc" + > + </File> + <File + RelativePath="..\..\..\net\url_request\url_request_test_job.h" + > + </File> + </Filter> + <Filter + Name="TestGoogleURLTracker" + > + <File + RelativePath="..\..\browser\google_url_tracker_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestURLFetcher" + > + <File + RelativePath="..\..\browser\url_fetcher_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestURLFixerUpper" + > + <File + RelativePath="..\..\browser\url_fixer_upper_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestWebContents" + > + <File + RelativePath="..\..\browser\web_contents_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestVisitedLink" + > + <File + RelativePath="..\..\browser\visitedlink_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestResourceDispatcher" + > + <File + RelativePath="..\..\browser\resource_dispatcher_host_unittest.cc" + > + </File> + <File + RelativePath="..\..\common\resource_dispatcher_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestIPCMessage" + > + <File + RelativePath="..\..\common\ipc_message_unittest.cc" + > + </File> + <File + RelativePath="..\..\common\ipc_sync_channel_unittest.cc" + > + </File> + <File + RelativePath="..\..\common\ipc_sync_channel_unittest.h" + > + </File> + <File + RelativePath="..\..\common\ipc_sync_message_unittest.cc" + > + </File> + <File + RelativePath="..\..\common\ipc_sync_message_unittest.h" + > + </File> + </Filter> + <Filter + Name="TestController" + > + <File + RelativePath="..\..\browser\controller_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestAutocomplete" + > + <File + RelativePath="..\..\browser\autocomplete\autocomplete_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\autocomplete\history_contents_provider_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\autocomplete\history_url_provider_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\autocomplete\keyword_provider_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestChromeViews" + > + <File + RelativePath="..\..\views\focus_manager_unittest.cc" + > + </File> + <File + RelativePath="..\..\views\grid_layout_unittest.cc" + > + </File> + <File + RelativePath="..\..\views\view_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestHistory" + > + <File + RelativePath="..\..\browser\history\expire_history_backend_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\history_backend_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\history_querying_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\history_types_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\history_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\starred_url_database_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\text_database_manager_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\text_database_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\url_database_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\visit_database_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\history\visit_tracker_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestJSONValueSerializer" + > + <File + RelativePath="..\..\common\json_value_serializer_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestNotificationService" + > + <File + RelativePath="..\..\common\notification_service_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestAnimation" + > + <File + RelativePath="..\..\common\animation_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestJPEGCodec" + > + <File + RelativePath="..\..\common\jpeg_codec_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestPrefService" + > + <File + RelativePath="..\..\common\pref_member_unittest.cc" + > + </File> + <File + RelativePath="..\..\common\pref_service_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestSessionService" + > + <File + RelativePath="..\..\browser\session_backend_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\session_service_test_helper.cc" + > + </File> + <File + RelativePath="..\..\browser\session_service_test_helper.h" + > + </File> + <File + RelativePath="..\..\browser\session_service_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestThumbnailDatabase" + > + <File + RelativePath="..\..\browser\history\thumbnail_database_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestL10n" + > + <File + RelativePath="..\..\common\l10n_util_unittest.cc" + > + </File> + <File + RelativePath="..\data\resource.h" + > + </File> + <File + RelativePath="..\data\resource.rc" + > + </File> + </Filter> + <Filter + Name="TestMRUCache" + > + <File + RelativePath="..\..\common\mru_cache_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestPerformanceProfiler" + > + <File + RelativePath="..\..\browser\navigation_profiler_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\page_load_tracker_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestNavigationController" + > + <File + RelativePath="..\..\browser\navigation_controller_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestMetricsLog" + > + <File + RelativePath="..\..\browser\metrics_log_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestBzip2" + > + <File + RelativePath="..\..\common\bzip2_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestTitleChomper" + > + <File + RelativePath="..\..\browser\title_chomper_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestTemplateURLParser" + > + <File + RelativePath="..\..\browser\template_url_parser_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestTemplateURL" + > + <File + RelativePath="..\..\browser\template_url_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestTemplateURLModel" + > + <File + RelativePath="..\..\browser\template_url_model_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestBookmarkDragData" + > + <File + RelativePath="..\..\browser\bookmark_drag_data_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestMetricsResponse" + > + <File + RelativePath="..\..\browser\metrics_response_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestProfileManager" + > + <File + RelativePath="..\..\browser\profile_manager_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestQueryParser" + > + <File + RelativePath="..\..\browser\history\query_parser_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestWinUtil" + > + <File + RelativePath="..\..\common\win_util_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestTimeFormat" + > + <File + RelativePath="..\..\common\time_format_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestBackForwardHistory" + > + <File + RelativePath="..\..\browser\back_forward_menu_model_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestBookmarkBarModel" + > + <File + RelativePath="..\..\browser\bookmark_bar_model_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestCacheManagerHost" + > + <File + RelativePath="..\..\browser\cache_manager_host_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestFocusManager" + > + <File + RelativePath="..\..\views\focus_manager_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestDragAndDrop" + > + <File + RelativePath="..\..\common\os_exchange_data_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestSnippet" + > + <File + RelativePath="..\..\browser\history\snippet_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestEmf" + > + <File + RelativePath="..\..\common\gfx\emf_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestEncryptor" + > + <File + RelativePath="..\..\browser\encryptor_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestSpellCheck" + > + <File + RelativePath="..\..\renderer\spellcheck_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestDownload" + > + <File + RelativePath="..\..\browser\download_manager_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestTabStripModel" + > + <File + RelativePath="..\..\browser\tabs\tab_strip_model_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestIconUtil" + > + <File + RelativePath="..\..\common\gfx\icon_util_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestWindowSizer" + > + <File + RelativePath="..\..\browser\window_sizer_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestURLElider" + > + <File + RelativePath="..\..\common\gfx\url_elider_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestPrinting" + > + <File + RelativePath="..\..\browser\printing\page_setup_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\printing\printing_test.h" + > + </File> + <File + RelativePath="..\..\browser\printing\win_printing_context_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestSafeBrowsing" + > + <File + RelativePath="..\..\browser\safe_browsing\bloom_filter_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\safe_browsing\chunk_range_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\safe_browsing\protocol_manager_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\safe_browsing\protocol_parser_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\safe_browsing\safe_browsing_database_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\safe_browsing\safe_browsing_util_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestChromePlugin" + > + <File + RelativePath="..\..\common\chrome_plugin_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestSiteInstance" + > + <File + RelativePath="..\..\browser\site_instance_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestSavePage" + > + <File + RelativePath="..\..\browser\save_package_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestPasswordManager" + > + <File + RelativePath="..\..\browser\password_form_manager_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestRendererSecurityPolicy" + > + <File + RelativePath="..\..\browser\renderer_security_policy_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestDnsHostInfo" + > + <File + RelativePath="..\..\browser\net\dns_host_info_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestDnsPrefetch" + > + <File + RelativePath="..\..\browser\net\dns_master_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestRenderDnsMaster" + > + <File + RelativePath="..\..\renderer\net\render_dns_master_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestRenderDnsQueue" + > + <File + RelativePath="..\..\renderer\net\render_dns_queue_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestImporter" + > + <File + RelativePath="..\..\browser\firefox_importer_unittest.cc" + > + </File> + <File + RelativePath="..\..\browser\importer_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestRLZ" + > + <File + RelativePath="..\..\browser\rlz\rlz_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestWebDatabase" + > + <File + RelativePath="..\..\browser\webdata\web_database_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestChromeThread" + > + <File + RelativePath="..\..\browser\chrome_thread_unittest.cc" + > + </File> + </Filter> + <Filter + Name="TestHunspell" + > + <File + RelativePath="..\..\tools\convert_dict\aff_reader.cc" + > + </File> + <File + RelativePath="..\..\tools\convert_dict\aff_reader.h" + > + </File> + <File + RelativePath="..\..\third_party\hunspell\google\bdict.h" + > + </File> + <File + RelativePath="..\..\third_party\hunspell\google\bdict_reader.cc" + > + </File> + <File + RelativePath="..\..\third_party\hunspell\google\bdict_reader.h" + > + </File> + <File + RelativePath="..\..\third_party\hunspell\google\bdict_writer.cc" + > + </File> + <File + RelativePath="..\..\third_party\hunspell\google\bdict_writer.h" + > + </File> + <File + RelativePath="..\..\tools\convert_dict\dic_reader.cc" + > + </File> + <File + RelativePath="..\..\tools\convert_dict\dic_reader.h" + > + </File> + <File + RelativePath="..\..\tools\convert_dict\hunspell_reader.cc" + > + </File> + <File + RelativePath="..\..\tools\convert_dict\hunspell_reader.h" + > + </File> + <File + RelativePath="..\..\third_party\hunspell\google\hunspell_tests.cc" + > + </File> + </Filter> + <Filter + Name="TestURL" + > + <File + RelativePath="..\..\..\googleurl\src\gurl_unittest.cc" + > + </File> + <File + RelativePath="..\..\..\googleurl\src\url_canon_unittest.cc" + > + </File> + <File + RelativePath="..\..\..\googleurl\src\url_parse_unittest.cc" + > + </File> + <File + RelativePath="..\..\..\googleurl\src\url_util_unittest.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/test/unit/win/rundebug.bat b/chrome/test/unit/win/rundebug.bat new file mode 100644 index 0000000..0b8c4bc --- /dev/null +++ b/chrome/test/unit/win/rundebug.bat @@ -0,0 +1,5 @@ +rem This is a convenience batch file that you can use to run the debug-mode +rem unit tests via a Windows shortcut. + +..\..\..\debug\UnitTests.exe +pause |