Skip to content

Commit 8d5f7a4

Browse files
committed
[iedriver] auto detect location of Edge if not specified
1 parent 1b20938 commit 8d5f7a4

2 files changed

Lines changed: 56 additions & 20 deletions

File tree

cpp/iedriver/BrowserFactory.cpp

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#define IE_SERVER_CHILD_WINDOW_CLASS "Internet Explorer_Server"
4444
#define ANDIE_FRAME_WINDOW_CLASS "Chrome_WidgetWin_1"
4545

46+
#define EDGE_REGISTRY_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\msedge.exe"
4647
#define IE_CLSID_REGISTRY_KEY L"SOFTWARE\\Classes\\InternetExplorer.Application\\CLSID"
4748
#define IE_SECURITY_ZONES_REGISTRY_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones"
4849
#define IE_TABPROCGROWTH_REGISTRY_KEY L"Software\\Microsoft\\Internet Explorer\\Main"
@@ -94,7 +95,8 @@ namespace webdriver {
9495

9596
BrowserFactory::BrowserFactory(void) {
9697
// Must be done in the constructor. Do not move to Initialize().
97-
this->GetExecutableLocation();
98+
this->GetEdgeExecutableLocation();
99+
this->GetIEExecutableLocation();
98100
this->GetIEVersion();
99101
this->oleacc_instance_handle_ = NULL;
100102
this->edge_ie_mode_ = false;
@@ -240,7 +242,7 @@ bool BrowserFactory::IsIELaunchURLAvailable() {
240242
FARPROC proc_address = 0;
241243
proc_address = ::GetProcAddress(library_handle, IELAUNCHURL_FUNCTION_NAME);
242244
if (proc_address == NULL || proc_address == 0) {
243-
LOGERR(DEBUG) << "Unable to get address of " << IELAUNCHURL_FUNCTION_NAME
245+
LOGERR(DEBUG) << "Unable to get address of " << IELAUNCHURL_FUNCTION_NAME
244246
<< " method in " << IEFRAME_LIBRARY_NAME;
245247
} else {
246248
api_is_available = true;
@@ -385,7 +387,10 @@ void BrowserFactory::LaunchEdgeInIEMode(PROCESS_INFORMATION* proc_info,
385387

386388
std::wstring executable_and_url = this->edge_executable_location_;
387389
if (executable_and_url == L"") {
388-
executable_and_url = L"msedge.exe"; // Assume it's on the path if it's not passed
390+
executable_and_url = this->edge_executable_located_location_; // Locate Edge via Registry if not passed
391+
if (executable_and_url == L"") {
392+
executable_and_url = L"msedge.exe"; // Assume it's on the path
393+
}
389394
}
390395

391396
// These flags force Edge into a mode where it will only run MSHTML
@@ -511,7 +516,7 @@ bool BrowserFactory::AttachToBrowser(ProcessWindowInfo* process_window_info,
511516
zoom_level = this->GetBrowserZoomLevel(process_window_info->pBrowser);
512517
}
513518
if (zoom_level != 100) {
514-
std::string zoom_level_error =
519+
std::string zoom_level_error =
515520
StringUtilities::Format(ZOOM_SETTING_ERROR_MESSAGE, zoom_level);
516521
LOG(WARN) << zoom_level_error;
517522
*error_message = zoom_level_error;
@@ -664,7 +669,7 @@ bool BrowserFactory::AttachToBrowserUsingShellWindows(
664669
hr = shell_browser->GetWindow(&hwnd);
665670
if (SUCCEEDED(hr)) {
666671
::EnumChildWindows(hwnd,
667-
&BrowserFactory::FindChildWindowForProcess,
672+
&BrowserFactory::FindChildWindowForProcess,
668673
reinterpret_cast<LPARAM>(process_window_info));
669674
if (process_window_info->hwndBrowser != NULL) {
670675
LOG(DEBUG) << "Found window handle "
@@ -876,7 +881,7 @@ IWebBrowser2* BrowserFactory::CreateBrowser(bool is_protected_mode) {
876881
<< "be successfully created.";
877882
}
878883
clock_t timeout = clock() + (45 * CLOCKS_PER_SEC);
879-
while (FAILED(hr) &&
884+
while (FAILED(hr) &&
880885
HRESULT_CODE(hr) == ERROR_SHUTDOWN_IS_SCHEDULED &&
881886
clock() < timeout) {
882887
::Sleep(500);
@@ -925,7 +930,7 @@ bool BrowserFactory::CreateLowIntegrityLevelToken(HANDLE* process_token_handle,
925930
}
926931
}
927932

928-
if (result) {
933+
if (result) {
929934
result = ::ConvertStringSidToSid(SDDL_ML_LOW, sid);
930935
if (result) {
931936
tml.Label.Attributes = SE_GROUP_INTEGRITY;
@@ -969,13 +974,13 @@ void BrowserFactory::InvokeClearCacheUtility(bool use_low_integrity_level) {
969974
PSID sid = NULL;
970975

971976
bool can_create_process = true;
972-
if (!use_low_integrity_level ||
977+
if (!use_low_integrity_level ||
973978
this->CreateLowIntegrityLevelToken(&process_token, &mic_token, &sid)) {
974979
if (0 != system_path_size &&
975980
system_path_size <= static_cast<int>(system_path_buffer.size())) {
976981
if (::PathCombine(&rundll_exe_path_buffer[0],
977982
&system_path_buffer[0],
978-
RUNDLL_EXE_NAME) &&
983+
RUNDLL_EXE_NAME) &&
979984
::PathCombine(&inetcpl_path_buffer[0],
980985
&system_path_buffer[0],
981986
INTERNET_CONTROL_PANEL_APPLET_NAME)) {
@@ -1202,14 +1207,14 @@ BOOL CALLBACK BrowserFactory::FindDialogWindowForProcess(HWND hwnd, LPARAM arg)
12021207
// No match found. Skip
12031208
return TRUE;
12041209
}
1205-
1206-
if (strcmp(ALERT_WINDOW_CLASS, name) != 0 &&
1210+
1211+
if (strcmp(ALERT_WINDOW_CLASS, name) != 0 &&
12071212
strcmp(HTML_DIALOG_WINDOW_CLASS, name) != 0 &&
12081213
strcmp(SECURITY_DIALOG_WINDOW_CLASS, name) != 0) {
12091214
return TRUE;
12101215
} else {
1211-
// If the window style has the WS_DISABLED bit set or the
1212-
// WS_VISIBLE bit unset, it can't be handled via the UI,
1216+
// If the window style has the WS_DISABLED bit set or the
1217+
// WS_VISIBLE bit unset, it can't be handled via the UI,
12131218
// and must not be a visible dialog. Furthermore, if the
12141219
// window style does not display a caption bar, it's not a
12151220
// dialog displayed by the browser, but likely by an add-on
@@ -1235,15 +1240,15 @@ BOOL CALLBACK BrowserFactory::FindDialogWindowForProcess(HWND hwnd, LPARAM arg)
12351240
return TRUE;
12361241
}
12371242

1238-
void BrowserFactory::GetExecutableLocation() {
1239-
LOG(TRACE) << "Entering BrowserFactory::GetExecutableLocation";
1243+
void BrowserFactory::GetIEExecutableLocation() {
1244+
LOG(TRACE) << "Entering BrowserFactory::GetIEExecutableLocation";
12401245

12411246
std::wstring class_id;
12421247
if (RegistryUtilities::GetRegistryValue(HKEY_LOCAL_MACHINE,
12431248
IE_CLSID_REGISTRY_KEY,
12441249
L"",
12451250
&class_id)) {
1246-
std::wstring location_key = L"SOFTWARE\\Classes\\CLSID\\" +
1251+
std::wstring location_key = L"SOFTWARE\\Classes\\CLSID\\" +
12471252
class_id +
12481253
L"\\LocalServer32";
12491254
std::wstring executable_location;
@@ -1284,11 +1289,40 @@ void BrowserFactory::GetExecutableLocation() {
12841289
}
12851290
}
12861291

1292+
void BrowserFactory::GetEdgeExecutableLocation() {
1293+
LOG(TRACE) << "Entering BrowserFactory::GetEdgeExecutableLocation";
1294+
std::wstring edge_executable_location;
1295+
if (RegistryUtilities::GetRegistryValue(HKEY_LOCAL_MACHINE,
1296+
EDGE_REGISTRY_KEY,
1297+
L"",
1298+
true,
1299+
&edge_executable_location)) {
1300+
// If the executable location in the registry has an environment
1301+
// variable in it, expand the environment variable to an absolute
1302+
// path.
1303+
DWORD expanded_location_size = ::ExpandEnvironmentStrings(edge_executable_location.c_str(), NULL, 0);
1304+
std::vector<wchar_t> expanded_location(expanded_location_size);
1305+
::ExpandEnvironmentStrings(edge_executable_location.c_str(), &expanded_location[0], expanded_location_size);
1306+
edge_executable_location = &expanded_location[0];
1307+
this->edge_executable_located_location_ = edge_executable_location;
1308+
size_t arg_start_pos = edge_executable_location.find(L" -");
1309+
if (arg_start_pos != std::string::npos) {
1310+
this->edge_executable_located_location_ = edge_executable_location.substr(0, arg_start_pos);
1311+
}
1312+
if (this->edge_executable_located_location_.substr(0, 1) == L"\"") {
1313+
this->edge_executable_located_location_.erase(0, 1);
1314+
this->edge_executable_located_location_.erase(this->edge_executable_located_location_.size() - 1, 1);
1315+
}
1316+
} else {
1317+
LOG(WARN) << "Unable to get Edge executable location from registry";
1318+
}
1319+
}
1320+
12871321
void BrowserFactory::GetIEVersion() {
12881322
LOG(TRACE) << "Entering BrowserFactory::GetIEVersion";
12891323

12901324
std::string ie_version = FileUtilities::GetFileVersion(this->ie_executable_location_);
1291-
1325+
12921326
if (ie_version.size() == 0) {
12931327
// 64-bit Windows 8 has a bug where it does not return the executable location properly
12941328
this->ie_major_version_ = -1;
@@ -1446,7 +1480,7 @@ bool BrowserFactory::IsWindowsVersionOrGreater(unsigned short major_version,
14461480
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
14471481
dwlConditionMask) != FALSE;
14481482
}
1449-
1483+
14501484
bool BrowserFactory::IsWindowsVistaOrGreater() {
14511485
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
14521486
}
@@ -1457,7 +1491,7 @@ bool BrowserFactory::IsEdgeMode() const {
14571491

14581492
// delete a folder recursively
14591493
int BrowserFactory::DeleteDirectory(const std::wstring &dir_name) {
1460-
WIN32_FIND_DATA file_info;
1494+
WIN32_FIND_DATA file_info;
14611495

14621496
std::wstring file_pattern = dir_name + L"\\*.*";
14631497
HANDLE file_handle = ::FindFirstFile(file_pattern.c_str(), &file_info);

cpp/iedriver/BrowserFactory.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ class BrowserFactory {
101101
ProcessWindowInfo* process_window_info,
102102
std::string* error_message);
103103

104-
void GetExecutableLocation(void);
104+
void GetEdgeExecutableLocation(void);
105+
void GetIEExecutableLocation(void);
105106
void GetIEVersion(void);
106107
bool ProtectedModeSettingsAreValid(void);
107108
int GetZoneProtectedModeSetting(const HKEY key_handle,
@@ -131,6 +132,7 @@ class BrowserFactory {
131132

132133
int ie_major_version_;
133134
std::wstring ie_executable_location_;
135+
std::wstring edge_executable_located_location_;
134136

135137
bool edge_ie_mode_;
136138
std::wstring edge_executable_location_;

0 commit comments

Comments
 (0)