Skip to content

Commit 24ad7a1

Browse files
committed
[iedriver] Correct logic for finding new tab in Edge IE Mode
1 parent d509170 commit 24ad7a1

File tree

5 files changed

+103
-66
lines changed

5 files changed

+103
-66
lines changed

cpp/iedriver/Browser.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Browser::Browser(IWebBrowser2* browser, HWND hwnd, HWND session_handle, bool is_
4040
this->is_navigation_started_ = false;
4141
this->browser_ = browser;
4242
this->AttachEvents();
43-
this->is_edge_chromium_ = is_edge_chromium;
43+
this->set_is_edge_chromium(is_edge_chromium);
4444
}
4545

4646
Browser::~Browser(void) {
@@ -116,23 +116,26 @@ void __stdcall Browser::NewWindow3(IDispatch** ppDisp,
116116
LOG(TRACE) << "Entering Browser::NewWindow3";
117117
::PostMessage(this->executor_handle(), WD_BEFORE_NEW_WINDOW, NULL, NULL);
118118
std::vector<HWND>* ie_window_handles = nullptr;
119+
WPARAM param_flag = 0;
119120

120-
if (this->is_edge_chromium_) {
121-
HWND top_level_handle = this->GetTopLevelWindowHandle();
121+
if (this->is_edge_chromium()) {
122+
param_flag = 1000;
123+
//HWND top_level_handle = this->GetTopLevelWindowHandle();
122124
// 1) find all Edge browser window handles
123125
std::vector<HWND>edge_window_handles;
124126
::EnumWindows(&BrowserFactory::FindEdgeBrowserHandles,
125127
reinterpret_cast<LPARAM>(&edge_window_handles));
126128

127129
// 2) find all IE browser window handlers as child window when Edge runs in IEMode
128130
ie_window_handles = new std::vector<HWND>;
129-
for (HWND& ewh : edge_window_handles) {
131+
for (HWND& edge_window_handle : edge_window_handles) {
130132
std::vector<HWND> child_window_handles;
131-
::EnumChildWindows(ewh, &BrowserFactory::FindIEBrowserHandles,
132-
reinterpret_cast<LPARAM>(&child_window_handles));
133+
::EnumChildWindows(edge_window_handle,
134+
&BrowserFactory::FindIEBrowserHandles,
135+
reinterpret_cast<LPARAM>(&child_window_handles));
133136

134-
for (HWND& cwh : child_window_handles) {
135-
ie_window_handles->push_back(cwh);
137+
for (HWND& child_window_handle : child_window_handles) {
138+
ie_window_handles->push_back(child_window_handle);
136139
}
137140
}
138141
} else {
@@ -175,8 +178,10 @@ void __stdcall Browser::NewWindow3(IDispatch** ppDisp,
175178
}
176179

177180
// 3) pass all IE window handles to WD_AFTER_NEW_WINDOW
178-
::PostMessage(this->executor_handle(), WD_AFTER_NEW_WINDOW, 1000,
179-
reinterpret_cast<LPARAM>(ie_window_handles));
181+
::PostMessage(this->executor_handle(),
182+
WD_AFTER_NEW_WINDOW,
183+
param_flag,
184+
reinterpret_cast<LPARAM>(ie_window_handles));
180185
}
181186

182187
void __stdcall Browser::DocumentComplete(IDispatch* pDisp, VARIANT* URL) {
@@ -427,12 +432,13 @@ void Browser::Close() {
427432
// make any sense.
428433
this->SetFocusedFrameByElement(NULL);
429434

430-
HRESULT hr = S_OK;
431-
if (this->is_edge_chromium_) {
432-
hr = PostMessage(GetTopLevelWindowHandle(), WM_CLOSE, 0, 0);
433-
} else {
434-
hr = this->browser_->Quit();
435-
}
435+
//HRESULT hr = S_OK;
436+
//if (this->is_edge_chromium_) {
437+
// hr = PostMessage(GetTopLevelWindowHandle(), WM_CLOSE, 0, 0);
438+
//} else {
439+
// hr = this->browser_->Quit();
440+
//}
441+
HRESULT hr = this->browser_->Quit();
436442

437443
if (FAILED(hr)) {
438444
LOGHR(WARN, hr) << "Call to IWebBrowser2::Quit failed";

cpp/iedriver/Browser.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ class Browser : public DocumentHost, public IDispEventSimpleImpl<1, Browser, &DI
159159
CComPtr<IWebBrowser2> browser_;
160160
bool is_navigation_started_;
161161
bool is_explicit_close_requested_;
162-
bool is_edge_chromium_;
163162
std::vector<DWORD> known_process_ids_;
164163
};
165164

cpp/iedriver/BrowserFactory.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1062,7 +1062,8 @@ BOOL CALLBACK BrowserFactory::FindBrowserWindow(HWND hwnd, LPARAM arg) {
10621062
}
10631063

10641064
if (strcmp(IE_FRAME_WINDOW_CLASS, name) != 0 &&
1065-
strcmp(SHELL_DOCOBJECT_VIEW_WINDOW_CLASS, name) != 0) {
1065+
strcmp(SHELL_DOCOBJECT_VIEW_WINDOW_CLASS, name) != 0 &&
1066+
strcmp(ANDIE_FRAME_WINDOW_CLASS, name) != 0) {
10661067
return TRUE;
10671068
}
10681069

cpp/iedriver/DocumentHost.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ class DocumentHost {
8585
void SetFocusedFrameToParent(void);
8686
bool SetFocusToBrowser(void);
8787

88+
bool is_edge_chromium(void) const { return this->is_edge_chromium_; }
89+
void set_is_edge_chromium(const bool value) { this->is_edge_chromium_ = value; }
90+
8891
bool wait_required(void) const { return this->wait_required_; }
8992
void set_wait_required(const bool value) { this->wait_required_ = value; }
9093

@@ -133,6 +136,7 @@ class DocumentHost {
133136
bool script_wait_required_;
134137
bool is_closing_;
135138
bool is_awaiting_new_process_;
139+
bool is_edge_chromium_;
136140
};
137141

138142
} // namespace webdriver

cpp/iedriver/IECommandExecutor.cpp

Lines changed: 75 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -296,34 +296,36 @@ LRESULT IECommandExecutor::OnAfterNewWindow(UINT uMsg,
296296
HWND top_level_handle = browser_wrapper->GetTopLevelWindowHandle();
297297

298298
std::vector<HWND>* current_window_handles =
299-
reinterpret_cast<std::vector<HWND>*>(lParam);
299+
reinterpret_cast<std::vector<HWND>*>(lParam);
300300
std::unordered_set<HWND> current_window_set(
301-
current_window_handles->begin(),
302-
current_window_handles->end());
301+
current_window_handles->begin(),
302+
current_window_handles->end());
303303
delete current_window_handles;
304304

305305
// sleep 0.5s then get current window handles
306306
::Sleep(500);
307307

308308
std::vector<HWND> edge_window_handles;
309309
::EnumWindows(&BrowserFactory::FindEdgeBrowserHandles,
310-
reinterpret_cast<LPARAM>(&edge_window_handles));
310+
reinterpret_cast<LPARAM>(&edge_window_handles));
311311

312312
std::vector<HWND> new_ie_window_handles;
313-
for (auto& ewh : edge_window_handles) {
313+
for (auto& edge_window_handle : edge_window_handles) {
314314
std::vector<HWND> child_window_handles;
315-
::EnumChildWindows(ewh, &BrowserFactory::FindIEBrowserHandles,
316-
reinterpret_cast<LPARAM>(&child_window_handles));
315+
::EnumChildWindows(edge_window_handle,
316+
&BrowserFactory::FindIEBrowserHandles,
317+
reinterpret_cast<LPARAM>(&child_window_handles));
317318

318-
for (auto& cwh : child_window_handles) {
319-
new_ie_window_handles.push_back(cwh);
319+
for (auto& child_window_handle : child_window_handles) {
320+
new_ie_window_handles.push_back(child_window_handle);
320321
}
321322
}
322323

323324
std::vector<HWND> diff;
324325
for (auto& window_handle : new_ie_window_handles) {
325-
if (current_window_set.find(window_handle) != current_window_set.end())
326+
if (current_window_set.find(window_handle) != current_window_set.end()) {
326327
continue;
328+
}
327329
diff.push_back(window_handle);
328330
}
329331

@@ -347,10 +349,9 @@ LRESULT IECommandExecutor::OnAfterNewWindow(UINT uMsg,
347349
info.pBrowser = NULL;
348350
std::string error_message = "";
349351
this->factory_->AttachToBrowser(&info, &error_message);
350-
BrowserHandle new_window_wrapper(new Browser(info.pBrowser,
351-
NULL,
352-
this->m_hWnd,
353-
true));
352+
BrowserHandle new_window_wrapper(
353+
new Browser(info.pBrowser, NULL, this->m_hWnd, true));
354+
354355
// Force a wait cycle to make sure the browser is finished initializing.
355356
new_window_wrapper->Wait(NORMAL_PAGE_LOAD_STRATEGY);
356357
this->AddManagedBrowser(new_window_wrapper);
@@ -1273,7 +1274,7 @@ std::string IECommandExecutor::OpenNewBrowsingContext(const std::string& window_
12731274
}
12741275

12751276
std::string IECommandExecutor::OpenNewBrowsingContext(const std::string& window_type,
1276-
const std::string& url) {
1277+
const std::string& url) {
12771278
LOG(TRACE) << "Entering IECommandExecutor::OpenNewBrowsingContext";
12781279
std::wstring target_url = StringUtilities::ToWString(url);
12791280
std::string new_browser_id = "";
@@ -1351,48 +1352,74 @@ std::string IECommandExecutor::OpenNewBrowserTab(const std::wstring& url) {
13511352
NULL);
13521353
::Sleep(500);
13531354

1354-
clock_t end_time = clock() + 5 * CLOCKS_PER_SEC;
1355+
HWND new_tab_window = NULL;
13551356
std::vector<HWND> new_handles;
13561357
::EnumChildWindows(top_level_handle,
13571358
&BrowserFactory::FindIEBrowserHandles,
13581359
reinterpret_cast<LPARAM>(&new_handles));
1359-
while (new_handles.size() <= original_handles.size() &&
1360-
clock() < end_time) {
1361-
::Sleep(50);
1362-
::EnumChildWindows(top_level_handle,
1363-
&BrowserFactory::FindIEBrowserHandles,
1364-
reinterpret_cast<LPARAM>(&new_handles));
1365-
}
1366-
std::sort(new_handles.begin(), new_handles.end());
1360+
clock_t end_time = clock() + 5 * CLOCKS_PER_SEC;
1361+
if (browser_wrapper->is_edge_chromium()) {
1362+
// It appears that for Chromium-based Edge in IE Mode, there will only
1363+
// ever be one active child window of the top-level window with window
1364+
// class "Internet Explorer_Server", which is the active tab. Inactive
1365+
// tabs are re-parented until brought back to being the active tab.
1366+
while ((new_handles.size() == 0 || new_handles[0] == original_handles[0])
1367+
&& clock() < end_time) {
1368+
if (new_handles.size() != 0) {
1369+
new_handles.clear();
1370+
}
13671371

1368-
if (new_handles.size() <= original_handles.size()) {
1369-
LOG(WARN) << "No new window handle found after attempt to open";
1370-
return "";
1371-
}
1372+
::Sleep(50);
1373+
::EnumChildWindows(top_level_handle,
1374+
&BrowserFactory::FindIEBrowserHandles,
1375+
reinterpret_cast<LPARAM>(&new_handles));
1376+
}
1377+
1378+
if (new_handles.size() == 0 || new_handles[0] == original_handles[0]) {
1379+
LOG(WARN) << "No new window handle found after attempt to open";
1380+
return "";
1381+
}
13721382

1373-
// We are guaranteed to have at least one HWND difference
1374-
// between the two vectors if we reach this point, because
1375-
// we know the vectors are different sizes.
1376-
std::vector<HWND> diff(new_handles.size());
1377-
std::vector<HWND>::iterator it = std::set_difference(new_handles.begin(),
1378-
new_handles.end(),
1379-
original_handles.begin(),
1380-
original_handles.end(),
1381-
diff.begin());
1382-
diff.resize(it - diff.begin());
1383-
if (diff.size() > 1) {
1384-
std::string handle_list = "";
1385-
std::vector<HWND>::const_iterator it = diff.begin();
1386-
for (; it != diff.end(); ++it) {
1387-
if (handle_list.size() > 0) {
1388-
handle_list.append(", ");
1383+
new_tab_window = new_handles[0];
1384+
} else {
1385+
while (new_handles.size() <= original_handles.size() &&
1386+
clock() < end_time) {
1387+
::Sleep(50);
1388+
::EnumChildWindows(top_level_handle,
1389+
&BrowserFactory::FindIEBrowserHandles,
1390+
reinterpret_cast<LPARAM>(&new_handles));
1391+
}
1392+
std::sort(new_handles.begin(), new_handles.end());
1393+
1394+
if (new_handles.size() <= original_handles.size()) {
1395+
LOG(WARN) << "No new window handle found after attempt to open";
1396+
return "";
1397+
}
1398+
1399+
// We are guaranteed to have at least one HWND difference
1400+
// between the two vectors if we reach this point, because
1401+
// we know the vectors are different sizes.
1402+
std::vector<HWND> diff(new_handles.size());
1403+
std::vector<HWND>::iterator it = std::set_difference(new_handles.begin(),
1404+
new_handles.end(),
1405+
original_handles.begin(),
1406+
original_handles.end(),
1407+
diff.begin());
1408+
diff.resize(it - diff.begin());
1409+
if (diff.size() > 1) {
1410+
std::string handle_list = "";
1411+
std::vector<HWND>::const_iterator it = diff.begin();
1412+
for (; it != diff.end(); ++it) {
1413+
if (handle_list.size() > 0) {
1414+
handle_list.append(", ");
1415+
}
1416+
handle_list.append(StringUtilities::Format("0x%08x", *it));
13891417
}
1390-
handle_list.append(StringUtilities::Format("0x%08x", *it));
1418+
LOG(DEBUG) << "Found more than one new window handles! Found "
1419+
<< diff.size() << "windows [" << handle_list << "]";
13911420
}
1392-
LOG(DEBUG) << "Found more than one new window handles! Found "
1393-
<< diff.size() << "windows [" << handle_list << "]";
1421+
new_tab_window = diff[0];
13941422
}
1395-
HWND new_tab_window = diff[0];
13961423

13971424
DWORD process_id;
13981425
::GetWindowThreadProcessId(new_tab_window, &process_id);

0 commit comments

Comments
 (0)