Skip to content

Commit 855c835

Browse files
committed
Implementing retrival of alert text for onBeforeUnload dialogs.
Fixes issue #7901.
1 parent 9571395 commit 855c835

File tree

7 files changed

+137
-8
lines changed

7 files changed

+137
-8
lines changed

Diff for: cpp/iedriver/Alert.cpp

+124-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ Alert::Alert(BrowserHandle browser, HWND handle) {
2121
this->browser_ = browser;
2222
this->alert_handle_ = handle;
2323

24-
HWND direct_ui_child = NULL;
25-
::EnumChildWindows(this->alert_handle_,
26-
&Alert::FindDirectUIChild,
27-
reinterpret_cast<LPARAM>(&direct_ui_child));
24+
HWND direct_ui_child = this->GetDirectUIChild();
2825
this->is_standard_alert_ = direct_ui_child == NULL;
2926
}
3027

@@ -99,6 +96,21 @@ int Alert::SendKeys(std::string keys) {
9996

10097
std::string Alert::GetText() {
10198
LOG(TRACE) << "Entering Alert::GetText";
99+
std::string alert_text_value = "";
100+
if (this->is_standard_alert_) {
101+
alert_text_value = this->GetStandardDialogText();
102+
} else {
103+
std::string alert_text = this->GetDirectUIDialogText();
104+
size_t first_crlf = alert_text.find("\r\n\r\n");
105+
if (first_crlf != std::string::npos && first_crlf + 4 < alert_text.size()) {
106+
alert_text_value = alert_text.substr(first_crlf + 4);
107+
}
108+
}
109+
return alert_text_value;
110+
}
111+
112+
std::string Alert::GetStandardDialogText() {
113+
LOG(TRACE) << "Entering Alert::GetStandardDialogText";
102114
TextLabelFindInfo info;
103115
info.label_handle = NULL;
104116
info.control_id_found = 0;
@@ -147,6 +159,114 @@ std::string Alert::GetText() {
147159
return alert_text_value;
148160
}
149161

162+
std::string Alert::GetDirectUIDialogText() {
163+
LOG(TRACE) << "Entering Alert::GetDirectUIDialogText";
164+
std::string alert_text_value = "";
165+
HWND direct_ui_child_handle = this->GetDirectUIChild();
166+
167+
CComPtr<IAccessible> window_object;
168+
HRESULT hr = ::AccessibleObjectFromWindow(
169+
direct_ui_child_handle,
170+
OBJID_WINDOW,
171+
IID_IAccessible,
172+
reinterpret_cast<void**>(&window_object));
173+
if (FAILED(hr)) {
174+
LOGHR(WARN, hr) << "Failed to get Active Accessibility window object from dialog";
175+
return alert_text_value;
176+
}
177+
178+
// ASSUMPTION: There is an object with the role of "pane" as a child of
179+
// the window object.
180+
CComPtr<IAccessible> pane_object = this->GetChildWithRole(window_object,
181+
ROLE_SYSTEM_PANE,
182+
0);
183+
if (!pane_object) {
184+
LOG(WARN) << "Failed to get Active Accessibility pane child object from window";
185+
return alert_text_value;
186+
}
187+
188+
// ASSUMPTION: The second "static text" accessibility object is the one
189+
// that contains the message.
190+
CComPtr<IAccessible> message_text_object = this->GetChildWithRole(
191+
pane_object,
192+
ROLE_SYSTEM_STATICTEXT,
193+
1);
194+
if (!message_text_object) {
195+
LOG(WARN) << "Failed to get Active Accessibility text child object from pane";
196+
return alert_text_value;
197+
}
198+
199+
CComVariant child_id;
200+
child_id.vt = VT_I4;
201+
child_id.lVal = CHILDID_SELF;
202+
203+
CComBSTR text_bstr;
204+
hr = message_text_object->get_accName(child_id, &text_bstr);
205+
if (FAILED(hr)) {
206+
LOGHR(WARN, hr) << "Failed to get accName property from text object";
207+
return alert_text_value;
208+
}
209+
210+
std::wstring text = text_bstr;
211+
alert_text_value = StringUtilities::ToString(text);
212+
return alert_text_value;
213+
}
214+
215+
IAccessible* Alert::GetChildWithRole(IAccessible* parent, long expected_role, int index) {
216+
LOG(TRACE) << "Entering Alert::GetChildWithRole";
217+
IAccessible* child = NULL;
218+
long child_count;
219+
HRESULT hr = parent->get_accChildCount(&child_count);
220+
if (FAILED(hr)) {
221+
LOGHR(WARN, hr) << "Failed to get accChildCount property from Active Accessibility object";
222+
return child;
223+
}
224+
225+
long returned_children = 0;
226+
std::vector<CComVariant> child_array(child_count);
227+
hr = ::AccessibleChildren(parent, 0, child_count, &child_array[0], &returned_children);
228+
229+
int found_index = 0;
230+
for (long i = 0; i < child_count; ++i) {
231+
if (child_array[i].vt == VT_DISPATCH) {
232+
CComPtr<IAccessible> child_object;
233+
hr = child_array[i].pdispVal->QueryInterface<IAccessible>(&child_object);
234+
if (FAILED(hr)) {
235+
LOGHR(WARN, hr) << "QueryInterface for IAccessible failed for child object with index " << i;
236+
}
237+
238+
CComVariant child_id;
239+
child_id.vt = VT_I4;
240+
child_id.lVal = CHILDID_SELF;
241+
242+
CComVariant actual_role;
243+
hr = child_object->get_accRole(child_id, &actual_role);
244+
if (FAILED(hr)) {
245+
LOGHR(WARN, hr) << "Failed to get accRole property from Active Accessibility object";
246+
}
247+
248+
if (expected_role == actual_role.lVal) {
249+
if (found_index == index) {
250+
child = child_object.Detach();
251+
} else {
252+
++found_index;
253+
}
254+
}
255+
LOG(DEBUG) << "accRole for child with index " << i << ": " << actual_role.lVal;
256+
}
257+
}
258+
return child;
259+
}
260+
261+
HWND Alert::GetDirectUIChild() {
262+
LOG(TRACE) << "Entering Alert::GetDirectUIChild";
263+
HWND direct_ui_child = NULL;
264+
::EnumChildWindows(this->alert_handle_,
265+
&Alert::FindDirectUIChild,
266+
reinterpret_cast<LPARAM>(&direct_ui_child));
267+
return direct_ui_child;
268+
}
269+
150270
int Alert::ClickAlertButton(DialogButtonInfo button_info) {
151271
LOG(TRACE) << "Entering Alert::ClickAlertButton";
152272
// Click on the appropriate button of the Alert

Diff for: cpp/iedriver/Alert.h

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ class Alert {
6363

6464
DialogButtonInfo GetDialogButton(BUTTON_TYPE button_type);
6565
int ClickAlertButton(DialogButtonInfo button_info);
66+
std::string GetStandardDialogText(void);
67+
std::string GetDirectUIDialogText(void);
68+
HWND GetDirectUIChild(void);
69+
IAccessible* GetChildWithRole(IAccessible* parent, long expected_role, int index);
6670

6771
static bool IsOKButton(HWND button_handle);
6872
static bool IsCancelButton(HWND button_handle);

Diff for: cpp/iedriver/IEDriver.vcxproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
</DisableSpecificWarnings>
108108
</ClCompile>
109109
<Link>
110-
<AdditionalDependencies>ws2_32.lib;Rpcrt4.lib;version.lib;iepmapi.lib;psapi.lib;comsuppw.lib;wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
110+
<AdditionalDependencies>ws2_32.lib;Rpcrt4.lib;version.lib;iepmapi.lib;psapi.lib;oleacc.lib;comsuppw.lib;wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
111111
<GenerateDebugInformation>true</GenerateDebugInformation>
112112
<AssemblyDebug>true</AssemblyDebug>
113113
<SubSystem>NotSet</SubSystem>
@@ -137,7 +137,7 @@
137137
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
138138
</ClCompile>
139139
<Link>
140-
<AdditionalDependencies>ws2_32.lib;Rpcrt4.lib;version.lib;iepmapi.lib;psapi.lib;comsuppw.lib;wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
140+
<AdditionalDependencies>ws2_32.lib;Rpcrt4.lib;version.lib;iepmapi.lib;psapi.lib;oleacc.lib;comsuppw.lib;wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
141141
<GenerateDebugInformation>true</GenerateDebugInformation>
142142
<AssemblyDebug>true</AssemblyDebug>
143143
<SubSystem>NotSet</SubSystem>
@@ -163,7 +163,7 @@
163163
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
164164
</ClCompile>
165165
<Link>
166-
<AdditionalDependencies>ws2_32.lib;Rpcrt4.lib;version.lib;iepmapi.lib;psapi.lib;comsuppw.lib;wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
166+
<AdditionalDependencies>ws2_32.lib;Rpcrt4.lib;version.lib;iepmapi.lib;psapi.lib;oleacc.lib;comsuppw.lib;wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
167167
<GenerateDebugInformation>true</GenerateDebugInformation>
168168
<SubSystem>Windows</SubSystem>
169169
<OptimizeReferences>true</OptimizeReferences>
@@ -190,7 +190,7 @@
190190
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
191191
</ClCompile>
192192
<Link>
193-
<AdditionalDependencies>ws2_32.lib;Rpcrt4.lib;version.lib;iepmapi.lib;psapi.lib;comsuppw.lib;wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
193+
<AdditionalDependencies>ws2_32.lib;Rpcrt4.lib;version.lib;iepmapi.lib;psapi.lib;oleacc.lib;comsuppw.lib;wininet.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies>
194194
<GenerateDebugInformation>true</GenerateDebugInformation>
195195
<SubSystem>Windows</SubSystem>
196196
<OptimizeReferences>true</OptimizeReferences>

Diff for: cpp/iedriverserver/CHANGELOG

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ available via the project downloads page. Changes in "revision" field indicate
99
private releases checked into the prebuilts directory of the source tree, but
1010
not made generally available on the downloads page.
1111

12+
v2.43.0.2
13+
=========
14+
* Implemented retrival of alert text for onBeforeUnload dialogs. Fixes issue
15+
#7901.
16+
1217
v2.43.0.1
1318
=========
1419
* Improved cross-platform compatibility of webdriver-server C++ code. This

Diff for: cpp/iedriverserver/IEDriverServer.rc

0 Bytes
Binary file not shown.

Diff for: cpp/prebuilt/Win32/Release/IEDriverServer.exe

8 KB
Binary file not shown.

Diff for: cpp/prebuilt/x64/Release/IEDriverServer.exe

11 KB
Binary file not shown.

0 commit comments

Comments
 (0)