Skip to content

Commit

Permalink
Refactored BrowserFactory class to use member variables.
Browse files Browse the repository at this point in the history
Previously, most functionality was passed into the methods of the
BrowserFactory, breaking the principle of encapsulation. This change
also moves the ability to force the use of the Windows CreateProcess
API and to pass command-line parameters to the CreateProcess API to
capabilities of the IE driver, rather than arguments passed via the
command line of IEDriverServer.exe.
  • Loading branch information
jimevans committed Jul 16, 2013
1 parent 498354b commit c6d0a96
Show file tree
Hide file tree
Showing 19 changed files with 815 additions and 885 deletions.
75 changes: 35 additions & 40 deletions cpp/IEDriver/BrowserFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,22 @@
namespace webdriver {

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

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

void BrowserFactory::Initialize(BrowserFactorySettings settings) {
LOG(TRACE) << "Entering BrowserFactory::Initialize";
this->ignore_protected_mode_settings_ = settings.ignore_protected_mode_settings;
this->ignore_zoom_setting_ = settings.ignore_zoom_setting;
this->browser_attach_timeout_ = settings.browser_attach_timeout;
this->force_createprocess_api_ = settings.force_create_process_api;
this->browser_command_line_switches_ = StringUtilities::ToWString(settings.browser_command_line_switches);
this->initial_browser_url_ = StringUtilities::ToWString(settings.initial_browser_url);

this->GetExecutableLocation();
this->GetIEVersion();
Expand All @@ -32,33 +47,23 @@ BrowserFactory::BrowserFactory(void) {
this->oleacc_instance_handle_ = ::LoadLibrary(OLEACC_LIBRARY_NAME);
}

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

DWORD BrowserFactory::LaunchBrowserProcess(const std::string& initial_url,
const bool ignore_protected_mode_settings,
const bool force_createprocess_api,
const std::string& ie_switches,
std::string* error_message) {
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: "
<< ignore_protected_mode_settings;
if (!ignore_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 (ignore_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 (force_createprocess_api) {
if (this->force_createprocess_api_) {
if (this->IsCreateProcessApiAvailable()) {
use_createprocess_api = true;
} else {
Expand All @@ -81,9 +86,9 @@ DWORD BrowserFactory::LaunchBrowserProcess(const std::string& initial_url,
::ZeroMemory(&proc_info, sizeof(proc_info));

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

process_id = proc_info.dwProcessId;
Expand Down Expand Up @@ -144,21 +149,18 @@ bool BrowserFactory::IsIELaunchURLAvailable() {
return api_is_available;
}

void BrowserFactory::LaunchBrowserUsingIELaunchURL(const std::string& initial_url,
PROCESS_INFORMATION* proc_info,
void BrowserFactory::LaunchBrowserUsingIELaunchURL(PROCESS_INFORMATION* proc_info,
std::string* error_message) {
LOG(TRACE) << "Entering BrowserFactory::IsIELaunchURLAvailable";
LOG(DEBUG) << "Starting IE using the IELaunchURL API";
std::wstring wide_initial_url = StringUtilities::ToWString(initial_url);

HRESULT launch_result = ::IELaunchURL(wide_initial_url.c_str(),
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";
*error_message = StringUtilities::Format(IELAUNCHURL_ERROR_MESSAGE,
launch_result,
initial_url.c_str());
this->initial_browser_url().c_str());
}
}

Expand Down Expand Up @@ -186,9 +188,7 @@ bool BrowserFactory::IsCreateProcessApiAvailable() {
return true;
}

void BrowserFactory::LaunchBrowserUsingCreateProcess(const std::string& initial_url,
const std::string& command_line_switches,
PROCESS_INFORMATION* proc_info,
void BrowserFactory::LaunchBrowserUsingCreateProcess(PROCESS_INFORMATION* proc_info,
std::string* error_message) {
LOG(TRACE) << "Entering BrowserFactory::LaunchBrowserUsingCreateProcess";
LOG(DEBUG) << "Starting IE using the CreateProcess API";
Expand All @@ -197,16 +197,13 @@ void BrowserFactory::LaunchBrowserUsingCreateProcess(const std::string& initial_
::ZeroMemory(&start_info, sizeof(start_info));
start_info.cb = sizeof(start_info);

std::wstring wide_initial_url = StringUtilities::ToWString(initial_url);
std::wstring wide_ie_switches = StringUtilities::ToWString(command_line_switches);

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

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

Expand Down Expand Up @@ -268,13 +265,11 @@ bool BrowserFactory::GetDocumentFromWindowHandle(HWND window_handle,
}

bool BrowserFactory::AttachToBrowser(ProcessWindowInfo* process_window_info,
const int timeout_in_milliseconds,
const bool ignore_zoom_setting,
std::string* error_message) {
LOG(TRACE) << "Entering BrowserFactory::AttachToBrowser";
clock_t end = clock() + (timeout_in_milliseconds / 1000 * CLOCKS_PER_SEC);
clock_t end = clock() + (this->browser_attach_timeout_ / 1000 * CLOCKS_PER_SEC);
while (process_window_info->hwndBrowser == NULL) {
if (timeout_in_milliseconds > 0 && (clock() > end)) {
if (this->browser_attach_timeout_ > 0 && (clock() > end)) {
break;
}
::EnumWindows(&BrowserFactory::FindBrowserWindow,
Expand All @@ -287,7 +282,7 @@ bool BrowserFactory::AttachToBrowser(ProcessWindowInfo* process_window_info,
if (process_window_info->hwndBrowser == NULL) {
*error_message = StringUtilities::Format(ATTACH_TIMEOUT_ERROR_MESSAGE,
process_window_info->dwProcessId,
timeout_in_milliseconds);
this->browser_attach_timeout_);
return false;
}

Expand All @@ -299,8 +294,8 @@ bool BrowserFactory::AttachToBrowser(ProcessWindowInfo* process_window_info,

// Test for zoom level = 100%
int zoom_level = 100;
LOG(DEBUG) << "Ignoring zoom setting: " << ignore_zoom_setting;
if (!ignore_zoom_setting) {
LOG(DEBUG) << "Ignoring zoom setting: " << this->ignore_zoom_setting_;
if (!this->ignore_zoom_setting_) {
zoom_level = this->GetZoomLevel(document, window);
}
if (zoom_level != 100) {
Expand Down
44 changes: 32 additions & 12 deletions cpp/IEDriver/BrowserFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,40 @@ struct ProcessWindowInfo {
IWebBrowser2* pBrowser;
};

struct BrowserFactorySettings {
bool ignore_protected_mode_settings;
bool ignore_zoom_setting;
bool force_create_process_api;
int browser_attach_timeout;
std::string initial_browser_url;
std::string browser_command_line_switches;
};

class BrowserFactory {
public:
BrowserFactory(void);
virtual ~BrowserFactory(void);

DWORD LaunchBrowserProcess(const std::string& initial_url,
const bool ignore_protected_mode_settings,
const bool force_createprocess_api,
const std::string& ie_switches,
std::string* error_message);
void Initialize(BrowserFactorySettings settings);

DWORD LaunchBrowserProcess(std::string* error_message);
IWebBrowser2* CreateBrowser();
bool AttachToBrowser(ProcessWindowInfo* procWinInfo,
const int timeout_in_milliseconds,
const bool ignore_zoom_setting,
std::string* error_message);
bool GetDocumentFromWindowHandle(HWND window_handle,
IHTMLDocument2** document);

bool ignore_protected_mode_settings(void) const { return this->ignore_protected_mode_settings_; }
bool ignore_zoom_setting(void) const { return this->ignore_zoom_setting_; }
bool force_createprocess_api(void) const { return this->force_createprocess_api_; }
int browser_attach_timeout(void) const { return this->browser_attach_timeout_; }
std::string initial_browser_url(void) const {
return StringUtilities::ToString(this->initial_browser_url_);
}
std::string browser_command_line_switches(void) const {
return StringUtilities::ToString(this->browser_command_line_switches_);
}

int browser_version(void) const { return this->ie_major_version_; }
int windows_major_version(void) const { return this->windows_major_version_; }
int windows_minor_version(void) const { return this->windows_minor_version_; }
Expand All @@ -109,16 +125,20 @@ class BrowserFactory {
int GetZoneProtectedModeSetting(const HKEY key_handle,
const std::wstring& zone_subkey_name);
int GetZoomLevel(IHTMLDocument2* document, IHTMLWindow2* window);
void LaunchBrowserUsingCreateProcess(const std::string& initial_url,
const std::string& command_line_switches,
PROCESS_INFORMATION* proc_info,
void LaunchBrowserUsingCreateProcess(PROCESS_INFORMATION* proc_info,
std::string* error_message);
void LaunchBrowserUsingIELaunchURL(const std::string& initial_url,
PROCESS_INFORMATION* proc_info,
void LaunchBrowserUsingIELaunchURL(PROCESS_INFORMATION* proc_info,
std::string* error_message);
bool IsIELaunchURLAvailable(void);
bool IsCreateProcessApiAvailable(void);

bool ignore_protected_mode_settings_;
bool ignore_zoom_setting_;
bool force_createprocess_api_;
std::wstring browser_command_line_switches_;
std::wstring initial_browser_url_;
int browser_attach_timeout_;

int ie_major_version_;
int windows_major_version_;
int windows_minor_version_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ class GetSessionCapabilitiesCommandHandler : public IECommandHandler {
capabilities[ENABLE_PERSISTENT_HOVER_CAPABILITY] = executor.enable_persistent_hover();
capabilities[UNEXPECTED_ALERT_BEHAVIOR_CAPABILITY] = executor.unexpected_alert_behavior();
capabilities[ELEMENT_SCROLL_BEHAVIOR_CAPABILITY] = executor.input_manager()->scroll_behavior();
capabilities[IGNORE_PROTECTED_MODE_CAPABILITY] = executor.ignore_protected_mode_settings();
capabilities[IGNORE_ZOOM_SETTING_CAPABILITY] = executor.ignore_zoom_setting();
capabilities[INITIAL_BROWSER_URL_CAPABILITY] = executor.initial_browser_url();
capabilities[IGNORE_PROTECTED_MODE_CAPABILITY] = executor.browser_factory()->ignore_protected_mode_settings();
capabilities[IGNORE_ZOOM_SETTING_CAPABILITY] = executor.browser_factory()->ignore_zoom_setting();
capabilities[INITIAL_BROWSER_URL_CAPABILITY] = executor.browser_factory()->initial_browser_url();
capabilities[ENABLE_ELEMENT_CACHE_CLEANUP_CAPABILITY] = executor.enable_element_cache_cleanup();
capabilities[REQUIRE_WINDOW_FOCUS_CAPABILITY] = executor.input_manager()->require_window_focus();
capabilities[BROWSER_ATTACH_TIMEOUT_CAPABILITY] = executor.browser_attach_timeout();
capabilities[BROWSER_ATTACH_TIMEOUT_CAPABILITY] = executor.browser_factory()->browser_attach_timeout();
capabilities[BROWSER_COMMAND_LINE_SWITCHES_CAPABILITY] = executor.browser_factory()->browser_command_line_switches();
capabilities[FORCE_CREATE_PROCESS_API_CAPABILITY] = executor.browser_factory()->force_createprocess_api();
response->SetSuccessResponse(capabilities);
}
};
Expand Down
25 changes: 17 additions & 8 deletions cpp/IEDriver/CommandHandlers/NewSessionCommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,36 @@ class NewSessionCommandHandler : public IECommandHandler {
const LocatorMap& locator_parameters,
const ParametersMap& command_parameters,
Response* response) {
int port = executor.port();
IECommandExecutor& mutable_executor = const_cast<IECommandExecutor&>(executor);
ParametersMap::const_iterator it = command_parameters.find("desiredCapabilities");
if (it != command_parameters.end()) {
BrowserFactorySettings factory_settings;
Json::Value ignore_protected_mode_settings = it->second.get(IGNORE_PROTECTED_MODE_CAPABILITY, false);
mutable_executor.set_ignore_protected_mode_settings(ignore_protected_mode_settings.asBool());
factory_settings.ignore_protected_mode_settings = ignore_protected_mode_settings.asBool();
Json::Value ignore_zoom_setting = it->second.get(IGNORE_ZOOM_SETTING_CAPABILITY, false);
mutable_executor.set_ignore_zoom_setting(ignore_zoom_setting.asBool());
factory_settings.ignore_zoom_setting = ignore_zoom_setting.asBool();
Json::Value browser_attach_timeout = it->second.get(BROWSER_ATTACH_TIMEOUT_CAPABILITY, 0);
factory_settings.browser_attach_timeout = browser_attach_timeout.asInt();
Json::Value initial_url = it->second.get(INITIAL_BROWSER_URL_CAPABILITY, "http://localhost:" + StringUtilities::ToString(port) + "/");
factory_settings.initial_browser_url = initial_url.asString();
Json::Value force_create_process_api = it->second.get(FORCE_CREATE_PROCESS_API_CAPABILITY, false);
factory_settings.force_create_process_api = force_create_process_api.asBool();
Json::Value browser_command_line_switches = it->second.get(BROWSER_COMMAND_LINE_SWITCHES_CAPABILITY, "");
factory_settings.browser_command_line_switches = browser_command_line_switches.asString();
mutable_executor.browser_factory()->Initialize(factory_settings);

Json::Value enable_native_events = it->second.get(NATIVE_EVENTS_CAPABILITY, true);
mutable_executor.input_manager()->set_enable_native_events(enable_native_events.asBool());
Json::Value browser_attach_timeout = it->second.get(BROWSER_ATTACH_TIMEOUT_CAPABILITY, 0);
mutable_executor.set_browser_attach_timeout(browser_attach_timeout.asInt());
Json::Value initial_url = it->second.get(INITIAL_BROWSER_URL_CAPABILITY, "");
mutable_executor.set_initial_browser_url(initial_url.asString());
Json::Value scroll_behavior = it->second.get(ELEMENT_SCROLL_BEHAVIOR_CAPABILITY, 0);
mutable_executor.input_manager()->set_scroll_behavior(static_cast<ELEMENT_SCROLL_BEHAVIOR>(scroll_behavior.asInt()));
Json::Value require_window_focus = it->second.get(REQUIRE_WINDOW_FOCUS_CAPABILITY, false);
mutable_executor.input_manager()->set_require_window_focus(require_window_focus.asBool());

Json::Value unexpected_alert_behavior = it->second.get(UNEXPECTED_ALERT_BEHAVIOR_CAPABILITY, DISMISS_UNEXPECTED_ALERTS);
mutable_executor.set_unexpected_alert_behavior(unexpected_alert_behavior.asString());
Json::Value enable_element_cache_cleanup = it->second.get(ENABLE_ELEMENT_CACHE_CLEANUP_CAPABILITY, true);
mutable_executor.set_enable_element_cache_cleanup(enable_element_cache_cleanup.asBool());
Json::Value require_window_focus = it->second.get(REQUIRE_WINDOW_FOCUS_CAPABILITY, false);
mutable_executor.input_manager()->set_require_window_focus(require_window_focus.asBool());
Json::Value enable_persistent_hover = it->second.get(ENABLE_PERSISTENT_HOVER_CAPABILITY, true);
if (require_window_focus.asBool() || !enable_native_events.asBool()) {
// Setting "require_window_focus" implies SendInput() API, and does not therefore require
Expand Down
Loading

0 comments on commit c6d0a96

Please sign in to comment.