chrome_frame_test_utils.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/test/chrome_frame_test_utils.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlapp.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlmisc.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iepmapi.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sddl.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlobj.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock2.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_version_info.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process_util.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths_internal.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/utils.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/clipboard/clipboard.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/clipboard/scoped_clipboard_writer.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome_frame_test {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kCrashServicePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const DWORD kCrashServicePipeDesiredAccess = FILE_READ_DATA |
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             FILE_WRITE_DATA |
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             FILE_WRITE_ATTRIBUTES;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const DWORD kCrashServicePipeFlagsAndAttributes = SECURITY_IDENTIFICATION |
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  SECURITY_SQOS_PRESENT;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kCrashServiceDetectTimeoutMs = 500;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kCrashServiceStartupTimeoutMs = 1000;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kIEImageName[] = L"iexplore.exe";
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kIEBrokerImageName[] = L"ieuser.exe";
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kChromeImageName[] = "chrome.exe";
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kIEProfileName[] = L"iexplore";
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromeLauncher[] = L"chrome_launcher.exe";
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const base::TimeDelta kChromeFrameLongNavigationTimeout =
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta::FromSeconds(30);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const base::TimeDelta kChromeFrameVeryLongNavigationTimeout =
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta::FromSeconds(90);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const base::TimeDelta kChromeFrameLongNavigationTimeout =
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta::FromSeconds(10);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const base::TimeDelta kChromeFrameVeryLongNavigationTimeout =
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta::FromSeconds(30);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callback function for EnumThreadWindows.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL CALLBACK CloseWindowsThreadCallback(HWND hwnd, LPARAM param) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int& count = *reinterpret_cast<int*>(param);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsWindowVisible(hwnd)) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsWindowEnabled(hwnd)) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DWORD results = 0;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!::SendMessageTimeout(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0, SMTO_BLOCK,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                10000, &results)) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Window hung: " << base::StringPrintf(L"%08X", hwnd);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count++;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Skipping disabled window: "
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << base::StringPrintf(L"%08X", hwnd);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRUE;  // continue enumeration
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Attempts to close all non-child, visible windows on the given thread.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The return value is the number of visible windows a close request was
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sent to.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CloseVisibleTopLevelWindowsOnThread(DWORD thread_id) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int window_close_attempts = 0;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumThreadWindows(thread_id, CloseWindowsThreadCallback,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    reinterpret_cast<LPARAM>(&window_close_attempts));
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return window_close_attempts;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Enumerates the threads of a process and attempts to close visible non-child
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// windows on all threads of the process.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The return value is the number of visible windows a close request was
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sent to.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CloseVisibleWindowsOnAllThreads(HANDLE process) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD process_id = ::GetProcessId(process);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (process_id == 0) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHandle snapshot(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!snapshot.IsValid()) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int window_close_attempts = 0;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  THREADENTRY32 te = { sizeof(THREADENTRY32) };
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (Thread32First(snapshot, &te)) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (RTL_CONTAINS_FIELD(&te, te.dwSize, th32OwnerProcessID) &&
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          te.th32OwnerProcessID == process_id) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_close_attempts +=
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            CloseVisibleTopLevelWindowsOnThread(te.th32ThreadID);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      te.dwSize = sizeof(te);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (Thread32Next(snapshot, &te));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return window_close_attempts;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetExecutableAppPath(const std::wstring& file) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring kAppPathsKey =
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\";
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring app_path;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::RegKey key(HKEY_LOCAL_MACHINE, (kAppPathsKey + file).c_str(),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        KEY_READ);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key.Handle()) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key.ReadValue(NULL, &app_path);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_path;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring FormatCommandForApp(const std::wstring& exe_name,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::wstring& argument) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring reg_path(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPrintf(L"Applications\\%ls\\shell\\open\\command",
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         exe_name.c_str()));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::RegKey key(HKEY_CLASSES_ROOT, reg_path.c_str(), KEY_READ);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring command;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key.Handle()) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key.ReadValue(NULL, &command);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int found = command.find(L"%1");
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found >= 0) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command.replace(found, 2, argument);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle LaunchExecutable(const std::wstring& executable,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const std::wstring& argument) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessHandle process = NULL;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring path = GetExecutableAppPath(executable);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path.empty()) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = FormatCommandForApp(executable, argument);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (path.empty()) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to find executable: " << executable;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine cmdline = CommandLine::FromString(path);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!base::LaunchProcess(cmdline, base::LaunchOptions(), &process)) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "LaunchProcess failed: " << ::GetLastError();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CommandLine cmdline((base::FilePath(path)));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmdline.AppendArgNative(argument);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!base::LaunchProcess(cmdline, base::LaunchOptions(), &process)) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "LaunchProcess failed: " << ::GetLastError();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle LaunchChrome(const std::wstring& url,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::FilePath& user_data_dir) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(base::DIR_MODULE, &path);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  path = path.AppendASCII(kChromeImageName);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine cmd(path);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd.AppendSwitch(switches::kNoFirstRun);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!user_data_dir.empty())
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd.AppendArgNative(url);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessHandle process = NULL;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::LaunchProcess(cmd, base::LaunchOptions(), &process);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle LaunchIEOnVista(const std::wstring& url) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef HRESULT (WINAPI* IELaunchURLPtr)(const wchar_t* url,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           PROCESS_INFORMATION* pi,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           VOID* info);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IELaunchURLPtr launch;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PROCESS_INFORMATION pi = {0};
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IELAUNCHURLINFO  info = {sizeof info, 0};
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE h = LoadLibrary(L"ieframe.dll");
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!h) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to load ieframe.dll: " << ::GetLastError();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  launch = reinterpret_cast<IELaunchURLPtr>(GetProcAddress(h, "IELaunchURL"));
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(launch);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = launch(url.c_str(), &pi, &info);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeLibrary(h);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SUCCEEDED(hr)) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseHandle(pi.hThread);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << base::StringPrintf("IELaunchURL failed: 0x%08X", hr);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pi.hProcess;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle LaunchIE(const std::wstring& url) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetInstalledIEVersion() >= IE_8) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome_frame_test::ClearIESessionHistory();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LaunchIEOnVista(url);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LaunchExecutable(kIEImageName, url);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TakeSnapshotAndLog() {
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::UnitTest* unit_test = testing::UnitTest::GetInstance();
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const testing::TestInfo* test_info = unit_test->current_test_info();
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string name;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (test_info != NULL) {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    name.append(test_info->test_case_name())
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .append(1, '.')
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .append(test_info->name());
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    name = "unknown test";
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath snapshot;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ui_test_utils::SaveScreenSnapshotToDesktop(&snapshot)) {
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Failed saving screen snapshot for " << name;
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LOG(ERROR) << "Saved screen snapshot for " << name << " to "
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << snapshot.value();
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CloseAllIEWindows() {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret = 0;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IShellWindows> windows;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = ::CoCreateInstance(__uuidof(ShellWindows), NULL, CLSCTX_ALL,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IID_IShellWindows, reinterpret_cast<void**>(windows.Receive()));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(SUCCEEDED(hr));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SUCCEEDED(hr)) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long count = 0;  // NOLINT
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    windows->get_Count(&count);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VARIANT i = { VT_I4 };
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i.lVal = 0; i.lVal < count; ++i.lVal) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::win::ScopedComPtr<IDispatch> folder;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windows->Item(i, folder.Receive());
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (folder != NULL) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::win::ScopedComPtr<IWebBrowser2> browser;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (SUCCEEDED(browser.QueryFrom(folder))) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          bool is_ie = true;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HWND window = NULL;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Check the class of the browser window to make sure we only close
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // IE windows.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (browser->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&window))) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            wchar_t class_name[MAX_PATH];
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (::GetClassName(window, class_name, arraysize(class_name))) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              is_ie = _wcsicmp(class_name, L"IEFrame") == 0;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (is_ie) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            browser->Quit();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ++ret;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LowIntegrityToken::LowIntegrityToken() : impersonated_(false) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LowIntegrityToken::~LowIntegrityToken() {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RevertToSelf();
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL LowIntegrityToken::RevertToSelf() {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL ok = TRUE;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (impersonated_) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(IsImpersonated());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = ::RevertToSelf();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      impersonated_ = false;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL LowIntegrityToken::Impersonate() {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!impersonated_);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsImpersonated());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE process_token_handle = NULL;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL ok = ::OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &process_token_handle);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "::OpenProcessToken failed: " << GetLastError();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ok;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHandle process_token(process_token_handle);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create impersonation low integrity token.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE impersonation_token_handle = NULL;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = ::DuplicateTokenEx(process_token,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, NULL,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SecurityImpersonation, TokenImpersonation, &impersonation_token_handle);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "::DuplicateTokenEx failed: " << GetLastError();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ok;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(stoyan): sandbox/win/src/restricted_token_utils.cc has
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetTokenIntegrityLevel function already.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHandle impersonation_token(impersonation_token_handle);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PSID integrity_sid = NULL;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TOKEN_MANDATORY_LABEL tml = {0};
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = ::ConvertStringSidToSid(SDDL_ML_LOW, &integrity_sid);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "::ConvertStringSidToSid failed: " << GetLastError();
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ok;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tml.Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tml.Label.Sid = integrity_sid;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = ::SetTokenInformation(impersonation_token, TokenIntegrityLevel,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &tml, sizeof(tml) + ::GetLengthSid(integrity_sid));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::LocalFree(integrity_sid);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "::SetTokenInformation failed: " << GetLastError();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ok;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switch current thread to low integrity.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = ::ImpersonateLoggedOnUser(impersonation_token);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    impersonated_ = true;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "::ImpersonateLoggedOnUser failed: " << GetLastError();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LowIntegrityToken::IsImpersonated() {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE token = NULL;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::OpenThreadToken(::GetCurrentThread(), 0, false, &token) &&
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ::GetLastError() != ERROR_NO_TOKEN) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (token)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(token);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!web_browser)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return E_INVALIDARG;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetInstalledIEVersion() >= IE_8) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome_frame_test::ClearIESessionHistory();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AllowSetForegroundWindow(ASFW_ANY);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = S_OK;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD cocreate_flags = CLSCTX_LOCAL_SERVER;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_frame_test::LowIntegrityToken token;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::IntegrityLevel integrity_level = base::INTEGRITY_UNKNOWN;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Vista has a bug which manifests itself when a medium integrity process
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // launches a COM server like IE which runs in protected mode due to UAC.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This causes the IWebBrowser2 interface which is returned to be useless,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // i.e it does not receive any events, etc. Our workaround for this is
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to impersonate a low integrity token and then launch IE.  Skip this if the
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tests are running at high integrity, since the workaround results in the
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // medium-integrity broker exiting, and the low-integrity IE is therefore
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unable to get chrome_launcher running at medium integrity.
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() == base::win::VERSION_VISTA &&
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetInstalledIEVersion() == IE_7 &&
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::GetProcessIntegrityLevel(base::Process::Current().handle(),
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &integrity_level) &&
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      integrity_level != base::HIGH_INTEGRITY) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create medium integrity browser that will launch IE broker.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::ScopedComPtr<IWebBrowser2> medium_integrity_browser;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hr = medium_integrity_browser.CreateInstance(CLSID_InternetExplorer, NULL,
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 CLSCTX_LOCAL_SERVER);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FAILED(hr))
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hr;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    medium_integrity_browser->Quit();
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Broker remains alive.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!token.Impersonate()) {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hr = HRESULT_FROM_WIN32(GetLastError());
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hr;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cocreate_flags |= CLSCTX_ENABLE_CLOAKING;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = ::CoCreateInstance(CLSID_InternetExplorer, NULL,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          cocreate_flags, IID_IWebBrowser2,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          reinterpret_cast<void**>(web_browser));
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ~LowIntegrityToken() will switch integrity back to medium.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetExeVersion(const std::wstring& exe_path) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<FileVersionInfo> ie_version_info(
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileVersionInfo::CreateFileVersionInfo(base::FilePath(exe_path)));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ie_version_info->product_version();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IEVersion GetInstalledIEVersion() {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring path(chrome_frame_test::GetExecutableAppPath(kIEImageName));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring version(GetExeVersion(path));
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t first_dot = version.find(L'.');
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int major_version = 0;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::StringToInt(base::StringPiece16(
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          version.data(),
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          first_dot == std::wstring::npos ? version.size() : first_dot),
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &major_version)) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return IE_UNSUPPORTED;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (major_version) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 6:
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return IE_6;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 7:
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return IE_7;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 8:
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return IE_8;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 9:
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return IE_9;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 10:
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return IE_10;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IE_UNSUPPORTED;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetProfilePathForIE() {
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath profile_path;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Browsers without IDeleteBrowsingHistory in non-priv mode
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have their profiles moved into "Temporary Internet Files".
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The code below basically retrieves the version of IE and computes
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the profile directory accordingly.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetInstalledIEVersion() <= IE_7) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_path = GetIETemporaryFilesFolder();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_path = profile_path.Append(L"Google Chrome Frame");
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetChromeFrameProfilePath(kIEProfileName, &profile_path);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return profile_path;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetTestDataFolder() {
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath test_dir;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_dir = test_dir.Append(FILE_PATH_LITERAL("chrome_frame"))
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append(FILE_PATH_LITERAL("test"))
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append(FILE_PATH_LITERAL("data"));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return test_dir;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetSeleniumTestFolder() {
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath test_dir;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_dir = test_dir.Append(FILE_PATH_LITERAL("data"))
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append(FILE_PATH_LITERAL("selenium_core"));
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return test_dir;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetPathFromUrl(const std::wstring& url) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 url16 = WideToUTF16(url);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL gurl = GURL(url16);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gurl.has_query()) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL::Replacements replacements;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    replacements.ClearQuery();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gurl = gurl.ReplaceComponents(replacements);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UTF8ToWide(gurl.PathForRequest());
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetPathAndQueryFromUrl(const std::wstring& url) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 url16 = WideToUTF16(url);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL gurl = GURL(url16);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UTF8ToWide(gurl.PathForRequest());
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring GetClipboardText() {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 text16;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::Clipboard::GetForCurrentThread()->ReadText(
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::Clipboard::BUFFER_STANDARD, &text16);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UTF16ToWide(text16);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetClipboardText(const std::wstring& text) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::ScopedClipboardWriter clipboard_writer(
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::Clipboard::GetForCurrentThread(),
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::Clipboard::BUFFER_STANDARD);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard_writer.WriteText(WideToUTF16(text));
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AddCFMetaTag(std::string* html_data) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!html_data) {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string lower = StringToLowerASCII(*html_data);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t head = lower.find("<head>");
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (head == std::string::npos) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add missing head section.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t html = lower.find("<html>");
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (html != std::string::npos) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      head = html + strlen("<html>");
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      html_data->insert(head, "<head></head>");
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Meta tag will not be injected "
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << "because the html tag could not be found";
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (head != std::string::npos) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html_data->insert(
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        head + strlen("<head>"),
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "<meta http-equiv=\"x-ua-compatible\" content=\"chrome=1\" />");
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return head != std::string::npos;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloseIeAtEndOfScope::~CloseIeAtEndOfScope() {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int closed = CloseAllIEWindows();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, closed != 0) << "Closed " << closed << " windows forcefully";
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Attempt to connect to a running crash_service instance. Success occurs if we
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can actually connect to the service's pipe or we receive ERROR_PIPE_BUSY.
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Waits up to |timeout_ms| for success. |timeout_ms| may be 0, meaning only try
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// once, or negative, meaning wait forever.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DetectRunningCrashService(int timeout_ms) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the crash_service.exe to be ready for clients.
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time start = base::Time::Now();
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHandle new_pipe;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_pipe.Set(::CreateFile(kCrashServicePipeName,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              kCrashServicePipeDesiredAccess,
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0,  // dwShareMode
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              NULL,  // lpSecurityAttributes
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              OPEN_EXISTING,
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              kCrashServicePipeFlagsAndAttributes,
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              NULL));  // hTemplateFile
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_pipe.IsValid()) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (::GetLastError()) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ERROR_PIPE_BUSY:
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // OK, it exists, let's assume that clients will eventually be able to
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // connect to it.
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ERROR_FILE_NOT_FOUND:
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Wait a bit longer
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DPLOG(WARNING) << "Unexpected error while checking crash_service.exe's "
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       << "pipe.";
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Go ahead and wait in case it clears up.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (timeout_ms == 0) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (timeout_ms > 0) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta duration = base::Time::Now() - start;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (duration.InMilliseconds() > timeout_ms) {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Sleep(10);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle StartCrashService() {
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (DetectRunningCrashService(kCrashServiceDetectTimeoutMs)) {
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "crash_service.exe is already running. We will use the "
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "existing process and leave it running after tests complete.";
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath exe_dir;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PathService::Get(base::DIR_EXE, &exe_dir)) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(false);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessHandle crash_service = NULL;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Starting crash_service.exe so you know if a test crashes!";
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath crash_service_path = exe_dir.AppendASCII("crash_service.exe");
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::LaunchProcess(crash_service_path.value(), base::LaunchOptions(),
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &crash_service)) {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Couldn't start crash_service.exe";
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time start = base::Time::Now();
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (DetectRunningCrashService(kCrashServiceStartupTimeoutMs)) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "crash_service.exe is ready for clients in "
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << (base::Time::Now() - start).InMilliseconds() << " ms.";
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return crash_service;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "crash_service.exe failed to accept client connections "
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "within " << kCrashServiceStartupTimeoutMs << " ms. "
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "Terminating it now.";
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First check to see if it's even still running just to minimize the
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // likelihood of spurious error messages from KillProcess.
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (WAIT_OBJECT_0 != ::WaitForSingleObject(crash_service, 0)) {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::KillProcess(crash_service, 0, false);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVirtualizeHklmAndHkcu::ScopedVirtualizeHklmAndHkcu() {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, L"hklm_fake");
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  override_manager_.OverrideRegistry(HKEY_CURRENT_USER, L"hkcu_fake");
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVirtualizeHklmAndHkcu::~ScopedVirtualizeHklmAndHkcu() {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVirtualizeHklmAndHkcu::RemoveAllOverrides() {
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  override_manager_.RemoveAllOverrides();
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KillProcesses(const std::wstring& executable_name, int exit_code,
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   bool wait) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = true;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::NamedProcessIterator iter(executable_name, NULL);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (const base::ProcessEntry* entry = iter.NextProcessEntry()) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result &= base::KillProcessById(entry->pid(), exit_code, wait);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedChromeFrameRegistrar::RegistrationType GetTestBedType() {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetConfigBool(false, L"PerUserTestBed")) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ScopedChromeFrameRegistrar::PER_USER;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ScopedChromeFrameRegistrar::SYSTEM_LEVEL;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearIESessionHistory() {
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath session_history_path;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PathService::Get(base::DIR_LOCAL_APP_DATA, &session_history_path))
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_history_path = session_history_path.AppendASCII("Microsoft");
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_history_path = session_history_path.AppendASCII("Internet Explorer");
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_history_path = session_history_path.AppendASCII("Recovery");
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::Delete(session_history_path, true);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetLocalIPv4Address() {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string address;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkInterfaceList nic_list;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net::GetNetworkList(&nic_list)) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "GetNetworkList failed to look up non-loopback adapters. "
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "Tests will be run over the loopback adapter, which may "
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "result in hangs.";
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // GetNetworkList only returns 'Up' non-loopback adapters. Select the first
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // IPv4 address found - we should be able to bind/connect over it.
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < nic_list.size(); ++i) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (nic_list[i].address.size() != net::kIPv4AddressSize)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char* address_string =
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          inet_ntoa(*reinterpret_cast<in_addr*>(&nic_list[i].address[0]));
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(address_string != NULL);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (address_string != NULL) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(INFO) << "HTTP tests will run over " << address_string << ".";
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        address.assign(address_string);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address.empty()) {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to find a non-loopback IP_V4 address. Tests will be "
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "run over the loopback adapter, which may result in hangs.";
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    address.assign("127.0.0.1");
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return address;
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome_frame_test
743