Index: chrome_frame/test/net/fake_external_tab.cc |
=================================================================== |
--- chrome_frame/test/net/fake_external_tab.cc (revision 0) |
+++ chrome_frame/test/net/fake_external_tab.cc (revision 0) |
@@ -0,0 +1,391 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome_frame/test/net/fake_external_tab.h" |
+ |
+#include <exdisp.h> |
+ |
+#include "app/app_paths.h" |
+#include "app/resource_bundle.h" |
+#include "app/win_util.h" |
+ |
+#include "base/command_line.h" |
+#include "base/file_util.h" |
+#include "base/icu_util.h" |
+#include "base/path_service.h" |
+#include "base/scoped_bstr_win.h" |
+#include "base/scoped_comptr_win.h" |
+#include "base/scoped_variant_win.h" |
+ |
+#include "chrome/browser/browser_prefs.h" |
+#include "chrome/browser/chrome_thread.h" |
+#include "chrome/browser/process_singleton.h" |
+#include "chrome/browser/profile_manager.h" |
+#include "chrome/common/chrome_constants.h" |
+#include "chrome/common/chrome_paths.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/pref_names.h" |
+#include "chrome/browser/renderer_host/render_process_host.h" |
+ |
+#include "chrome_frame/utils.h" |
+#include "chrome_frame/test/chrome_frame_test_utils.h" |
+#include "chrome_frame/test/net/dialog_watchdog.h" |
+#include "chrome_frame/test/net/test_automation_resource_message_filter.h" |
+ |
+namespace { |
+ |
+// A special command line switch to allow developers to manually launch the |
+// browser and debug CF inside the browser. |
+const wchar_t kManualBrowserLaunch[] = L"manual-browser"; |
+ |
+// Pops up a message box after the test environment has been set up |
+// and before tearing it down. Useful for when debugging tests and not |
+// the test environment that's been set up. |
+const wchar_t kPromptAfterSetup[] = L"prompt-after-setup"; |
+ |
+const int kTestServerPort = 4666; |
+// The test HTML we use to initialize Chrome Frame. |
+// Note that there's a little trick in there to avoid an extra URL request |
+// that the browser will otherwise make for the site's favicon. |
+// If we don't do this the browser will create a new URL request after |
+// the CF page has been initialized and that URL request will confuse the |
+// global URL instance counter in the unit tests and subsequently trip |
+// some DCHECKs. |
+const char kChromeFrameHtml[] = "<html><head>" |
+ "<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />" |
+ "<link rel=\"shortcut icon\" href=\"file://c:\\favicon.ico\"/>" |
+ "</head><body>Chrome Frame should now be loaded</body></html>"; |
+ |
+bool ShouldLaunchBrowser() { |
+ return !CommandLine::ForCurrentProcess()->HasSwitch(kManualBrowserLaunch); |
+} |
+ |
+bool PromptAfterSetup() { |
+ return CommandLine::ForCurrentProcess()->HasSwitch(kPromptAfterSetup); |
+} |
+ |
+} // end namespace |
+ |
+FakeExternalTab::FakeExternalTab() { |
+ PathService::Get(chrome::DIR_USER_DATA, &overridden_user_dir_); |
+ user_data_dir_ = FilePath::FromWStringHack(GetProfilePath()); |
+ PathService::Override(chrome::DIR_USER_DATA, user_data_dir_); |
+ process_singleton_.reset(new ProcessSingleton(user_data_dir_)); |
+} |
+ |
+FakeExternalTab::~FakeExternalTab() { |
+ if (!overridden_user_dir_.empty()) { |
+ PathService::Override(chrome::DIR_USER_DATA, overridden_user_dir_); |
+ } |
+} |
+ |
+std::wstring FakeExternalTab::GetProfileName() { |
+ return L"iexplore"; |
+} |
+ |
+std::wstring FakeExternalTab::GetProfilePath() { |
+ std::wstring path; |
+ GetUserProfileBaseDirectory(&path); |
+ file_util::AppendToPath(&path, GetProfileName()); |
+ return path; |
+} |
+ |
+void FakeExternalTab::Initialize() { |
+ DCHECK(g_browser_process == NULL); |
+ |
+ // The gears plugin causes the PluginRequestInterceptor to kick in and it |
+ // will cause problems when it tries to intercept URL requests. |
+ PathService::Override(chrome::FILE_GEARS_PLUGIN, FilePath()); |
+ |
+ icu_util::Initialize(); |
+ |
+ chrome::RegisterPathProvider(); |
+ app::RegisterPathProvider(); |
+ |
+ ResourceBundle::InitSharedInstance(L"en-US"); |
+ ResourceBundle::GetSharedInstance().LoadThemeResources(); |
+ |
+ const CommandLine* cmd = CommandLine::ForCurrentProcess(); |
+ browser_process_.reset(new BrowserProcessImpl(*cmd)); |
+ RenderProcessHost::set_run_renderer_in_process(true); |
+ // BrowserProcessImpl's constructor should set g_browser_process. |
+ DCHECK(g_browser_process); |
+ |
+ Profile* profile = g_browser_process->profile_manager()-> |
+ GetDefaultProfile(FilePath(user_data())); |
+ PrefService* prefs = profile->GetPrefs(); |
+ PrefService* local_state = browser_process_->local_state(); |
+ local_state->RegisterStringPref(prefs::kApplicationLocale, L""); |
+ local_state->RegisterBooleanPref(prefs::kMetricsReportingEnabled, false); |
+ |
+ browser::RegisterAllPrefs(prefs, local_state); |
+ |
+ // Override some settings to avoid hitting some preferences that have not |
+ // been registered. |
+ prefs->SetBoolean(prefs::kPasswordManagerEnabled, false); |
+ prefs->SetBoolean(prefs::kAlternateErrorPagesEnabled, false); |
+ prefs->SetBoolean(prefs::kSafeBrowsingEnabled, false); |
+ |
+ profile->InitExtensions(); |
+} |
+ |
+void FakeExternalTab::Shutdown() { |
+ browser_process_.reset(); |
+ g_browser_process = NULL; |
+ process_singleton_.reset(); |
+ |
+ ResourceBundle::CleanupSharedInstance(); |
+} |
+ |
+CFUrlRequestUnittestRunner::CFUrlRequestUnittestRunner(int argc, char** argv) |
+ : NetTestSuite(argc, argv), |
+ chrome_frame_html_("/chrome_frame", kChromeFrameHtml) { |
+ fake_chrome_.Initialize(); |
+ pss_subclass_.reset(new ProcessSingletonSubclass(this)); |
+ EXPECT_TRUE(pss_subclass_->Subclass(fake_chrome_.user_data())); |
+ StartChromeFrameInHostBrowser(); |
+} |
+ |
+CFUrlRequestUnittestRunner::~CFUrlRequestUnittestRunner() { |
+ fake_chrome_.Shutdown(); |
+} |
+ |
+DWORD WINAPI NavigateIE(void* param) { |
+ return 0; |
+ win_util::ScopedCOMInitializer com; |
+ BSTR url = reinterpret_cast<BSTR>(param); |
+ |
+ bool found = false; |
+ int retries = 0; |
+ const int kMaxRetries = 20; |
+ while (!found && retries < kMaxRetries) { |
+ ScopedComPtr<IShellWindows> windows; |
+ HRESULT hr = ::CoCreateInstance(__uuidof(ShellWindows), NULL, CLSCTX_ALL, |
+ IID_IShellWindows, reinterpret_cast<void**>(windows.Receive())); |
+ DCHECK(SUCCEEDED(hr)) << "CoCreateInstance"; |
+ |
+ if (SUCCEEDED(hr)) { |
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); |
+ long count = 0; // NOLINT |
+ windows->get_Count(&count); |
+ VARIANT i = { VT_I4 }; |
+ for (i.lVal = 0; i.lVal < count; ++i.lVal) { |
+ ScopedComPtr<IDispatch> folder; |
+ windows->Item(i, folder.Receive()); |
+ if (folder != NULL) { |
+ ScopedComPtr<IWebBrowser2> browser; |
+ if (SUCCEEDED(browser.QueryFrom(folder))) { |
+ found = true; |
+ browser->Stop(); |
+ Sleep(1000); |
+ VARIANT empty = ScopedVariant::kEmptyVariant; |
+ hr = browser->Navigate(url, &empty, &empty, &empty, &empty); |
+ DCHECK(SUCCEEDED(hr)) << "Failed to navigate"; |
+ break; |
+ } |
+ } |
+ } |
+ } |
+ if (!found) { |
+ DLOG(INFO) << "Waiting for browser to initialize..."; |
+ ::Sleep(100); |
+ retries++; |
+ } |
+ } |
+ |
+ DCHECK(retries < kMaxRetries); |
+ DCHECK(found); |
+ |
+ ::SysFreeString(url); |
+ |
+ return 0; |
+} |
+ |
+void CFUrlRequestUnittestRunner::StartChromeFrameInHostBrowser() { |
+ if (!ShouldLaunchBrowser()) |
+ return; |
+ |
+ win_util::ScopedCOMInitializer com; |
+ chrome_frame_test::CloseAllIEWindows(); |
+ |
+ test_http_server_.reset(new test_server::SimpleWebServer(kTestServerPort)); |
+ test_http_server_->AddResponse(&chrome_frame_html_); |
+ std::wstring url(StringPrintf(L"http://localhost:%i/chrome_frame", |
+ kTestServerPort).c_str()); |
+ |
+ // Launch IE. This launches IE correctly on Vista too. |
+ ScopedHandle ie_process(chrome_frame_test::LaunchIE(url)); |
+ EXPECT_TRUE(ie_process.IsValid()); |
+ |
+ // NOTE: If you're running IE8 and CF is not being loaded, you need to |
+ // disable IE8's prebinding until CF properly handles that situation. |
+ // |
+ // HKCU\Software\Microsoft\Internet Explorer\Main |
+ // Value name: EnablePreBinding (REG_DWORD) |
+ // Value: 0 |
+} |
+ |
+void CFUrlRequestUnittestRunner::ShutDownHostBrowser() { |
+ if (ShouldLaunchBrowser()) { |
+ win_util::ScopedCOMInitializer com; |
+ chrome_frame_test::CloseAllIEWindows(); |
+ } |
+} |
+ |
+// Override virtual void Initialize to not call icu initialize |
+void CFUrlRequestUnittestRunner::Initialize() { |
+ DCHECK(::GetCurrentThreadId() == test_thread_id_); |
+ |
+ // Start by replicating some of the steps that would otherwise be |
+ // done by TestSuite::Initialize. We can't call the base class |
+ // directly because it will attempt to initialize some things such as |
+ // ICU that have already been initialized for this process. |
+ InitializeLogging(); |
+ base::Time::EnableHiResClockForTests(); |
+ |
+#if !defined(PURIFY) && defined(OS_WIN) |
+ logging::SetLogAssertHandler(UnitTestAssertHandler); |
+#endif // !defined(PURIFY) |
+ |
+ // Next, do some initialization for NetTestSuite. |
+ NetTestSuite::InitializeTestThread(); |
+} |
+ |
+void CFUrlRequestUnittestRunner::Shutdown() { |
+ DCHECK(::GetCurrentThreadId() == test_thread_id_); |
+ NetTestSuite::Shutdown(); |
+} |
+ |
+void CFUrlRequestUnittestRunner::OnConnectAutomationProviderToChannel( |
+ const std::string& channel_id) { |
+ Profile* profile = g_browser_process->profile_manager()-> |
+ GetDefaultProfile(fake_chrome_.user_data()); |
+ |
+ AutomationProviderList* list = |
+ g_browser_process->InitAutomationProviderList(); |
+ DCHECK(list); |
+ list->AddProvider(TestAutomationProvider::NewAutomationProvider(profile, |
+ channel_id, this)); |
+} |
+ |
+void CFUrlRequestUnittestRunner::OnInitialTabLoaded() { |
+ test_http_server_.reset(); |
+ StartTests(); |
+} |
+ |
+void CFUrlRequestUnittestRunner::RunMainUIThread() { |
+ DCHECK(MessageLoop::current()); |
+ DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
+ |
+ // Register the main thread by instantiating it, but don't call any methods. |
+ ChromeThread main_thread; |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ |
+ MessageLoop::current()->Run(); |
+} |
+ |
+void CFUrlRequestUnittestRunner::StartTests() { |
+ if (PromptAfterSetup()) |
+ MessageBoxA(NULL, "click ok to run", "", MB_OK); |
+ |
+ DCHECK_EQ(test_thread_.IsValid(), false); |
+ test_thread_.Set(::CreateThread(NULL, 0, RunAllUnittests, this, 0, |
+ &test_thread_id_)); |
+ DCHECK(test_thread_.IsValid()); |
+} |
+ |
+// static |
+DWORD CFUrlRequestUnittestRunner::RunAllUnittests(void* param) { |
+ PlatformThread::SetName("CFUrlRequestUnittestRunner"); |
+ CFUrlRequestUnittestRunner* me = |
+ reinterpret_cast<CFUrlRequestUnittestRunner*>(param); |
+ me->Run(); |
+ me->fake_chrome_.ui_loop()->PostTask(FROM_HERE, |
+ NewRunnableFunction(TakeDownBrowser, me)); |
+ return 0; |
+} |
+ |
+// static |
+void CFUrlRequestUnittestRunner::TakeDownBrowser( |
+ CFUrlRequestUnittestRunner* me) { |
+ if (PromptAfterSetup()) |
+ MessageBoxA(NULL, "click ok to exit", "", MB_OK); |
+ |
+ me->ShutDownHostBrowser(); |
+} |
+ |
+void CFUrlRequestUnittestRunner::InitializeLogging() { |
+ FilePath exe; |
+ PathService::Get(base::FILE_EXE, &exe); |
+ FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log")); |
+ logging::InitLogging(log_filename.value().c_str(), |
+ logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, |
+ logging::LOCK_LOG_FILE, |
+ logging::DELETE_OLD_LOG_FILE); |
+ // We want process and thread IDs because we may have multiple processes. |
+ // Note: temporarily enabled timestamps in an effort to catch bug 6361. |
+ logging::SetLogItems(true, true, true, true); |
+} |
+ |
+void FilterDisabledTests() { |
+ if (::testing::FLAGS_gtest_filter.GetLength() && |
+ ::testing::FLAGS_gtest_filter.Compare("*") != 0) { |
+ // Don't override user specified filters. |
+ return; |
+ } |
+ |
+ const char* disabled_tests[] = { |
+ // Tests disabled since they're testing the same functionality used |
+ // by the TestAutomationProvider. |
+ "URLRequestTest.InterceptNetworkError", |
+ "URLRequestTest.InterceptRestartRequired", |
+ "URLRequestTest.InterceptRespectsCancelMain", |
+ "URLRequestTest.InterceptRespectsCancelRedirect", |
+ "URLRequestTest.InterceptRespectsCancelFinal", |
+ "URLRequestTest.InterceptRespectsCancelInRestart", |
+ "URLRequestTest.InterceptRedirect", |
+ "URLRequestTest.InterceptServerError", |
+ "URLRequestTestFTP.*", |
+ |
+ // Tests that are currently not working: |
+ |
+ // Temporarily disabled because they needs user input (login dialog). |
+ "URLRequestTestHTTP.BasicAuth", |
+ "URLRequestTestHTTP.BasicAuthWithCookies", |
+ |
+ // HTTPS tests temporarily disabled due to the certificate error dialog. |
+ // TODO(tommi): The tests currently fail though, so need to fix. |
+ "HTTPSRequestTest.HTTPSMismatchedTest", |
+ "HTTPSRequestTest.HTTPSExpiredTest", |
+ |
+ // Tests chrome's network stack's cache (might not apply to CF). |
+ "URLRequestTestHTTP.VaryHeader", |
+ |
+ // I suspect we can only get this one to work (if at all) on IE8 and |
+ // later by using the new INTERNET_OPTION_SUPPRESS_BEHAVIOR flags |
+ // See http://msdn.microsoft.com/en-us/library/aa385328(VS.85).aspx |
+ "URLRequestTest.DoNotSaveCookies", |
+ }; |
+ |
+ std::string filter("-"); // All following filters will be negative. |
+ for (int i = 0; i < arraysize(disabled_tests); ++i) { |
+ if (i > 0) |
+ filter += ":"; |
+ filter += disabled_tests[i]; |
+ } |
+ |
+ ::testing::FLAGS_gtest_filter = filter; |
+} |
+ |
+int main(int argc, char** argv) { |
+ DialogWatchdog watchdog; |
+ // See url_request_unittest.cc for these credentials. |
+ SupplyProxyCredentials credentials("user", "secret"); |
+ watchdog.AddObserver(&credentials); |
+ testing::InitGoogleTest(&argc, argv); |
+ FilterDisabledTests(); |
+ CFUrlRequestUnittestRunner test_suite(argc, argv); |
+ test_suite.RunMainUIThread(); |
+ return 0; |
+} |