Loosen up heuristics for detecting account creation forms.
[chromium-blink-merge.git] / chrome_frame / test / chrome_frame_test_utils.cc
blobd8d1e133b3d0a6dd05166e0eddfd76f72a04ceb1
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome_frame/test/chrome_frame_test_utils.h"
7 #include <atlapp.h>
8 #include <atlmisc.h>
9 #include <iepmapi.h>
10 #include <sddl.h>
11 #include <shlobj.h>
12 #include <winsock2.h>
14 #include "base/command_line.h"
15 #include "base/file_path.h"
16 #include "base/file_util.h"
17 #include "base/file_version_info.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/path_service.h"
20 #include "base/process.h"
21 #include "base/process_util.h"
22 #include "base/string_util.h"
23 #include "base/stringprintf.h"
24 #include "base/utf_string_conversions.h"
25 #include "base/win/registry.h"
26 #include "base/win/scoped_handle.h"
27 #include "base/win/windows_version.h"
28 #include "chrome/common/chrome_paths.h"
29 #include "chrome/common/chrome_paths_internal.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome_frame/utils.h"
32 #include "net/base/net_util.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "ui/base/clipboard/clipboard.h"
35 #include "ui/base/clipboard/scoped_clipboard_writer.h"
37 namespace chrome_frame_test {
39 const wchar_t kCrashServicePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
41 const DWORD kCrashServicePipeDesiredAccess = FILE_READ_DATA |
42 FILE_WRITE_DATA |
43 FILE_WRITE_ATTRIBUTES;
45 const DWORD kCrashServicePipeFlagsAndAttributes = SECURITY_IDENTIFICATION |
46 SECURITY_SQOS_PRESENT;
47 const int kCrashServiceStartupTimeoutMs = 500;
49 const wchar_t kIEImageName[] = L"iexplore.exe";
50 const wchar_t kIEBrokerImageName[] = L"ieuser.exe";
51 const char kChromeImageName[] = "chrome.exe";
52 const wchar_t kIEProfileName[] = L"iexplore";
53 const wchar_t kChromeLauncher[] = L"chrome_launcher.exe";
55 #ifndef NDEBUG
56 const base::TimeDelta kChromeFrameLongNavigationTimeout =
57 base::TimeDelta::FromSeconds(30);
58 const base::TimeDelta kChromeFrameVeryLongNavigationTimeout =
59 base::TimeDelta::FromSeconds(90);
60 #else
61 const base::TimeDelta kChromeFrameLongNavigationTimeout =
62 base::TimeDelta::FromSeconds(15);
63 const base::TimeDelta kChromeFrameVeryLongNavigationTimeout =
64 base::TimeDelta::FromSeconds(45);
65 #endif
67 // Callback function for EnumThreadWindows.
68 BOOL CALLBACK CloseWindowsThreadCallback(HWND hwnd, LPARAM param) {
69 int& count = *reinterpret_cast<int*>(param);
70 if (IsWindowVisible(hwnd)) {
71 if (IsWindowEnabled(hwnd)) {
72 DWORD results = 0;
73 if (!::SendMessageTimeout(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0, SMTO_BLOCK,
74 10000, &results)) {
75 LOG(WARNING) << "Window hung: " << base::StringPrintf(L"%08X", hwnd);
77 count++;
78 } else {
79 LOG(WARNING) << "Skipping disabled window: "
80 << base::StringPrintf(L"%08X", hwnd);
83 return TRUE; // continue enumeration
86 // Attempts to close all non-child, visible windows on the given thread.
87 // The return value is the number of visible windows a close request was
88 // sent to.
89 int CloseVisibleTopLevelWindowsOnThread(DWORD thread_id) {
90 int window_close_attempts = 0;
91 EnumThreadWindows(thread_id, CloseWindowsThreadCallback,
92 reinterpret_cast<LPARAM>(&window_close_attempts));
93 return window_close_attempts;
96 // Enumerates the threads of a process and attempts to close visible non-child
97 // windows on all threads of the process.
98 // The return value is the number of visible windows a close request was
99 // sent to.
100 int CloseVisibleWindowsOnAllThreads(HANDLE process) {
101 DWORD process_id = ::GetProcessId(process);
102 if (process_id == 0) {
103 NOTREACHED();
104 return 0;
107 base::win::ScopedHandle snapshot(
108 CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0));
109 if (!snapshot.IsValid()) {
110 NOTREACHED();
111 return 0;
114 int window_close_attempts = 0;
115 THREADENTRY32 te = { sizeof(THREADENTRY32) };
116 if (Thread32First(snapshot, &te)) {
117 do {
118 if (RTL_CONTAINS_FIELD(&te, te.dwSize, th32OwnerProcessID) &&
119 te.th32OwnerProcessID == process_id) {
120 window_close_attempts +=
121 CloseVisibleTopLevelWindowsOnThread(te.th32ThreadID);
123 te.dwSize = sizeof(te);
124 } while (Thread32Next(snapshot, &te));
127 return window_close_attempts;
130 std::wstring GetExecutableAppPath(const std::wstring& file) {
131 std::wstring kAppPathsKey =
132 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\";
134 std::wstring app_path;
135 base::win::RegKey key(HKEY_LOCAL_MACHINE, (kAppPathsKey + file).c_str(),
136 KEY_READ);
137 if (key.Handle()) {
138 key.ReadValue(NULL, &app_path);
141 return app_path;
144 std::wstring FormatCommandForApp(const std::wstring& exe_name,
145 const std::wstring& argument) {
146 std::wstring reg_path(
147 base::StringPrintf(L"Applications\\%ls\\shell\\open\\command",
148 exe_name.c_str()));
149 base::win::RegKey key(HKEY_CLASSES_ROOT, reg_path.c_str(), KEY_READ);
151 std::wstring command;
152 if (key.Handle()) {
153 key.ReadValue(NULL, &command);
154 int found = command.find(L"%1");
155 if (found >= 0) {
156 command.replace(found, 2, argument);
159 return command;
162 base::ProcessHandle LaunchExecutable(const std::wstring& executable,
163 const std::wstring& argument) {
164 base::ProcessHandle process = NULL;
165 std::wstring path = GetExecutableAppPath(executable);
166 if (path.empty()) {
167 path = FormatCommandForApp(executable, argument);
168 if (path.empty()) {
169 LOG(ERROR) << "Failed to find executable: " << executable;
170 } else {
171 CommandLine cmdline = CommandLine::FromString(path);
172 if (!base::LaunchProcess(cmdline, base::LaunchOptions(), &process)) {
173 LOG(ERROR) << "LaunchProcess failed: " << ::GetLastError();
176 } else {
177 CommandLine cmdline((FilePath(path)));
178 cmdline.AppendArgNative(argument);
179 if (!base::LaunchProcess(cmdline, base::LaunchOptions(), &process)) {
180 LOG(ERROR) << "LaunchProcess failed: " << ::GetLastError();
183 return process;
186 base::ProcessHandle LaunchChrome(const std::wstring& url,
187 const FilePath& user_data_dir) {
188 FilePath path;
189 PathService::Get(base::DIR_MODULE, &path);
190 path = path.AppendASCII(kChromeImageName);
192 CommandLine cmd(path);
193 cmd.AppendSwitch(switches::kNoFirstRun);
194 if (!user_data_dir.empty())
195 cmd.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
196 cmd.AppendArgNative(url);
198 base::ProcessHandle process = NULL;
199 base::LaunchProcess(cmd, base::LaunchOptions(), &process);
200 return process;
203 base::ProcessHandle LaunchIEOnVista(const std::wstring& url) {
204 typedef HRESULT (WINAPI* IELaunchURLPtr)(const wchar_t* url,
205 PROCESS_INFORMATION* pi,
206 VOID* info);
208 IELaunchURLPtr launch;
209 PROCESS_INFORMATION pi = {0};
210 IELAUNCHURLINFO info = {sizeof info, 0};
211 HMODULE h = LoadLibrary(L"ieframe.dll");
212 if (!h) {
213 LOG(ERROR) << "Failed to load ieframe.dll: " << ::GetLastError();
214 return NULL;
216 launch = reinterpret_cast<IELaunchURLPtr>(GetProcAddress(h, "IELaunchURL"));
217 CHECK(launch);
218 HRESULT hr = launch(url.c_str(), &pi, &info);
219 FreeLibrary(h);
220 if (SUCCEEDED(hr)) {
221 CloseHandle(pi.hThread);
222 } else {
223 LOG(ERROR) << base::StringPrintf("IELaunchURL failed: 0x%08X", hr);
225 return pi.hProcess;
228 base::ProcessHandle LaunchIE(const std::wstring& url) {
229 if (GetInstalledIEVersion() >= IE_8) {
230 chrome_frame_test::ClearIESessionHistory();
233 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
234 return LaunchIEOnVista(url);
236 return LaunchExecutable(kIEImageName, url);
239 int CloseAllIEWindows() {
240 int ret = 0;
242 base::win::ScopedComPtr<IShellWindows> windows;
243 HRESULT hr = ::CoCreateInstance(__uuidof(ShellWindows), NULL, CLSCTX_ALL,
244 IID_IShellWindows, reinterpret_cast<void**>(windows.Receive()));
245 DCHECK(SUCCEEDED(hr));
247 if (SUCCEEDED(hr)) {
248 long count = 0; // NOLINT
249 windows->get_Count(&count);
250 VARIANT i = { VT_I4 };
251 for (i.lVal = 0; i.lVal < count; ++i.lVal) {
252 base::win::ScopedComPtr<IDispatch> folder;
253 windows->Item(i, folder.Receive());
254 if (folder != NULL) {
255 base::win::ScopedComPtr<IWebBrowser2> browser;
256 if (SUCCEEDED(browser.QueryFrom(folder))) {
257 bool is_ie = true;
258 HWND window = NULL;
259 // Check the class of the browser window to make sure we only close
260 // IE windows.
261 if (browser->get_HWND(reinterpret_cast<SHANDLE_PTR*>(window))) {
262 wchar_t class_name[MAX_PATH];
263 if (::GetClassName(window, class_name, arraysize(class_name))) {
264 is_ie = _wcsicmp(class_name, L"IEFrame") == 0;
267 if (is_ie) {
268 browser->Quit();
269 ++ret;
276 return ret;
280 LowIntegrityToken::LowIntegrityToken() : impersonated_(false) {
283 LowIntegrityToken::~LowIntegrityToken() {
284 RevertToSelf();
287 BOOL LowIntegrityToken::RevertToSelf() {
288 BOOL ok = TRUE;
289 if (impersonated_) {
290 DCHECK(IsImpersonated());
291 ok = ::RevertToSelf();
292 if (ok)
293 impersonated_ = false;
296 return ok;
299 BOOL LowIntegrityToken::Impersonate() {
300 DCHECK(!impersonated_);
301 DCHECK(!IsImpersonated());
302 HANDLE process_token_handle = NULL;
303 BOOL ok = ::OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE,
304 &process_token_handle);
305 if (!ok) {
306 LOG(ERROR) << "::OpenProcessToken failed: " << GetLastError();
307 return ok;
310 base::win::ScopedHandle process_token(process_token_handle);
311 // Create impersonation low integrity token.
312 HANDLE impersonation_token_handle = NULL;
313 ok = ::DuplicateTokenEx(process_token,
314 TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, NULL,
315 SecurityImpersonation, TokenImpersonation, &impersonation_token_handle);
316 if (!ok) {
317 LOG(ERROR) << "::DuplicateTokenEx failed: " << GetLastError();
318 return ok;
321 // TODO(stoyan): sandbox/win/src/restricted_token_utils.cc has
322 // SetTokenIntegrityLevel function already.
323 base::win::ScopedHandle impersonation_token(impersonation_token_handle);
324 PSID integrity_sid = NULL;
325 TOKEN_MANDATORY_LABEL tml = {0};
326 ok = ::ConvertStringSidToSid(SDDL_ML_LOW, &integrity_sid);
327 if (!ok) {
328 LOG(ERROR) << "::ConvertStringSidToSid failed: " << GetLastError();
329 return ok;
332 tml.Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
333 tml.Label.Sid = integrity_sid;
334 ok = ::SetTokenInformation(impersonation_token, TokenIntegrityLevel,
335 &tml, sizeof(tml) + ::GetLengthSid(integrity_sid));
336 ::LocalFree(integrity_sid);
337 if (!ok) {
338 LOG(ERROR) << "::SetTokenInformation failed: " << GetLastError();
339 return ok;
342 // Switch current thread to low integrity.
343 ok = ::ImpersonateLoggedOnUser(impersonation_token);
344 if (ok) {
345 impersonated_ = true;
346 } else {
347 LOG(ERROR) << "::ImpersonateLoggedOnUser failed: " << GetLastError();
350 return ok;
353 bool LowIntegrityToken::IsImpersonated() {
354 HANDLE token = NULL;
355 if (!::OpenThreadToken(::GetCurrentThread(), 0, false, &token) &&
356 ::GetLastError() != ERROR_NO_TOKEN) {
357 return true;
360 if (token)
361 ::CloseHandle(token);
363 return false;
366 HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser) {
367 if (!web_browser)
368 return E_INVALIDARG;
370 if (GetInstalledIEVersion() >= IE_8) {
371 chrome_frame_test::ClearIESessionHistory();
374 AllowSetForegroundWindow(ASFW_ANY);
376 HRESULT hr = S_OK;
377 DWORD cocreate_flags = CLSCTX_LOCAL_SERVER;
378 chrome_frame_test::LowIntegrityToken token;
379 base::IntegrityLevel integrity_level = base::INTEGRITY_UNKNOWN;
380 // Vista has a bug which manifests itself when a medium integrity process
381 // launches a COM server like IE which runs in protected mode due to UAC.
382 // This causes the IWebBrowser2 interface which is returned to be useless,
383 // i.e it does not receive any events, etc. Our workaround for this is
384 // to impersonate a low integrity token and then launch IE. Skip this if the
385 // tests are running at high integrity, since the workaround results in the
386 // medium-integrity broker exiting, and the low-integrity IE is therefore
387 // unable to get chrome_launcher running at medium integrity.
388 if (base::win::GetVersion() == base::win::VERSION_VISTA &&
389 GetInstalledIEVersion() == IE_7 &&
390 base::GetProcessIntegrityLevel(base::Process::Current().handle(),
391 &integrity_level) &&
392 integrity_level != base::HIGH_INTEGRITY) {
393 // Create medium integrity browser that will launch IE broker.
394 base::win::ScopedComPtr<IWebBrowser2> medium_integrity_browser;
395 hr = medium_integrity_browser.CreateInstance(CLSID_InternetExplorer, NULL,
396 CLSCTX_LOCAL_SERVER);
397 if (FAILED(hr))
398 return hr;
399 medium_integrity_browser->Quit();
400 // Broker remains alive.
401 if (!token.Impersonate()) {
402 hr = HRESULT_FROM_WIN32(GetLastError());
403 return hr;
406 cocreate_flags |= CLSCTX_ENABLE_CLOAKING;
409 hr = ::CoCreateInstance(CLSID_InternetExplorer, NULL,
410 cocreate_flags, IID_IWebBrowser2,
411 reinterpret_cast<void**>(web_browser));
412 // ~LowIntegrityToken() will switch integrity back to medium.
413 return hr;
416 std::wstring GetExeVersion(const std::wstring& exe_path) {
417 scoped_ptr<FileVersionInfo> ie_version_info(
418 FileVersionInfo::CreateFileVersionInfo(FilePath(exe_path)));
419 return ie_version_info->product_version();
422 IEVersion GetInstalledIEVersion() {
423 std::wstring path = chrome_frame_test::GetExecutableAppPath(kIEImageName);
424 std::wstring version = GetExeVersion(path);
426 switch (version[0]) {
427 case '6':
428 return IE_6;
429 case '7':
430 return IE_7;
431 case '8':
432 return IE_8;
433 case '9':
434 return IE_9;
435 case '10':
436 return IE_10;
437 default:
438 break;
441 return IE_UNSUPPORTED;
444 FilePath GetProfilePathForIE() {
445 FilePath profile_path;
446 // Browsers without IDeleteBrowsingHistory in non-priv mode
447 // have their profiles moved into "Temporary Internet Files".
448 // The code below basically retrieves the version of IE and computes
449 // the profile directory accordingly.
450 if (GetInstalledIEVersion() <= IE_7) {
451 profile_path = GetIETemporaryFilesFolder();
452 profile_path = profile_path.Append(L"Google Chrome Frame");
453 } else {
454 GetChromeFrameProfilePath(kIEProfileName, &profile_path);
456 return profile_path;
459 FilePath GetTestDataFolder() {
460 FilePath test_dir;
461 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
462 test_dir = test_dir.Append(FILE_PATH_LITERAL("chrome_frame"))
463 .Append(FILE_PATH_LITERAL("test"))
464 .Append(FILE_PATH_LITERAL("data"));
465 return test_dir;
468 FilePath GetSeleniumTestFolder() {
469 FilePath test_dir;
470 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
471 test_dir = test_dir.Append(FILE_PATH_LITERAL("data"))
472 .Append(FILE_PATH_LITERAL("selenium_core"));
473 return test_dir;
476 std::wstring GetPathFromUrl(const std::wstring& url) {
477 string16 url16 = WideToUTF16(url);
478 GURL gurl = GURL(url16);
479 if (gurl.has_query()) {
480 GURL::Replacements replacements;
481 replacements.ClearQuery();
482 gurl = gurl.ReplaceComponents(replacements);
484 return UTF8ToWide(gurl.PathForRequest());
487 std::wstring GetPathAndQueryFromUrl(const std::wstring& url) {
488 string16 url16 = WideToUTF16(url);
489 GURL gurl = GURL(url16);
490 return UTF8ToWide(gurl.PathForRequest());
493 std::wstring GetClipboardText() {
494 string16 text16;
495 ui::Clipboard::GetForCurrentThread()->ReadText(
496 ui::Clipboard::BUFFER_STANDARD, &text16);
497 return UTF16ToWide(text16);
500 void SetClipboardText(const std::wstring& text) {
501 ui::ScopedClipboardWriter clipboard_writer(
502 ui::Clipboard::GetForCurrentThread(),
503 ui::Clipboard::BUFFER_STANDARD);
504 clipboard_writer.WriteText(WideToUTF16(text));
507 bool AddCFMetaTag(std::string* html_data) {
508 if (!html_data) {
509 NOTREACHED();
510 return false;
512 std::string lower = StringToLowerASCII(*html_data);
513 size_t head = lower.find("<head>");
514 if (head == std::string::npos) {
515 // Add missing head section.
516 size_t html = lower.find("<html>");
517 if (html != std::string::npos) {
518 head = html + strlen("<html>");
519 html_data->insert(head, "<head></head>");
520 } else {
521 LOG(ERROR) << "Meta tag will not be injected "
522 << "because the html tag could not be found";
525 if (head != std::string::npos) {
526 html_data->insert(
527 head + strlen("<head>"),
528 "<meta http-equiv=\"x-ua-compatible\" content=\"chrome=1\" />");
530 return head != std::string::npos;
533 CloseIeAtEndOfScope::~CloseIeAtEndOfScope() {
534 int closed = CloseAllIEWindows();
535 LOG_IF(ERROR, closed != 0) << "Closed " << closed << " windows forcefully";
538 // Attempt to connect to a running crash_service instance. Success occurs if we
539 // can actually connect to the service's pipe or we receive ERROR_PIPE_BUSY.
540 // Waits up to |timeout_ms| for success. |timeout_ms| may be 0, meaning only try
541 // once, or negative, meaning wait forever.
542 bool DetectRunningCrashService(int timeout_ms) {
543 // Wait for the crash_service.exe to be ready for clients.
544 base::Time start = base::Time::Now();
545 base::win::ScopedHandle new_pipe;
547 while (true) {
548 new_pipe.Set(::CreateFile(kCrashServicePipeName,
549 kCrashServicePipeDesiredAccess,
550 0, // dwShareMode
551 NULL, // lpSecurityAttributes
552 OPEN_EXISTING,
553 kCrashServicePipeFlagsAndAttributes,
554 NULL)); // hTemplateFile
556 if (new_pipe.IsValid()) {
557 return true;
560 switch (::GetLastError()) {
561 case ERROR_PIPE_BUSY:
562 // OK, it exists, let's assume that clients will eventually be able to
563 // connect to it.
564 return true;
565 case ERROR_FILE_NOT_FOUND:
566 // Wait a bit longer
567 break;
568 default:
569 DPLOG(WARNING) << "Unexpected error while checking crash_service.exe's "
570 << "pipe.";
571 // Go ahead and wait in case it clears up.
572 break;
575 if (timeout_ms == 0) {
576 return false;
577 } else if (timeout_ms > 0) {
578 base::TimeDelta duration = base::Time::Now() - start;
579 if (duration.InMilliseconds() > timeout_ms) {
580 return false;
584 Sleep(10);
588 base::ProcessHandle StartCrashService() {
589 if (DetectRunningCrashService(kCrashServiceStartupTimeoutMs)) {
590 VLOG(1) << "crash_service.exe is already running. We will use the "
591 "existing process and leave it running after tests complete.";
592 return NULL;
595 FilePath exe_dir;
596 if (!PathService::Get(base::DIR_EXE, &exe_dir)) {
597 DCHECK(false);
598 return NULL;
601 base::ProcessHandle crash_service = NULL;
603 VLOG(1) << "Starting crash_service.exe so you know if a test crashes!";
605 FilePath crash_service_path = exe_dir.AppendASCII("crash_service.exe");
606 if (!base::LaunchProcess(crash_service_path.value(), base::LaunchOptions(),
607 &crash_service)) {
608 LOG(ERROR) << "Couldn't start crash_service.exe";
609 return NULL;
612 base::Time start = base::Time::Now();
614 if (DetectRunningCrashService(kCrashServiceStartupTimeoutMs)) {
615 VLOG(1) << "crash_service.exe is ready for clients in "
616 << (base::Time::Now() - start).InMilliseconds() << " ms.";
617 return crash_service;
618 } else {
619 LOG(ERROR) << "crash_service.exe failed to accept client connections "
620 "within " << kCrashServiceStartupTimeoutMs << " ms. "
621 "Terminating it now.";
623 // First check to see if it's even still running just to minimize the
624 // likelihood of spurious error messages from KillProcess.
625 if (WAIT_OBJECT_0 != ::WaitForSingleObject(crash_service, 0)) {
626 base::KillProcess(crash_service, 0, false);
628 return NULL;
632 ScopedVirtualizeHklmAndHkcu::ScopedVirtualizeHklmAndHkcu() {
633 override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, L"hklm_fake");
634 override_manager_.OverrideRegistry(HKEY_CURRENT_USER, L"hkcu_fake");
637 ScopedVirtualizeHklmAndHkcu::~ScopedVirtualizeHklmAndHkcu() {
640 void ScopedVirtualizeHklmAndHkcu::RemoveAllOverrides() {
641 override_manager_.RemoveAllOverrides();
644 bool KillProcesses(const std::wstring& executable_name, int exit_code,
645 bool wait) {
646 bool result = true;
647 base::NamedProcessIterator iter(executable_name, NULL);
648 while (const base::ProcessEntry* entry = iter.NextProcessEntry()) {
649 result &= base::KillProcessById(entry->pid(), exit_code, wait);
651 return result;
654 ScopedChromeFrameRegistrar::RegistrationType GetTestBedType() {
655 if (GetConfigBool(false, L"PerUserTestBed")) {
656 return ScopedChromeFrameRegistrar::PER_USER;
657 } else {
658 return ScopedChromeFrameRegistrar::SYSTEM_LEVEL;
662 void ClearIESessionHistory() {
663 FilePath session_history_path;
664 if (!PathService::Get(base::DIR_LOCAL_APP_DATA, &session_history_path))
665 return;
667 session_history_path = session_history_path.AppendASCII("Microsoft");
668 session_history_path = session_history_path.AppendASCII("Internet Explorer");
669 session_history_path = session_history_path.AppendASCII("Recovery");
670 file_util::Delete(session_history_path, true);
673 std::string GetLocalIPv4Address() {
674 std::string address;
675 net::NetworkInterfaceList nic_list;
677 if (!net::GetNetworkList(&nic_list)) {
678 LOG(ERROR) << "GetNetworkList failed to look up non-loopback adapters. "
679 << "Tests will be run over the loopback adapter, which may "
680 << "result in hangs.";
681 } else {
682 // GetNetworkList only returns 'Up' non-loopback adapters. Select the first
683 // IPv4 address found - we should be able to bind/connect over it.
684 for (size_t i = 0; i < nic_list.size(); ++i) {
685 if (nic_list[i].address.size() != net::kIPv4AddressSize)
686 continue;
687 char* address_string =
688 inet_ntoa(*reinterpret_cast<in_addr*>(&nic_list[i].address[0]));
689 DCHECK(address_string != NULL);
690 if (address_string != NULL) {
691 LOG(INFO) << "HTTP tests will run over " << address_string << ".";
692 address.assign(address_string);
693 break;
698 if (address.empty()) {
699 LOG(ERROR) << "Failed to find a non-loopback IP_V4 address. Tests will be "
700 << "run over the loopback adapter, which may result in hangs.";
701 address.assign("127.0.0.1");
704 return address;
707 } // namespace chrome_frame_test