#include "HtmlDialog.h"
#include "errorcodes.h"
#include "logging.h"
#include "BrowserFactory.h"
#include "StringUtilities.h"
#include "WebDriverConstants.h"
#define HIDDEN_PARENT_WINDOW_CLASS "Internet Explorer_Hidden"
namespace webdriver {
HtmlDialog::HtmlDialog(IHTMLWindow2* window, HWND hwnd, HWND session_handle) : DocumentHost(hwnd, session_handle) {
LOG(TRACE) << "Entering HtmlDialog::HtmlDialog";
this->is_navigating_ = false;
this->window_ = window;
this->AttachEvents();
}
HtmlDialog::~HtmlDialog(void) {
}
void HtmlDialog::AttachEvents() {
CComPtr<IUnknown> unknown;
this->window_->QueryInterface<IUnknown>(&unknown);
HRESULT hr = this->DispEventAdvise(unknown);
}
void HtmlDialog::DetachEvents() {
LOG(TRACE) << "Entering HtmlDialog::DetachEvents";
CComPtr<IUnknown> unknown;
this->window_->QueryInterface<IUnknown>(&unknown);
HRESULT hr = this->DispEventUnadvise(unknown);
}
void __stdcall HtmlDialog::OnBeforeUnload(IHTMLEventObj *pEvtObj) {
LOG(TRACE) << "Entering HtmlDialog::OnBeforeUnload";
this->is_navigating_ = true;
}
void __stdcall HtmlDialog::OnLoad(IHTMLEventObj *pEvtObj) {
LOG(TRACE) << "Entering HtmlDialog::OnLoad";
this->is_navigating_ = false;
}
void HtmlDialog::GetDocument(IHTMLDocument2** doc) {
this->GetDocument(false, doc);
}
void HtmlDialog::GetDocument(const bool force_top_level_document,
IHTMLDocument2** doc) {
LOG(TRACE) << "Entering HtmlDialog::GetDocument";
HRESULT hr = S_OK;
if (this->focused_frame_window() == NULL || force_top_level_document) {
hr = this->window_->get_document(doc);
} else {
hr = this->focused_frame_window()->get_document(doc);
}
if (FAILED(hr)) {
LOGHR(DEBUG, hr) << "Unable to get document";
}
}
void HtmlDialog::Close() {
LOG(TRACE) << "Entering HtmlDialog::Close";
if (!this->is_closing()) {
this->is_navigating_ = false;
this->set_is_closing(true);
this->SetFocusedFrameByElement(NULL);
this->DetachEvents();
this->window_->close();
this->window_.Release();
this->window_ = NULL;
this->PostQuitMessage();
}
}
bool HtmlDialog::IsValidWindow() {
LOG(TRACE) << "Entering HtmlDialog::IsValidWindow";
if (!::IsWindow(this->GetTopLevelWindowHandle())) {
this->is_navigating_ = false;
this->DetachEvents();
this->PostQuitMessage();
return false;
}
return true;
}
bool HtmlDialog::SetFullScreen(bool is_full_screen) {
return false;
}
bool HtmlDialog::IsFullScreen() {
return false;
}
bool HtmlDialog::IsBusy() {
LOG(TRACE) << "Entering HtmlDialog::IsBusy";
return false;
}
bool HtmlDialog::Wait(const std::string& page_load_strategy) {
LOG(TRACE) << "Entering HtmlDialog::Wait";
if (!this->is_closing() && !this->IsValidWindow()) {
return true;
}
HWND child_dialog_handle = this->GetActiveDialogWindowHandle();
if (child_dialog_handle != NULL) {
this->is_navigating_ = false;
this->set_wait_required(false);
return true;
}
::Sleep(250);
return !this->is_navigating_;
}
HWND HtmlDialog::GetContentWindowHandle() {
LOG(TRACE) << "Entering HtmlDialog::GetContentWindowHandle";
return this->window_handle();
}
HWND HtmlDialog::GetBrowserWindowHandle() {
LOG(TRACE) << "Entering HtmlDialog::GetBrowserWindowHandle";
return this->window_handle();
}
std::string HtmlDialog::GetWindowName() {
LOG(TRACE) << "Entering HtmlDialog::GetWindowName";
return "";
}
std::string HtmlDialog::GetBrowserUrl() {
LOG(TRACE) << "Entering HtmlDialog::GetBrowserUrl";
return "";
}
std::string HtmlDialog::GetTitle() {
LOG(TRACE) << "Entering HtmlDialog::GetTitle";
CComPtr<IHTMLDocument2> doc;
this->GetDocument(&doc);
CComBSTR title;
HRESULT hr = doc->get_title(&title);
if (FAILED(hr)) {
LOGHR(WARN, hr) << "Unable to get document title";
return "";
}
std::wstring converted_title = title;
std::string title_string = StringUtilities::ToString(converted_title);
return title_string;
}
HWND HtmlDialog::GetTopLevelWindowHandle(void) {
LOG(TRACE) << "Entering HtmlDialog::GetTopLevelWindowHandle";
HWND parent_handle = ::GetParent(this->window_handle());
std::vector<char> parent_class_buffer(25);
if (::GetClassNameA(parent_handle, &parent_class_buffer[0], 25)) {
if (strcmp(HIDDEN_PARENT_WINDOW_CLASS, &parent_class_buffer[0]) == 0) {
return NULL;
}
}
return parent_handle;
}
HWND HtmlDialog::GetActiveDialogWindowHandle() {
LOG(TRACE) << "Entering HtmlDialog::GetActiveDialogWindowHandle";
DialogWindowInfo info;
info.hwndOwner = this->GetTopLevelWindowHandle();
info.hwndDialog = NULL;
if (info.hwndOwner != NULL) {
::EnumWindows(&HtmlDialog::FindChildDialogWindow, reinterpret_cast<LPARAM>(&info));
}
if (info.hwndDialog != NULL) {
std::vector<char> window_class_name(34);
if (::GetClassNameA(info.hwndDialog, &window_class_name[0], 34)) {
if (strcmp(HTML_DIALOG_WINDOW_CLASS, &window_class_name[0]) == 0) {
HWND content_window_handle = this->FindContentWindowHandle(info.hwndDialog);
if (content_window_handle != NULL) {
::Sleep(250);
::PostMessage(this->executor_handle(),
WD_NEW_HTML_DIALOG,
NULL,
reinterpret_cast<LPARAM>(content_window_handle));
}
}
}
}
return info.hwndDialog;
}
long HtmlDialog::GetWidth() {
LOG(TRACE) << "Entering HtmlDialog::GetWidth";
return 0L;
}
long HtmlDialog::GetHeight() {
LOG(TRACE) << "Entering HtmlDialog::GetHeight";
return 0L;
}
void HtmlDialog::SetWidth(long width) {
LOG(TRACE) << "Entering HtmlDialog::SetWidth";
}
void HtmlDialog::SetHeight(long height) {
LOG(TRACE) << "Entering HtmlDialog::SetHeight";
}
int HtmlDialog::NavigateToUrl(const std::string& url,
std::string* error_message) {
LOG(TRACE) << "Entering HtmlDialog::NavigateToUrl";
return ENOTIMPLEMENTED;
}
int HtmlDialog::NavigateBack() {
LOG(TRACE) << "Entering HtmlDialog::NavigateBack";
return ENOTIMPLEMENTED;
}
int HtmlDialog::NavigateForward() {
LOG(TRACE) << "Entering HtmlDialog::NavigateForward";
return ENOTIMPLEMENTED;
}
int HtmlDialog::Refresh() {
LOG(TRACE) << "Entering HtmlDialog::Refresh";
return ENOTIMPLEMENTED;
}
BOOL CALLBACK HtmlDialog::FindChildDialogWindow(HWND hwnd, LPARAM arg) {
DialogWindowInfo* window_info = reinterpret_cast<DialogWindowInfo*>(arg);
if (::GetWindow(hwnd, GW_OWNER) != window_info->hwndOwner) {
return TRUE;
}
std::vector<char> window_class_name(34);
if (::GetClassNameA(hwnd, &window_class_name[0], 34) == 0) {
return TRUE;
}
if (strcmp(ALERT_WINDOW_CLASS, &window_class_name[0]) != 0 &&
strcmp(HTML_DIALOG_WINDOW_CLASS, &window_class_name[0]) != 0) {
return TRUE;
} else {
if ((::GetWindowLong(hwnd, GWL_STYLE) & WS_DISABLED) != 0 ||
(::GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) == 0) {
return TRUE;
}
}
window_info->hwndDialog = hwnd;
return FALSE;
}
}