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