// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "BrowserFactory.h"

#include <ctime>
#include <vector>

#include <exdispid.h>
#include <iepmapi.h>
#include <psapi.h>
#include <sddl.h>
#include <shlguid.h>
#include <shlobj.h>

#include "logging.h"

#include "FileUtilities.h"
#include "RegistryUtilities.h"
#include "StringUtilities.h"
#include "WebDriverConstants.h"

#define HTML_GETOBJECT_MSG L"WM_HTML_GETOBJECT"
#define OLEACC_LIBRARY_NAME L"OLEACC.DLL"
#define IEFRAME_LIBRARY_NAME L"ieframe.dll"
#define IELAUNCHURL_FUNCTION_NAME "IELaunchURL"

#define IE_FRAME_WINDOW_CLASS "IEFrame"
#define SHELL_DOCOBJECT_VIEW_WINDOW_CLASS "Shell DocObject View"
#define IE_SERVER_CHILD_WINDOW_CLASS "Internet Explorer_Server"
#define ANDIE_FRAME_WINDOW_CLASS "Chrome_WidgetWin_1"

#define EDGE_REGISTRY_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\msedge.exe"
#define IE_CLSID_REGISTRY_KEY L"SOFTWARE\\Classes\\InternetExplorer.Application\\CLSID"
#define IE_REDIRECT L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Ext\\CLSID"
#define IE_SECURITY_ZONES_REGISTRY_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones"
#define IE_TABPROCGROWTH_REGISTRY_KEY L"Software\\Microsoft\\Internet Explorer\\Main"

#define IE_PROTECTED_MODE_SETTING_VALUE_NAME L"2500"

#define IELAUNCHURL_ERROR_MESSAGE "IELaunchURL() returned HRESULT %X ('%s') for URL '%s'"
#define CREATEPROCESS_ERROR_MESSAGE "CreateProcess() failed for command line '%s'"
#define CREATEPROCESS_EDGE_ERROR "CreateProcess() failed for edge with the following command: "
#define NULL_PROCESS_ID_ERROR_MESSAGE " successfully launched Internet Explorer, but did not return a valid process ID."
#define PROTECTED_MODE_SETTING_ERROR_MESSAGE "Protected Mode settings are not the same for all zones. Enable Protected Mode must be set to the same value (enabled or disabled) for all zones."
#define ZOOM_SETTING_ERROR_MESSAGE "Browser zoom level was set to %d%%. It should be set to 100%%"
#define ATTACH_TIMEOUT_ERROR_MESSAGE "Could not find an Internet Explorer window belonging to the process with ID %d within %d milliseconds."
#define ATTACH_FAILURE_ERROR_MESSAGE "Found browser window using ShellWindows API, but could not attach to the browser IWebBrowser2 object."
#define CREATEPROCESS_REGISTRY_ERROR_MESSAGE "Unable to use CreateProcess() API. To use CreateProcess() with Internet Explorer 8 or higher, the value of registry setting in HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main\\TabProcGrowth must be '0'."

#define ZONE_MY_COMPUTER L"0"
#define ZONE_LOCAL_INTRANET L"1"
#define ZONE_TRUSTED_SITES L"2"
#define ZONE_INTERNET L"3"
#define ZONE_RESTRICTED_SITES L"4"

#define IELAUNCHURL_API L"ielaunchurl"
#define CREATEPROCESS_API L"createprocess"

#define RUNDLL_EXE_NAME L"rundll32.exe"
#define INTERNET_CONTROL_PANEL_APPLET_NAME L"inetcpl.cpl"
#define CLEAR_CACHE_COMMAND_LINE_ARGS L"rundll32.exe %s,ClearMyTracksByProcess %u"
// This magic value is the combination of the following bitflags:
// #define CLEAR_HISTORY         0x0001 // Clears history
// #define CLEAR_COOKIES         0x0002 // Clears cookies
// #define CLEAR_CACHE           0x0004 // Clears Temporary Internet Files folder
// #define CLEAR_CACHE_ALL       0x0008 // Clears offline favorites and download history
// #define CLEAR_FORM_DATA       0x0010 // Clears saved form data for form auto-fill-in
// #define CLEAR_PASSWORDS       0x0020 // Clears passwords saved for websites
// #define CLEAR_PHISHING_FILTER 0x0040 // Clears phishing filter data
// #define CLEAR_RECOVERY_DATA   0x0080 // Clears webpage recovery data
// #define CLEAR_PRIVACY_ADVISOR 0x0800 // Clears tracking data
// #define CLEAR_SHOW_NO_GUI     0x0100 // Do not show a GUI when running the cache clearing
//
// Bitflags available but not used in this magic value are as follows:
// #define CLEAR_USE_NO_THREAD      0x0200 // Do not use multithreading for deletion
// #define CLEAR_PRIVATE_CACHE      0x0400 // Valid only when browser is in private browsing mode
// #define CLEAR_DELETE_ALL         0x1000 // Deletes data stored by add-ons
// #define CLEAR_PRESERVE_FAVORITES 0x2000 // Preserves cached data for "favorite" websites
#define CLEAR_CACHE_OPTIONS 0x09FF

namespace webdriver {

BrowserFactory::BrowserFactory(void) {
  // Must be done in the constructor. Do not move to Initialize().
  this->GetEdgeExecutableLocation();
  this->GetIEExecutableLocation();
  this->GetIEVersion();
  this->oleacc_instance_handle_ = NULL;
  this->edge_ie_mode_ = false;
  this->ignore_process_match_ = false;
}

BrowserFactory::~BrowserFactory(void) {
  if (this->oleacc_instance_handle_) {
    ::FreeLibrary(this->oleacc_instance_handle_);
  }
}

std::string BrowserFactory::initial_browser_url(void) {
  return StringUtilities::ToString(this->initial_browser_url_);
}

std::string BrowserFactory::browser_command_line_switches(void) {
  return StringUtilities::ToString(this->browser_command_line_switches_);
}

void BrowserFactory::Initialize(BrowserFactorySettings settings) {
  LOG(TRACE) << "Entering BrowserFactory::Initialize";
  this->ignore_protected_mode_settings_ = settings.ignore_protected_mode_settings;
  this->browser_attach_timeout_ = settings.browser_attach_timeout;
  this->force_createprocess_api_ = settings.force_create_process_api;
  this->force_shell_windows_api_ = settings.force_shell_windows_api;
  this->clear_cache_ = settings.clear_cache_before_launch;
  this->browser_command_line_switches_ = StringUtilities::ToWString(settings.browser_command_line_switches);
  this->initial_browser_url_ = StringUtilities::ToWString(settings.initial_browser_url);
  this->edge_ie_mode_ = settings.attach_to_edge_ie || this->ie_redirects_edge_;
  this->ignore_process_match_ = settings.ignore_process_match;
  this->ignore_zoom_setting_ = settings.ignore_zoom_setting || this->edge_ie_mode_;
  LOG(DEBUG) << "path before was " << settings.edge_executable_path << "\n";
  this->edge_executable_location_ = StringUtilities::ToWString(settings.edge_executable_path);
  LOG(DEBUG) << "path after was " << StringUtilities::ToString(this->edge_executable_location_) << "\n";
  this->html_getobject_msg_ = ::RegisterWindowMessage(HTML_GETOBJECT_MSG);

  // Explicitly load MSAA so we know if it's installed
  this->oleacc_instance_handle_ = ::LoadLibrary(OLEACC_LIBRARY_NAME);
}

void BrowserFactory::ClearCache() {
  LOG(TRACE) << "Entering BrowserFactory::ClearCache";
  if (this->clear_cache_) {
    if (IsWindowsVistaOrGreater()) {
      LOG(DEBUG) << "Clearing cache with low mandatory integrity level as required on Windows Vista or later.";
      this->InvokeClearCacheUtility(true);
    }
    LOG(DEBUG) << "Clearing cache with normal process execution.";
    this->InvokeClearCacheUtility(false);
  }
}

DWORD BrowserFactory::LaunchBrowserProcess(std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::LaunchBrowserProcess";

  DWORD process_id = NULL;
  bool has_valid_protected_mode_settings = false;
  LOG(DEBUG) << "Ignoring Protected Mode Settings: "
             << this->ignore_protected_mode_settings_;
  if (!this->ignore_protected_mode_settings_) {
    LOG(DEBUG) << "Checking validity of Protected Mode settings.";
    has_valid_protected_mode_settings = this->ProtectedModeSettingsAreValid();
  }
  LOG(DEBUG) << "Has Valid Protected Mode Settings: "
             << has_valid_protected_mode_settings;
  if (this->ignore_protected_mode_settings_ || has_valid_protected_mode_settings) {
    // Determine which launch API to use.
    bool use_createprocess_api = false;
    if (this->force_createprocess_api_) {
      if (this->IsCreateProcessApiAvailable()) {
        use_createprocess_api = true;
      } else {
        // The only time IsCreateProcessApiAvailable will return false
        // is when the user is using IE 8 or higher, and does not have
        // the correct registry key setting to force the same process
        // for the enclosing window and tab processes.
        *error_message = CREATEPROCESS_REGISTRY_ERROR_MESSAGE;
        return NULL;
      }
    } else {
      // If we have the IELaunchURL API, expressly use it. Otherwise,
      // fall back to using CreateProcess().
      if (!this->IsIELaunchURLAvailable()) {
        use_createprocess_api = true;
      }
    }

    this->ClearCache();

    PROCESS_INFORMATION proc_info;
    ::ZeroMemory(&proc_info, sizeof(proc_info));

    if (this->edge_ie_mode_) {
      this->LaunchEdgeInIEMode(&proc_info, error_message);
    } else if (!use_createprocess_api) {
      this->LaunchBrowserUsingIELaunchURL(&proc_info, error_message);
    } else {
      this->LaunchBrowserUsingCreateProcess(&proc_info, error_message);
    }

    process_id = proc_info.dwProcessId;
    if (process_id == NULL) {
      // If whatever API we are using failed to launch the browser, we should
      // have a NULL value in the dwProcessId member of the PROCESS_INFORMATION
      // structure. In that case, we will have already set the approprate error
      // message. On the off chance that we haven't yet set the appropriate
      // error message, that means we successfully launched the browser (i.e.,
      // the browser launch API returned a success code), but we still have a
      // NULL process ID.
      if (error_message->size() == 0) {
        std::string launch_api_name = use_createprocess_api ? "The CreateProcess API" : "The IELaunchURL API";
        *error_message = launch_api_name + NULL_PROCESS_ID_ERROR_MESSAGE;
      }
    } else {
      ::WaitForInputIdle(proc_info.hProcess, 2000);
      std::string browser_launched = this->edge_ie_mode_ ? "Edge in IE Mode" : "IE";
      LOG(DEBUG) << browser_launched << " launched successfully with process ID " << process_id;
      std::vector<wchar_t> image_buffer(MAX_PATH);
      int buffer_count = ::GetProcessImageFileName(proc_info.hProcess, &image_buffer[0], MAX_PATH);
      std::wstring full_image_path = &image_buffer[0];
      size_t last_delimiter = full_image_path.find_last_of('\\');
      std::string image_name = StringUtilities::ToString(full_image_path.substr(last_delimiter + 1, buffer_count - last_delimiter));
      LOG(DEBUG) << "Process with ID " << process_id << " is executing " << image_name;
    }

    if (proc_info.hThread != NULL) {
      ::CloseHandle(proc_info.hThread);
    }

    if (proc_info.hProcess != NULL) {
      ::CloseHandle(proc_info.hProcess);
    }

  } else {
    *error_message = PROTECTED_MODE_SETTING_ERROR_MESSAGE;
  }
  return process_id;
}

bool BrowserFactory::IsIELaunchURLAvailable() {
  LOG(TRACE) << "Entering BrowserFactory::IsIELaunchURLAvailable";
  bool api_is_available = false;
  HMODULE library_handle = ::LoadLibrary(IEFRAME_LIBRARY_NAME);
  if (library_handle != NULL) {
    FARPROC proc_address = 0;
    proc_address = ::GetProcAddress(library_handle, IELAUNCHURL_FUNCTION_NAME);
    if (proc_address == NULL || proc_address == 0) {
      LOGERR(DEBUG) << "Unable to get address of " << IELAUNCHURL_FUNCTION_NAME
                    << " method in " << IEFRAME_LIBRARY_NAME;
    } else {
      api_is_available = true;
    }
    ::FreeLibrary(library_handle);
  } else {
    LOGERR(DEBUG) << "Unable to load library " << IEFRAME_LIBRARY_NAME;
  }
  return api_is_available;
}

void BrowserFactory::LaunchBrowserUsingIELaunchURL(PROCESS_INFORMATION* proc_info,
                                                   std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::LaunchBrowserUsingIELaunchURL";
  LOG(DEBUG) << "Starting IE using the IELaunchURL API";
  HRESULT launch_result = ::IELaunchURL(this->initial_browser_url_.c_str(),
                                        proc_info,
                                        NULL);
  if (FAILED(launch_result)) {
    LOGHR(WARN, launch_result) << "Error using IELaunchURL to start IE";
    std::wstring hresult_msg = _com_error(launch_result).ErrorMessage();
    *error_message = StringUtilities::Format(IELAUNCHURL_ERROR_MESSAGE,
                                             launch_result,
                                             StringUtilities::ToString(hresult_msg).c_str(),
                                             this->initial_browser_url().c_str());
  }
}

bool BrowserFactory::IsCreateProcessApiAvailable() {
  LOG(TRACE) << "Entering BrowserFactory::IsCreateProcessApiAvailable";
  if (this->ie_major_version_ >= 8) {
    // According to http://blogs.msdn.com/b/askie/archive/2009/03/09/opening-a-new-tab-may-launch-a-new-process-with-internet-explorer-8-0.aspx
    // If CreateProcess() is used and TabProcGrowth != 0 IE will use different tab and frame processes.
    // Such behaviour is not supported by AttachToBrowser().
    // FYI, IELaunchURL() returns correct 'frame' process (but sometimes not).
    std::wstring tab_proc_growth;
    if (RegistryUtilities::GetRegistryValue(HKEY_CURRENT_USER,
                                            IE_TABPROCGROWTH_REGISTRY_KEY,
                                            L"TabProcGrowth",
                                            &tab_proc_growth)) {
      if (tab_proc_growth != L"0") {
        // Registry value has wrong value, return false
        return false;
      }
    } else {
      // Registry key or value not found, or another error condition getting the value.
      return false;
    }
  }
  return true;
}

void BrowserFactory::LaunchBrowserUsingCreateProcess(PROCESS_INFORMATION* proc_info,
                                                     std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::LaunchBrowserUsingCreateProcess";
  LOG(DEBUG) << "Starting IE using the CreateProcess API";

  STARTUPINFO start_info;
  ::ZeroMemory(&start_info, sizeof(start_info));
  start_info.cb = sizeof(start_info);

  std::wstring executable_and_url = this->ie_executable_location_;
  if (this->browser_command_line_switches_.size() != 0) {
    executable_and_url.append(L" ");
    executable_and_url.append(this->browser_command_line_switches_);
  }
  executable_and_url.append(L" ");
  executable_and_url.append(this->initial_browser_url_);

  LOG(TRACE) << "IE starting command line is: '"
             << LOGWSTRING(executable_and_url) << "'.";

  LPWSTR command_line = new WCHAR[executable_and_url.size() + 1];
  wcscpy_s(command_line,
           executable_and_url.size() + 1,
           executable_and_url.c_str());
  command_line[executable_and_url.size()] = L'\0';
  BOOL create_process_result = ::CreateProcess(NULL,
                                               command_line,
                                               NULL,
                                               NULL,
                                               FALSE,
                                               0,
                                               NULL,
                                               NULL,
                                               &start_info,
                                               proc_info);
  if (!create_process_result) {
    *error_message = StringUtilities::Format(CREATEPROCESS_ERROR_MESSAGE,
                                             StringUtilities::ToString(command_line));
  }
  delete[] command_line;
}

bool BrowserFactory::DirectoryExists(std::wstring& dir_name) {
  DWORD attribs = ::GetFileAttributes(dir_name.c_str());
  if (attribs == INVALID_FILE_ATTRIBUTES) {
    return false;
  }
  return (attribs & FILE_ATTRIBUTE_DIRECTORY);
}

bool BrowserFactory::CreateUniqueTempDir(std::wstring &temp_dir) {
  // get temporary folder for the current user
  wchar_t temp_path_array[128];
  ::GetTempPath(128, temp_path_array);
  std::wstring temp_path = temp_path_array;
  if (!DirectoryExists(temp_path)) {
    return false;
  }

  // create a IEDriver temporary folder inside the user level temporary folder
  bool temp_dir_created = false;
  for (int i = 0; i < 10; i++) {
    std::wstring output =
        temp_path + L"IEDriver-" + StringUtilities::CreateGuid();
    if (DirectoryExists(output)) {
      continue;
    }

    ::CreateDirectory(output.c_str(), NULL);
    if (!DirectoryExists(output)) {
      continue;
    }

    temp_dir = output;
    temp_dir_created = true;
    break;
  }

  return temp_dir_created;
}

void BrowserFactory::LaunchEdgeInIEMode(PROCESS_INFORMATION* proc_info,
                                        std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::LaunchEdgeInIEMode";
  LOG(DEBUG) << "Starting Edge Chromium from the command line";

  STARTUPINFO start_info;
  ::ZeroMemory(&start_info, sizeof(start_info));
  start_info.cb = sizeof(start_info);

  std::wstring executable_and_url = this->edge_executable_location_;
  if (executable_and_url == L"") {
    executable_and_url = this->edge_executable_located_location_; // Locate Edge via Registry if not passed
    if (executable_and_url == L"") {
      executable_and_url = L"msedge.exe"; // Assume it's on the path
    }
  }

  // These flags force Edge into a mode where it will only run MSHTML
  executable_and_url.append(L" --ie-mode-force");
  executable_and_url.append(L" --internet-explorer-integration=iemode");

  // create a temporary directory for IEDriver test
  std::wstring temp_dir;
  if (CreateUniqueTempDir(temp_dir)) {
    LOG(TRACE) << L"Using temporary folder " << LOGWSTRING(temp_dir) << ".";
    executable_and_url.append(L" --user-data-dir=" + temp_dir);
    this->edge_user_data_dir_ = temp_dir;
  }

  // Prevent Edge from showing first run experience tab.
  executable_and_url.append(L" --no-first-run");

  // Disable Edge prelaunch and other background processes on startup.
  executable_and_url.append(L" --no-service-autorun");

  // Disable profile sync and implicit MS account sign-in.
  executable_and_url.append(L" --disable-sync");
  executable_and_url.append(L" --disable-features=msImplicitSignin");

  // ALways allow popups for testing.
  executable_and_url.append(L" --disable-popup-blocking");

  // Ensure IE Mode tabs have a chance to shut down cleanly before the Edge process exits.
  executable_and_url.append(L" --enable-features=msIEModeAlwaysWaitForUnload");

  executable_and_url.append(L" ");
  executable_and_url.append(this->initial_browser_url_);

  LOG(TRACE) << "Edge in IE Mode starting command line is: '"
             << LOGWSTRING(executable_and_url) << "'.";

  LPWSTR command_line = new WCHAR[executable_and_url.size() + 1];
  wcscpy_s(command_line,
           executable_and_url.size() + 1,
           executable_and_url.c_str());
  command_line[executable_and_url.size()] = L'\0';
  BOOL create_process_result = ::CreateProcess(NULL,
                                               command_line,
                                               NULL,
                                               NULL,
                                               FALSE,
                                               0,
                                               NULL,
                                               NULL,
                                               &start_info,
                                               proc_info);


  if (!create_process_result) {
    *error_message = CREATEPROCESS_EDGE_ERROR + StringUtilities::ToString(command_line);
  }

  delete[] command_line;
}


bool BrowserFactory::GetDocumentFromWindowHandle(HWND window_handle,
                                                 IHTMLDocument2** document) {
  LOG(TRACE) << "Entering BrowserFactory::GetDocumentFromWindowHandle";

  if (window_handle != NULL && this->oleacc_instance_handle_) {
    LRESULT result;

    ::SendMessageTimeout(window_handle,
                         this->html_getobject_msg_,
                         0L,
                         0L,
                         SMTO_ABORTIFHUNG,
                         1000,
                         reinterpret_cast<PDWORD_PTR>(&result));

    LPFNOBJECTFROMLRESULT object_pointer = reinterpret_cast<LPFNOBJECTFROMLRESULT>(::GetProcAddress(this->oleacc_instance_handle_, "ObjectFromLresult"));
    if (object_pointer != NULL) {
      HRESULT hr;
      hr = (*object_pointer)(result,
                             IID_IHTMLDocument2,
                             0,
                             reinterpret_cast<void**>(document));
      if (SUCCEEDED(hr)) {
        return true;
      } else {
        LOGHR(WARN, hr) << "Unable to convert document object pointer to IHTMLDocument2 object via ObjectFromLresult";
      }
    } else {
      LOG(WARN) << "Unable to get address of ObjectFromLresult method from library; GetProcAddress() for ObjectFromLresult returned NULL";
    }
  } else {
    LOG(WARN) << "Window handle is invalid or OLEACC.DLL is not loaded properly";
  }
  return false;
}

bool BrowserFactory::AttachToBrowser(ProcessWindowInfo* process_window_info,
                                     std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::AttachToBrowser";
  bool attached = false;

  // Attempt to attach to the browser using ActiveAccessibility API
  // first, if this fails fallback to using ShellWindows API.
  // ActiveAccessibility fails if the Windows Desktop runs out of
  // free space for GlobalAtoms.
  // ShellWindows might fail if there is an IE modal dialog blocking
  // execution (unverified).
  if (!this->force_shell_windows_api_) {
    LOG(DEBUG) << "Using Active Accessibility to find IWebBrowser2 interface";
    attached = this->AttachToBrowserUsingActiveAccessibility(process_window_info,
                                                             error_message);
    if (!attached) {
      LOG(DEBUG) << "Failed to find IWebBrowser2 using ActiveAccessibility: "
                 << *error_message;
      // Reset the browser window handle to NULL, since we didn't attach
      // using Active Accessibility.
      process_window_info->hwndBrowser = NULL;
    }
  }

  if (!attached) {
    LOG(DEBUG) << "Using IShellWindows to find IWebBrowser2 interface";
    attached = this->AttachToBrowserUsingShellWindows(process_window_info,
                                                      error_message);
  }

  if (attached) {
    // Test for zoom level = 100%
    int zoom_level = 100;
    LOG(DEBUG) << "Ignoring zoom setting: " << this->ignore_zoom_setting_;
    if (!this->ignore_zoom_setting_) {
      zoom_level = this->GetBrowserZoomLevel(process_window_info->pBrowser);
    }
    if (zoom_level != 100) {
      std::string zoom_level_error =
          StringUtilities::Format(ZOOM_SETTING_ERROR_MESSAGE, zoom_level);
      LOG(WARN) << zoom_level_error;
      *error_message = zoom_level_error;
      return false;
    }
  }
  return attached;
}


bool BrowserFactory::IsBrowserProcessInitialized(DWORD process_id) {
  ProcessWindowInfo info;
  info.dwProcessId = process_id;
  info.hwndBrowser = NULL;
  info.pBrowser = NULL;

  ::EnumWindows(&BrowserFactory::FindBrowserWindow,
                reinterpret_cast<LPARAM>(&info));
  return info.hwndBrowser != NULL;
}

bool BrowserFactory::AttachToBrowserUsingActiveAccessibility
                                    (ProcessWindowInfo* process_window_info,
                                     std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::AttachToBrowserUsingActiveAccessibility";

  clock_t end = clock() + (this->browser_attach_timeout_ / 1000 * CLOCKS_PER_SEC);
  while (process_window_info->hwndBrowser == NULL) {
    if (this->browser_attach_timeout_ > 0 && (clock() > end)) {
      break;
    }
    if (!this->edge_ie_mode_) {
      ::EnumWindows(&BrowserFactory::FindBrowserWindow,
                    reinterpret_cast<LPARAM>(process_window_info));
    } else {
      // If we're in edge_ie_mode, we need to look for different windows
      if (this->ignore_process_match_) {
        LOG(TRACE) << "Finding window handle for IE Mode on Edge, "
                   << "ignoring process id match. This assumes only one "
                   << "Edge instance is running on the host.";
        ::EnumWindows(&BrowserFactory::FindEdgeWindowIgnoringProcessMatch,
                      reinterpret_cast<LPARAM>(process_window_info));
      } else {
        LOG(TRACE) << "Finding window handle for IE Mode on Edge";
        ::EnumWindows(&BrowserFactory::FindEdgeWindow,
                    reinterpret_cast<LPARAM>(process_window_info));

      }
    }

    if (process_window_info->hwndBrowser == NULL) {
      ::Sleep(250);
    }
  }

  if (process_window_info->hwndBrowser == NULL) {
    *error_message = StringUtilities::Format(ATTACH_TIMEOUT_ERROR_MESSAGE,
                                             process_window_info->dwProcessId,
                                             this->browser_attach_timeout_);
    return false;
  } else {
    LOG(DEBUG) << "Found window handle " << process_window_info->hwndBrowser
               << " for window with class 'Internet Explorer_Server' belonging"
               << " to process with id " << process_window_info->dwProcessId;
  }

  CComPtr<IHTMLDocument2> document;
  if (this->GetDocumentFromWindowHandle(process_window_info->hwndBrowser,
                                        &document)) {
    int get_parent_window_retry_count = 8;
    CComPtr<IHTMLWindow2> window;
    HRESULT hr = document->get_parentWindow(&window);
    while (FAILED(hr) && get_parent_window_retry_count > 0) {
      // We know we have a valid document. We *should* be able to do a
      // document.parentWindow call to get the window. However, on the off-
      // chance that the document exists, but IE is slow to initialize all
      // of the COM objects and the full DOM, we'll sleep up to 2 seconds,
      // retrying to get the parent window.
      ::Sleep(250);
      hr = document->get_parentWindow(&window);
      --get_parent_window_retry_count;
    }
    if (SUCCEEDED(hr)) {
      // http://support.microsoft.com/kb/257717
      CComPtr<IServiceProvider> provider;
      window->QueryInterface<IServiceProvider>(&provider);
      if (provider) {
        CComPtr<IServiceProvider> child_provider;
        hr = provider->QueryService(SID_STopLevelBrowser,
                                    IID_IServiceProvider,
                                    reinterpret_cast<void**>(&child_provider));
        if (SUCCEEDED(hr)) {
          CComPtr<IWebBrowser2> browser;
          hr = child_provider->QueryService(SID_SWebBrowserApp,
                                            IID_IWebBrowser2,
                                            reinterpret_cast<void**>(&browser));
          if (SUCCEEDED(hr)) {
            process_window_info->pBrowser = browser.Detach();
            return true;
          } else {
            LOGHR(WARN, hr) << "IServiceProvider::QueryService for SID_SWebBrowserApp failed";
          }
        } else {
          LOGHR(WARN, hr) << "IServiceProvider::QueryService for SID_STopLevelBrowser failed";
        }
      } else {
        LOG(WARN) << "QueryInterface for IServiceProvider failed";
      }
    } else {
      LOGHR(WARN, hr) << "Call to IHTMLDocument2::get_parentWindow failed";
    }
  } else {
    *error_message = "Could not get document from window handle";
  }
  return false;
}

bool BrowserFactory::AttachToBrowserUsingShellWindows(
                                     ProcessWindowInfo* process_window_info,
                                     std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::AttachToBrowserUsingShellWindows";

  CComPtr<IShellWindows> shell_windows;
  HRESULT hr = shell_windows.CoCreateInstance(CLSID_ShellWindows);
  if (FAILED(hr)) {
    LOGHR(WARN, hr) << "Unable to create an object using the IShellWindows interface with CoCreateInstance";
    return false;
  }

  CComPtr<IUnknown> enumerator_unknown;
  hr = shell_windows->_NewEnum(&enumerator_unknown);
  if (FAILED(hr)) {
    LOGHR(WARN, hr) << "Unable to get enumerator from IShellWindows interface";
    return false;
  }

  clock_t end = clock() + (this->browser_attach_timeout_ / 1000 * CLOCKS_PER_SEC);

  CComPtr<IEnumVARIANT> enumerator;
  enumerator_unknown->QueryInterface<IEnumVARIANT>(&enumerator);
  while (process_window_info->hwndBrowser == NULL) {
    if (this->browser_attach_timeout_ > 0 && (clock() > end)) {
      break;
    }
    enumerator->Reset();
    for (CComVariant shell_window_variant;
         enumerator->Next(1, &shell_window_variant, NULL) == S_OK;
         shell_window_variant.Clear()) {

      if (shell_window_variant.vt != VT_DISPATCH) {
        continue;
      }

      CComPtr<IShellBrowser> shell_browser;
      hr = IUnknown_QueryService(shell_window_variant.pdispVal,
                                 SID_STopLevelBrowser,
                                 IID_PPV_ARGS(&shell_browser));
      if (shell_browser) {
        HWND hwnd;
        hr = shell_browser->GetWindow(&hwnd);
        if (SUCCEEDED(hr)) {
          ::EnumChildWindows(hwnd,
                             &BrowserFactory::FindChildWindowForProcess,
                             reinterpret_cast<LPARAM>(process_window_info));
          if (process_window_info->hwndBrowser != NULL) {
            LOG(DEBUG) << "Found window handle "
                       << process_window_info->hwndBrowser
                       << " for window with class 'Internet Explorer_Server'"
                       << " belonging to process with id "
                       << process_window_info->dwProcessId;
            CComPtr<IWebBrowser2> browser;
            hr = shell_window_variant.pdispVal->QueryInterface<IWebBrowser2>(&browser);
            if (FAILED(hr)) {
              LOGHR(WARN, hr) << "Found browser window using ShellWindows "
                              << "API, but QueryInterface for IWebBrowser2 "
                              << "failed, so could not attach to the browser.";
            } else {
              process_window_info->pBrowser = browser.Detach();
            }
            break;
          }
        }
      }
    }
    if (process_window_info->hwndBrowser == NULL ||
        process_window_info->pBrowser == NULL) {
      ::Sleep(250);
    }
  }

  if (process_window_info->hwndBrowser == NULL) {
    *error_message = StringUtilities::Format(ATTACH_TIMEOUT_ERROR_MESSAGE,
                                             process_window_info->dwProcessId,
                                             this->browser_attach_timeout_);
    return false;
  }

  if (process_window_info->pBrowser == NULL) {
    *error_message = ATTACH_FAILURE_ERROR_MESSAGE;
    return false;
  }
  return true;
}

int BrowserFactory::GetBrowserZoomLevel(IWebBrowser2* browser) {
  LOG(TRACE) << "Entering BrowserFactory::GetBrowserZoomLevel";
  clock_t end = clock() + (this->browser_attach_timeout_ / 1000 * CLOCKS_PER_SEC);
  CComPtr<IDispatch> document_dispatch;
  while (!document_dispatch) {
    if (this->browser_attach_timeout_ > 0 && (clock() > end)) {
      break;
    }

    browser->get_Document(&document_dispatch);

    if (!document_dispatch) {
      ::Sleep(250);
    }
  }

  if (!document_dispatch) {
    LOG(WARN) << "Call to IWebBrowser2::get_Document failed";
    return 0;
  }

  CComPtr<IHTMLDocument2> document;
  document_dispatch->QueryInterface(&document);
  if (!document) {
    LOG(WARN) << "QueryInterface for IHTMLDocument2 failed.";
    return 0;
  }

  CComPtr<IHTMLWindow2> window;
  HRESULT hr = document->get_parentWindow(&window);
  if (FAILED(hr)) {
    LOGHR(WARN, hr) << "Call to IHTMLDocument2::get_parentWindow failed";
    return 0;
  }

  // Test for zoom level = 100%
  int zoom_level = this->GetZoomLevel(document, window);
  return zoom_level;
}

int BrowserFactory::GetZoomLevel(IHTMLDocument2* document, IHTMLWindow2* window) {
  LOG(TRACE) << "Entering BrowserFactory::GetZoomLevel";
  int zoom = 100;  // Chances are the zoom level hasn't been modified....
  HRESULT hr = S_OK;
  if (this->ie_major_version_ == 7) {
    CComPtr<IHTMLElement> body;
    hr = document->get_body(&body);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Call to IHTMLDocument2::get_body failed";
      return zoom;
    }

    long offset_width = 0;
    hr = body->get_offsetWidth(&offset_width);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Call to IHTMLElement::get_offsetWidth failed";
      return zoom;
    }

    CComPtr<IHTMLElement2> body2;
    hr = body.QueryInterface<IHTMLElement2>(&body2);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Attempt to QueryInterface for IHTMLElement2 failed";
      return zoom;
    }

    CComPtr<IHTMLRect> rect;
    hr = body2->getBoundingClientRect(&rect);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Call to IHTMLElement2::getBoundingClientRect failed";
      return zoom;
    }

    long left = 0, right = 0;
    hr = rect->get_left(&left);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Call to IHTMLRect::get_left failed";
      return zoom;
    }

    hr = rect->get_right(&right);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Call to IHTMLRect::get_right failed";
      return zoom;
    }

    zoom = static_cast<int>((static_cast<double>(right - left) / offset_width) * 100.0);
  } else if (this->ie_major_version_ >= 8) {
    CComPtr<IHTMLScreen> screen;
    hr = window->get_screen(&screen);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Call to IHTMLWindow2::get_screen failed";
      return zoom;
    }

    CComPtr<IHTMLScreen2> screen2;
    hr = screen.QueryInterface<IHTMLScreen2>(&screen2);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Attempt to QueryInterface for IHTMLScreen2 failed";
      return zoom;
    }

    long device_xdpi=0, logical_xdpi = 0;
    hr = screen2->get_deviceXDPI(&device_xdpi);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Call to IHTMLScreen2::get_deviceXDPI failed";
      return zoom;
    }

    hr = screen2->get_logicalXDPI(&logical_xdpi);
    if (FAILED(hr)) {
      LOGHR(WARN, hr) << "Call to IHTMLScreen2::get_logicalXDPI failed";
      return zoom;
    }

    zoom = static_cast<int>((static_cast<double>(device_xdpi) / logical_xdpi) * 100.0);
  } else {
    // IE6 case
    zoom = 100;
  }

  LOG(DEBUG) << "Browser zoom level is " << zoom << "%";
  return zoom;
}

IWebBrowser2* BrowserFactory::CreateBrowser(bool is_protected_mode) {
  LOG(TRACE) << "Entering BrowserFactory::CreateBrowser";

  IWebBrowser2* browser = NULL;
  DWORD context = CLSCTX_LOCAL_SERVER;
  if (this->ie_major_version_ == 7 && IsWindowsVistaOrGreater()) {
    // ONLY for IE 7 on Windows Vista. XP and below do not have Protected Mode;
    // Windows 7 shipped with IE8.
    context = context | CLSCTX_ENABLE_CLOAKING;
  }

  HRESULT hr = S_OK;
  if (is_protected_mode) {
    hr = ::CoCreateInstance(CLSID_InternetExplorer,
                            NULL,
                            context,
                            IID_IWebBrowser2,
                            reinterpret_cast<void**>(&browser));
  } else {
    hr = ::CoCreateInstance(CLSID_InternetExplorerMedium,
                            NULL,
                            context,
                            IID_IWebBrowser2,
                            reinterpret_cast<void**>(&browser));
  }
  // When IWebBrowser2::Quit() is called, the wrapper process doesn't
  // exit right away. When that happens, CoCreateInstance can fail while
  // the abandoned iexplore.exe instance is still valid. The "right" way
  // to do this would be to call ::EnumProcesses before calling
  // CoCreateInstance, finding all of the iexplore.exe processes, waiting
  // for one to exit, and then proceed. However, there is no way to tell
  // if a process ID belongs to an Internet Explorer instance, particularly
  // when a 32-bit process tries to enumerate 64-bit processes on 64-bit
  // Windows. So, we'll take the brute force way out, just retrying the call
  // to CoCreateInstance until it succeeds (the old iexplore.exe process has
  // exited), or we get a different error code. We'll also set a 45-second
  // timeout, with 45 seconds being chosen because it's below the default
  // 60 second HTTP request timeout of most language bindings.
  if (FAILED(hr) && HRESULT_CODE(hr) == ERROR_SHUTDOWN_IS_SCHEDULED) {
    LOG(DEBUG) << "CoCreateInstance for IWebBrowser2 failed due to a "
                << "browser process that has not yet fully exited. Retrying "
                << "until the browser process exits and a new instance can "
                << "be successfully created.";
  }
  clock_t timeout = clock() + (45 * CLOCKS_PER_SEC);
  while (FAILED(hr) &&
         HRESULT_CODE(hr) == ERROR_SHUTDOWN_IS_SCHEDULED &&
         clock() < timeout) {
    ::Sleep(500);
    hr = ::CoCreateInstance(CLSID_InternetExplorer,
                            NULL,
                            context,
                            IID_IWebBrowser2,
                            reinterpret_cast<void**>(&browser));
  }
  if (FAILED(hr) && HRESULT_CODE(hr) != ERROR_SHUTDOWN_IS_SCHEDULED) {
    // If we hit this branch, the CoCreateInstance failed due to an unexpected
    // error, either before we looped, or at some point during the loop. In
    // in either case, there's not much else we can do except log the failure.
    LOGHR(WARN, hr) << "CoCreateInstance for IWebBrowser2 failed.";
  }

  if (browser != NULL) {
    browser->put_Visible(VARIANT_TRUE);
  }

  return browser;
}

bool BrowserFactory::CreateLowIntegrityLevelToken(HANDLE* process_token_handle,
                                                  HANDLE* mic_token_handle,
                                                  PSID* sid) {
  LOG(TRACE) << "Entering BrowserFactory::CreateLowIntegrityLevelToken";
  BOOL result = TRUE;
  TOKEN_MANDATORY_LABEL tml = {0};

  HANDLE process_handle = ::GetCurrentProcess();
  result = ::OpenProcessToken(process_handle,
                              MAXIMUM_ALLOWED,
                              process_token_handle);

  if (result) {
    result = ::DuplicateTokenEx(*process_token_handle,
                                MAXIMUM_ALLOWED,
                                NULL,
                                SecurityImpersonation,
                                TokenPrimary,
                                mic_token_handle);
    if (!result) {
      LOGERR(WARN) << "CreateLowIntegrityLevelToken: Could not duplicate token";
      ::CloseHandle(*process_token_handle);
    }
   }

  if (result) {
    result = ::ConvertStringSidToSid(SDDL_ML_LOW, sid);
    if (result) {
      tml.Label.Attributes = SE_GROUP_INTEGRITY;
      tml.Label.Sid = *sid;
    } else {
      LOGERR(WARN) << "CreateLowIntegrityLevelToken: Could not convert string SID to SID";
      ::CloseHandle(*process_token_handle);
      ::CloseHandle(*mic_token_handle);
    }
  }

  if(result) {
    result = ::SetTokenInformation(*mic_token_handle,
                                   TokenIntegrityLevel,
                                   &tml,
                                   sizeof(tml) + ::GetLengthSid(*sid));
    if (!result) {
      LOGERR(WARN) << "CreateLowIntegrityLevelToken: Could not set token information to low level";
      ::CloseHandle(*process_token_handle);
      ::CloseHandle(*mic_token_handle);
      ::LocalFree(*sid);
    }
  }

  ::CloseHandle(process_handle);
  return result == TRUE;
}

void BrowserFactory::InvokeClearCacheUtility(bool use_low_integrity_level) {
  LOG(TRACE) << "Entering BrowserFactory::InvokeClearCacheUtility";
  HRESULT hr = S_OK;
  std::vector<wchar_t> system_path_buffer(MAX_PATH);
  std::vector<wchar_t> rundll_exe_path_buffer(MAX_PATH);
  std::vector<wchar_t> inetcpl_path_buffer(MAX_PATH);
  std::wstring args = L"";

  UINT system_path_size = ::GetSystemDirectory(&system_path_buffer[0], MAX_PATH);

  HANDLE  process_token = NULL;
  HANDLE  mic_token = NULL;
  PSID    sid = NULL;

  bool can_create_process = true;
  if (!use_low_integrity_level ||
      this->CreateLowIntegrityLevelToken(&process_token, &mic_token, &sid)) {
    if (0 != system_path_size &&
        system_path_size <= static_cast<int>(system_path_buffer.size())) {
      if (::PathCombine(&rundll_exe_path_buffer[0],
                        &system_path_buffer[0],
                        RUNDLL_EXE_NAME) &&
          ::PathCombine(&inetcpl_path_buffer[0],
                        &system_path_buffer[0],
                        INTERNET_CONTROL_PANEL_APPLET_NAME)) {
        // PathCombine will return NULL if the buffer would be exceeded.
        ::PathQuoteSpaces(&rundll_exe_path_buffer[0]);
        ::PathQuoteSpaces(&inetcpl_path_buffer[0]);
        args = StringUtilities::Format(CLEAR_CACHE_COMMAND_LINE_ARGS,
                                       &inetcpl_path_buffer[0],
                                       CLEAR_CACHE_OPTIONS);
      } else {
        LOG(WARN) << "Cannot combine paths to utilities required to clear cache.";
        can_create_process = false;
      }
    } else {
      LOG(WARN) << "Paths system directory exceeds MAX_PATH.";
      can_create_process = false;
    }

    if (can_create_process) {
      LOG(DEBUG) << "Launching inetcpl.cpl via rundll32.exe to clear cache";
      STARTUPINFO start_info;
      ::ZeroMemory(&start_info, sizeof(start_info));
      start_info.cb = sizeof(start_info);

      PROCESS_INFORMATION process_info;
      BOOL is_process_created = FALSE;
      start_info.dwFlags = STARTF_USESHOWWINDOW;
      start_info.wShowWindow = SW_SHOWNORMAL;

      std::vector<wchar_t> args_buffer(0);
      StringUtilities::ToBuffer(args, &args_buffer);
      // Create the process to run with low or medium rights
      if (use_low_integrity_level) {
        is_process_created = CreateProcessAsUser(mic_token,
                                                 &rundll_exe_path_buffer[0],
                                                 &args_buffer[0],
                                                 NULL,
                                                 NULL,
                                                 FALSE,
                                                 0,
                                                 NULL,
                                                 NULL,
                                                 &start_info,
                                                 &process_info);
      } else {
        is_process_created = CreateProcess(&rundll_exe_path_buffer[0],
                                           &args_buffer[0],
                                           NULL,
                                           NULL,
                                           FALSE,
                                           0,
                                           NULL,
                                           NULL,
                                           &start_info,
                                           &process_info);
      }

      if (is_process_created) {
        // Wait for the rundll32.exe process to exit.
        LOG(DEBUG) << "Waiting for rundll32.exe process to exit.";
        ::WaitForInputIdle(process_info.hProcess, 5000);
        ::WaitForSingleObject(process_info.hProcess, 30000);
        ::CloseHandle(process_info.hProcess);
        ::CloseHandle(process_info.hThread);
        LOG(DEBUG) << "Cache clearing complete.";
      } else {
        LOGERR(WARN) << "Could not create process for clearing cache.";
      }
    }

    // Close the handles opened when creating the
    // low integrity level token
    if (use_low_integrity_level) {
      ::CloseHandle(process_token);
      ::CloseHandle(mic_token);
      ::LocalFree(sid);
    }
  }
}

BOOL CALLBACK BrowserFactory::FindBrowserWindow(HWND hwnd, LPARAM arg) {
  // Could this be an IE instance?
  // 8 == "IeFrame\0"
  // 21 == "Shell DocObject View\0"
  // 19 == "Chrome_WidgetWin_1"
  char name[21];
  if (::GetClassNameA(hwnd, name, 21) == 0) {
    // No match found. Skip
    return TRUE;
  }

  if (strcmp(IE_FRAME_WINDOW_CLASS, name) != 0 &&
      strcmp(SHELL_DOCOBJECT_VIEW_WINDOW_CLASS, name) != 0 &&
      strcmp(ANDIE_FRAME_WINDOW_CLASS, name) != 0) {
    return TRUE;
  }

  return EnumChildWindows(hwnd, FindChildWindowForProcess, arg);
}

BOOL CALLBACK BrowserFactory::FindEdgeWindow(HWND hwnd, LPARAM arg) {
  // Could this be an EdgeChrome window?
  // 19 == "Chrome_WidgetWin_1"
  char name[20];
  if (::GetClassNameA(hwnd, name, 20) == 0) {
    // No match found. Skip
    return TRUE;
  }

  // continue if it is not "Chrome_WidgetWin_1"
  if (strcmp(ANDIE_FRAME_WINDOW_CLASS, name) != 0) return TRUE;

  // continue if window does not belong to the target process
  DWORD process_id = NULL;
  ::GetWindowThreadProcessId(hwnd, &process_id);
  ProcessWindowInfo* process_window_info = reinterpret_cast<ProcessWindowInfo*>(arg);
  if (process_window_info->dwProcessId != process_id) {
    return TRUE;
  }

  return EnumChildWindows(hwnd, FindEdgeChildWindowForProcess, arg);
}

BOOL CALLBACK BrowserFactory::FindEdgeWindowIgnoringProcessMatch(HWND hwnd, LPARAM arg) {
  // Could this be an EdgeChrome window?
  // 19 == "Chrome_WidgetWin_1"
  char name[20];
  if (::GetClassNameA(hwnd, name, 20) == 0) {
    // No match found. Skip
    return TRUE;
  }

  // continue if it is not "Chrome_WidgetWin_1"
  if (strcmp(ANDIE_FRAME_WINDOW_CLASS, name) != 0) return TRUE;

  return EnumChildWindows(hwnd, FindEdgeChildWindowForProcess, arg);
}

BOOL CALLBACK BrowserFactory::FindIEBrowserHandles(HWND hwnd, LPARAM arg) {
  std::vector<HWND>* handles = reinterpret_cast<std::vector<HWND>*>(arg);

  // Could this be an Internet Explorer Server window?
  // 25 == "Internet Explorer_Server\0"
  char name[25];
  if (::GetClassNameA(hwnd, name, 25) == 0) {
    // No match found. Skip
    return TRUE;
  }

  if (strcmp("Internet Explorer_Server", name) == 0) {
    handles->push_back(hwnd);
  }

  return TRUE;
}

BOOL CALLBACK BrowserFactory::FindEdgeBrowserHandles(HWND hwnd, LPARAM arg) {
  std::vector<HWND>* handles = reinterpret_cast<std::vector<HWND>*>(arg);

  // Could this be an Internet Explorer Server window?
  // 19 == "Chrome_WidgetWin_1\0"
  char name[20];
  if (::GetClassNameA(hwnd, name, 20) == 0) {
    // No match found. Skip
    return TRUE;
  }

  if (strcmp("Chrome_WidgetWin_1", name) == 0) {
    handles->push_back(hwnd);
  }

  return TRUE;
}

BOOL CALLBACK BrowserFactory::FindChildWindowForProcess(HWND hwnd, LPARAM arg) {
  ProcessWindowInfo *process_window_info = reinterpret_cast<ProcessWindowInfo*>(arg);

  // Could this be an Internet Explorer Server window?
  // 25 == "Internet Explorer_Server\0"
  char name[25];
  if (::GetClassNameA(hwnd, name, 25) == 0) {
    // No match found. Skip
    return TRUE;
  }

  if (strcmp(IE_SERVER_CHILD_WINDOW_CLASS, name) != 0) {
    return TRUE;
  } else {
    DWORD process_id = NULL;
    ::GetWindowThreadProcessId(hwnd, &process_id);
    LOG(DEBUG) << "Looking for " << process_window_info->dwProcessId;
    if (process_window_info->dwProcessId == process_id) {
      // Once we've found the first Internet Explorer_Server window
      // for the process we want, we can stop.
      process_window_info->hwndBrowser = hwnd;
      return FALSE;
    }
  }

  return TRUE;
}

BOOL CALLBACK BrowserFactory::FindEdgeChildWindowForProcess(HWND hwnd, LPARAM arg) {
  ProcessWindowInfo* process_window_info = reinterpret_cast<ProcessWindowInfo*>(arg);

  // Could this be an Internet Explorer Server window?
  // 25 == "Internet Explorer_Server\0"
  char name[25];
  if (::GetClassNameA(hwnd, name, 25) == 0) {
    // No match found. Skip
    return TRUE;
  }

  if (strcmp(IE_SERVER_CHILD_WINDOW_CLASS, name) != 0) {
    return TRUE;
  }
  else {
    DWORD process_id = NULL;
    ::GetWindowThreadProcessId(hwnd, &process_id);
    LOG(DEBUG) << "Looking for " << process_window_info->dwProcessId;
    // Once we've found the first Internet Explorer_Server window
    // for the process we want, we can stop.
    process_window_info->hwndBrowser = hwnd;
    return FALSE;
  }

  return TRUE;
}

BOOL CALLBACK BrowserFactory::FindDialogWindowForProcess(HWND hwnd, LPARAM arg) {
  ProcessWindowInfo* process_win_info = reinterpret_cast<ProcessWindowInfo*>(arg);

  // Could this be an dialog window?
  // 7 == "#32770\0"
  // 29 == "Credential Dialog Xaml Host\0"
  // 34 == "Internet Explorer_TridentDlgFrame\0"
  char name[34];
  if (::GetClassNameA(hwnd, name, 34) == 0) {
    // No match found. Skip
    return TRUE;
  }

  if (strcmp(ALERT_WINDOW_CLASS, name) != 0 &&
      strcmp(HTML_DIALOG_WINDOW_CLASS, name) != 0 &&
      strcmp(SECURITY_DIALOG_WINDOW_CLASS, name) != 0) {
    return TRUE;
  } else {
    // If the window style has the WS_DISABLED bit set or the
    // WS_VISIBLE bit unset, it can't be handled via the UI,
    // and must not be a visible dialog. Furthermore, if the
    // window style does not display a caption bar, it's not a
    // dialog displayed by the browser, but likely by an add-on
    // (like an antivirus toolbar). Note that checking the caption
    // window style is a hack, and may begin to fail if IE ever
    // changes the style of its alert windows.
    long window_long_style = ::GetWindowLong(hwnd, GWL_STYLE);
    if ((window_long_style & WS_DISABLED) != 0 ||
        (window_long_style & WS_VISIBLE) == 0 ||
        (window_long_style & WS_CAPTION) == 0) {
      return TRUE;
    }
    DWORD process_id = NULL;
    ::GetWindowThreadProcessId(hwnd, &process_id);
    if (process_win_info->dwProcessId == process_id) {
      // Once we've found the first dialog (#32770) window
      // for the process we want, we can stop.
      process_win_info->hwndBrowser = hwnd;
      return FALSE;
    }
  }

  return TRUE;
}

void BrowserFactory::GetIEExecutableLocation() {
  LOG(TRACE) << "Entering BrowserFactory::GetIEExecutableLocation";

   std::wstring redirection;
    if (RegistryUtilities::GetRegistryValue(HKEY_LOCAL_MACHINE,
      IE_REDIRECT,
      L"{1FD49718-1D00-4B19-AF5F-070AF6D5D54C}",
      &redirection)) {
      this->ie_redirects_edge_ = redirection == L"1";
    }
    else {
      LOG(WARN) << "Unable to determine IE to Edge Redirection";
    }

  std::wstring class_id;
  if (RegistryUtilities::GetRegistryValue(HKEY_LOCAL_MACHINE,
                                          IE_CLSID_REGISTRY_KEY,
                                          L"",
                                          &class_id)) {
    std::wstring location_key = L"SOFTWARE\\Classes\\CLSID\\" +
                                class_id +
                                L"\\LocalServer32";
    std::wstring executable_location;

    // If we are a 32-bit driver instance, running on 64-bit Windows,
    // we want to bypass the registry redirection so that we can get
    // the actual location of the browser executable. The primary place
    // this matters is when getting the browser version; the secondary
    // place is if the user specifies to use the CreateProcess API for
    // launching the browser, hence the 'true' argument in the following
    // call to RegistryUtilities::GetRegistryValue.
    if (RegistryUtilities::GetRegistryValue(HKEY_LOCAL_MACHINE,
                                            location_key,
                                            L"",
                                            true,
                                            &executable_location)) {
      // If the executable location in the registry has an environment
      // variable in it, expand the environment variable to an absolute
      // path.
      DWORD expanded_location_size = ::ExpandEnvironmentStrings(executable_location.c_str(), NULL, 0);
      std::vector<wchar_t> expanded_location(expanded_location_size);
      ::ExpandEnvironmentStrings(executable_location.c_str(), &expanded_location[0], expanded_location_size);
      executable_location = &expanded_location[0];
      this->ie_executable_location_ = executable_location;
      size_t arg_start_pos = executable_location.find(L" -");
      if (arg_start_pos != std::string::npos) {
        this->ie_executable_location_ = executable_location.substr(0, arg_start_pos);
      }
      if (this->ie_executable_location_.substr(0, 1) == L"\"") {
        this->ie_executable_location_.erase(0, 1);
        this->ie_executable_location_.erase(this->ie_executable_location_.size() - 1, 1);
      }
    } else {
      LOG(WARN) << "Unable to get IE executable location from registry";
    }
  } else {
    LOG(WARN) << "Unable to get IE class id from registry";
  }
}

void BrowserFactory::GetEdgeExecutableLocation() {
   LOG(TRACE) << "Entering BrowserFactory::GetEdgeExecutableLocation";
 std::wstring edge_executable_location;
  if (RegistryUtilities::GetRegistryValue(HKEY_LOCAL_MACHINE,
                                          EDGE_REGISTRY_KEY,
                                          L"",
                                          true,
                                          &edge_executable_location)) {
    // If the executable location in the registry has an environment
    // variable in it, expand the environment variable to an absolute
    // path.
    DWORD expanded_location_size = ::ExpandEnvironmentStrings(edge_executable_location.c_str(), NULL, 0);
    std::vector<wchar_t> expanded_location(expanded_location_size);
    ::ExpandEnvironmentStrings(edge_executable_location.c_str(), &expanded_location[0], expanded_location_size);
    edge_executable_location = &expanded_location[0];
    this->edge_executable_located_location_ = edge_executable_location;
    size_t arg_start_pos = edge_executable_location.find(L" -");
    if (arg_start_pos != std::string::npos) {
      this->edge_executable_located_location_ = edge_executable_location.substr(0, arg_start_pos);
    }
    if (this->edge_executable_located_location_.substr(0, 1) == L"\"") {
      this->edge_executable_located_location_.erase(0, 1);
      this->edge_executable_located_location_.erase(this->edge_executable_located_location_.size() - 1, 1);
    }
  } else {
    LOG(WARN) << "Unable to get Edge executable location from registry";
  }
}

void BrowserFactory::GetIEVersion() {
  LOG(TRACE) << "Entering BrowserFactory::GetIEVersion";

  std::string ie_version = FileUtilities::GetFileVersion(this->ie_executable_location_);

  if (ie_version.size() == 0) {
    // 64-bit Windows 8 has a bug where it does not return the executable location properly
    this->ie_major_version_ = -1;
    LOG(WARN) << "Couldn't find IE version for executable "
               << LOGWSTRING(this->ie_executable_location_)
               << ", falling back to "
               << this->ie_major_version_;
    return;
  }

  std::stringstream version_stream(ie_version);
  version_stream >> this->ie_major_version_;
}

bool BrowserFactory::ProtectedModeSettingsAreValid() {
  LOG(TRACE) << "Entering BrowserFactory::ProtectedModeSettingsAreValid";

  bool settings_are_valid = true;
  LOG(DEBUG) << "Detected IE version: " << this->ie_major_version_
             << ", Windows version supports Protected Mode: "
             << IsWindowsVistaOrGreater() ? "true" : "false";
  // Only need to check Protected Mode settings on IE 7 or higher
  // and on Windows Vista or higher. Otherwise, Protected Mode
  // doesn't come into play, and are valid.
  // Documentation of registry settings can be found at the following
  // Microsoft KnowledgeBase article:
  // http://support.microsoft.com/kb/182569
  if (this->ie_major_version_ >= 7 && IsWindowsVistaOrGreater()) {
    HKEY key_handle;
    if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_CURRENT_USER,
                                        IE_SECURITY_ZONES_REGISTRY_KEY,
                                        0,
                                        KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
                                        &key_handle)) {
      DWORD subkey_count = 0;
      DWORD max_subkey_name_length = 0;
      if (ERROR_SUCCESS == ::RegQueryInfoKey(key_handle,
                                             NULL,
                                             NULL,
                                             NULL,
                                             &subkey_count,
                                             &max_subkey_name_length,
                                             NULL,
                                             NULL,
                                             NULL,
                                             NULL,
                                             NULL,
                                             NULL)) {
        int protected_mode_value = -1;
        std::vector<wchar_t> subkey_name_buffer(max_subkey_name_length + 1);
        for (size_t index = 0; index < subkey_count; ++index) {
          DWORD number_of_characters_copied = max_subkey_name_length + 1;
          ::RegEnumKeyEx(key_handle,
                         static_cast<DWORD>(index),
                         &subkey_name_buffer[0],
                         &number_of_characters_copied,
                         NULL,
                         NULL,
                         NULL,
                         NULL);
          std::wstring subkey_name = &subkey_name_buffer[0];
          // Ignore the "My Computer" zone, since it's not displayed
          // in the UI.
          if (subkey_name != ZONE_MY_COMPUTER) {
            int value = this->GetZoneProtectedModeSetting(key_handle,
                                                          subkey_name);
            if (protected_mode_value == -1) {
              protected_mode_value = value;
            } else {
              if (value != protected_mode_value) {
                settings_are_valid = false;
                break;
              }
            }
          }
        }
      } else {
        LOG(WARN) << "RegQueryInfoKey to get count of zone setting subkeys failed";
      }
      ::RegCloseKey(key_handle);
    } else {
      std::wstring registry_key_string = IE_SECURITY_ZONES_REGISTRY_KEY;
      LOG(WARN) << "RegOpenKeyEx for zone settings registry key "
                << LOGWSTRING(registry_key_string)
                << " in HKEY_CURRENT_USER failed";
    }
  }
  return settings_are_valid;
}

int BrowserFactory::GetZoneProtectedModeSetting(const HKEY key_handle,
                                                const std::wstring& zone_subkey_name) {
  LOG(TRACE) << "Entering BrowserFactory::GetZoneProtectedModeSetting";

  int protected_mode_value = 3;
  HKEY subkey_handle;
  if (ERROR_SUCCESS == ::RegOpenKeyEx(key_handle,
                                      zone_subkey_name.c_str(),
                                      0,
                                      KEY_QUERY_VALUE,
                                      &subkey_handle)) {
    DWORD value = 0;
    DWORD value_length = sizeof(DWORD);
    if (ERROR_SUCCESS == ::RegQueryValueEx(subkey_handle,
                                           IE_PROTECTED_MODE_SETTING_VALUE_NAME,
                                           NULL,
                                           NULL,
                                           reinterpret_cast<LPBYTE>(&value),
                                           &value_length)) {
      LOG(DEBUG) << "Found Protected Mode setting value of "
                 << value << " for zone " << LOGWSTRING(zone_subkey_name);
      protected_mode_value = value;
    } else {
      LOG(DEBUG) << "RegQueryValueEx failed for getting Protected Mode setting for a zone: "
                 << LOGWSTRING(zone_subkey_name);
    }
    ::RegCloseKey(subkey_handle);
  } else {
    // The REG_DWORD value doesn't exist, so we have to return the default
    // value, which is "on" for the Internet and Restricted Sites zones and
    // is "on" for the Local Intranet zone in IE7 only (the default was
    // changed to "off" for Local Intranet in IE8), and "off" everywhere
    // else.
    // Note that a value of 0 in the registry value indicates that Protected
    // Mode is "on" for that zone; a value of 3 indicates that Protected Mode
    // is "off" for that zone.
    if (zone_subkey_name == ZONE_INTERNET ||
        zone_subkey_name == ZONE_RESTRICTED_SITES ||
        (zone_subkey_name == ZONE_LOCAL_INTRANET && this->ie_major_version_ == 7)) {
      protected_mode_value = 0;
    }
    LOG(DEBUG) << "Protected Mode zone setting value does not exist for zone "
               << LOGWSTRING(zone_subkey_name) << ". Using default value of "
               << protected_mode_value;
  }
  return protected_mode_value;
}

bool BrowserFactory::IsWindowsVersionOrGreater(unsigned short major_version,
                                               unsigned short minor_version,
                                               unsigned short service_pack) {
  OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0,{ 0 }, 0, 0 };
  DWORDLONG        const dwlConditionMask = VerSetConditionMask(
    VerSetConditionMask(
      VerSetConditionMask(
        0, VER_MAJORVERSION, VER_GREATER_EQUAL),
      VER_MINORVERSION, VER_GREATER_EQUAL),
    VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);

  osvi.dwMajorVersion = major_version;
  osvi.dwMinorVersion = minor_version;
  osvi.wServicePackMajor = service_pack;

  return VerifyVersionInfoW(&osvi,
                            VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
                            dwlConditionMask) != FALSE;
}

bool BrowserFactory::IsWindowsVistaOrGreater() {
  return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
}

bool BrowserFactory::IsEdgeMode() const {
  return this->edge_ie_mode_;
}

// delete a folder recursively
int BrowserFactory::DeleteDirectory(const std::wstring &dir_name) {
  WIN32_FIND_DATA file_info;

  std::wstring file_pattern = dir_name + L"\\*.*";
  HANDLE file_handle = ::FindFirstFile(file_pattern.c_str(), &file_info);
  if (file_handle != INVALID_HANDLE_VALUE) {
    do {
      if (file_info.cFileName[0] == '.') {
        continue;
      }
      std::wstring file_path = dir_name + L"\\" + file_info.cFileName;

      if (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        int return_value = DeleteDirectory(file_path);
        if (return_value) {
          return return_value;
        }
      } else {
        if (::SetFileAttributes(file_path.c_str(), FILE_ATTRIBUTE_NORMAL) == FALSE) {
          return ::GetLastError();
        }

        if (::DeleteFile(file_path.c_str()) == FALSE) {
          return ::GetLastError();
        }
      }
    } while (::FindNextFile(file_handle, &file_info) == TRUE);

    ::FindClose(file_handle);
    DWORD dwError = ::GetLastError();
    if (dwError != ERROR_NO_MORE_FILES) {
      return dwError;
    }

    if (::SetFileAttributes(dir_name.c_str(), FILE_ATTRIBUTE_NORMAL) == FALSE) {
      return ::GetLastError();
    }

    if (::RemoveDirectory(dir_name.c_str()) == FALSE) {
      return ::GetLastError();
    }
  }

  return 0;
}

std::wstring BrowserFactory::GetEdgeTempDir() {
  return this->edge_user_data_dir_;
}

} // namespace webdriver
