forked from SeleniumHQ/selenium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
JimEvans: Atomizing findElement and findElements in the IE driver. Fi…
…nding by XPath and CSS selectors do not use the atoms yet. r11013
- Loading branch information
Showing
15 changed files
with
585 additions
and
348 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,146 +1,102 @@ | ||
#include "StdAfx.h" | ||
#include "atoms.h" | ||
#include "BrowserManager.h" | ||
|
||
namespace webdriver { | ||
|
||
ElementFinder::ElementFinder(void) { | ||
ElementFinder::ElementFinder(std::wstring locator) { | ||
this->locator_ = locator; | ||
} | ||
|
||
ElementFinder::~ElementFinder(void) { | ||
} | ||
|
||
int ElementFinder::FindElement(BrowserManager *manager, ElementWrapper *parent_wrapper, std::wstring criteria, ElementWrapper **found_element) { | ||
int ElementFinder::FindElement(BrowserManager *manager, ElementWrapper *parent_wrapper, std::wstring criteria, Json::Value *found_element) { | ||
BrowserWrapper *browser; | ||
int status_code = manager->GetCurrentBrowser(&browser); | ||
if (status_code == SUCCESS) { | ||
IHTMLElement *parent_element; | ||
status_code = this->GetParentElement(browser, parent_wrapper, &parent_element); | ||
std::wstring criteria_object_script = L"(function() { return function(){ return { " + this->locator_ + L" : \"" + criteria + L"\" }; };})();"; | ||
ScriptWrapper *criteria_wrapper = new ScriptWrapper(criteria_object_script, 0); | ||
status_code = browser->ExecuteScript(criteria_wrapper); | ||
if (status_code == SUCCESS) { | ||
IHTMLElement *element; | ||
status_code = this->FindElementInternal(browser, parent_element, criteria, &element); | ||
if (status_code == SUCCESS) { | ||
ElementWrapper *wrapper; | ||
manager->AddManagedElement(element, &wrapper); | ||
*found_element = wrapper; | ||
CComVariant criteria_object; | ||
::VariantCopy(&criteria_object, &criteria_wrapper->result()); | ||
|
||
// The atom is just the definition of an anonymous | ||
// function: "function() {...}"; Wrap it in another function so we can | ||
// invoke it with our arguments without polluting the current namespace. | ||
std::wstring script(L"(function() { return ("); | ||
|
||
// Read in all the scripts | ||
for (int j = 0; FIND_ELEMENT[j]; j++) { | ||
script += FIND_ELEMENT[j]; | ||
} | ||
|
||
// Now for the magic and to close things | ||
script += L")})();"; | ||
|
||
ScriptWrapper *script_wrapper = new ScriptWrapper(script, 2); | ||
script_wrapper->AddArgument(criteria_object); | ||
if (parent_wrapper) { | ||
script_wrapper->AddArgument(parent_wrapper->element()); | ||
} | ||
|
||
status_code = browser->ExecuteScript(script_wrapper); | ||
if (status_code == SUCCESS && script_wrapper->ResultIsElement()) { | ||
script_wrapper->ConvertResultToJsonValue(manager, found_element); | ||
} else { | ||
status_code = ENOSUCHELEMENT; | ||
} | ||
delete script_wrapper; | ||
} else { | ||
status_code = ENOSUCHELEMENT; | ||
} | ||
delete criteria_wrapper; | ||
} | ||
return status_code; | ||
} | ||
|
||
int ElementFinder::FindElements(BrowserManager *manager, ElementWrapper *parent_wrapper, std::wstring criteria, std::vector<ElementWrapper*> *found_elements) { | ||
int ElementFinder::FindElements(BrowserManager *manager, ElementWrapper *parent_wrapper, std::wstring criteria, Json::Value *found_elements) { | ||
BrowserWrapper *browser; | ||
int status_code = manager->GetCurrentBrowser(&browser); | ||
if (status_code == SUCCESS) { | ||
IHTMLElement *parent_element; | ||
status_code = this->GetParentElement(browser, parent_wrapper, &parent_element); | ||
std::wstring criteria_object_script = L"(function() { return function(){ return { " + this->locator_ + L" : \"" + criteria + L"\" }; };})();"; | ||
ScriptWrapper *criteria_wrapper = new ScriptWrapper(criteria_object_script, 0); | ||
status_code = browser->ExecuteScript(criteria_wrapper); | ||
if (status_code == SUCCESS) { | ||
std::vector<IHTMLElement*> raw_elements; | ||
status_code = this->FindElementsInternal(browser, parent_element, criteria, &raw_elements); | ||
std::vector<IHTMLElement*>::iterator begin = raw_elements.begin(); | ||
std::vector<IHTMLElement*>::iterator end = raw_elements.end(); | ||
for (std::vector<IHTMLElement*>::iterator it = begin; it != end; ++it) { | ||
ElementWrapper *wrapper; | ||
manager->AddManagedElement(*it, &wrapper); | ||
found_elements->push_back(wrapper); | ||
} | ||
} | ||
} | ||
return status_code; | ||
} | ||
|
||
int ElementFinder::FindElementInternal(BrowserWrapper *browser, IHTMLElement *parent_element, std::wstring criteria, IHTMLElement **element) { | ||
return ENOSUCHELEMENT; | ||
} | ||
|
||
int ElementFinder::FindElementsInternal(BrowserWrapper *browser, IHTMLElement *parent_element, std::wstring criteria, std::vector<IHTMLElement*> *elements) { | ||
return ENOSUCHELEMENT; | ||
} | ||
CComVariant criteria_object; | ||
::VariantCopy(&criteria_object, &criteria_wrapper->result()); | ||
|
||
void ElementFinder::GetHtmlDocument3(BrowserWrapper *browser, IHTMLDocument3 **doc3) { | ||
CComPtr<IHTMLDocument2> doc; | ||
browser->GetDocument(&doc); | ||
// The atom is just the definition of an anonymous | ||
// function: "function() {...}"; Wrap it in another function so we can | ||
// invoke it with our arguments without polluting the current namespace. | ||
std::wstring script(L"(function() { return ("); | ||
|
||
CComQIPtr<IHTMLDocument3> doc3_qi_pointer(doc); | ||
if (doc3_qi_pointer) { | ||
*doc3 = doc3_qi_pointer.Detach(); | ||
} | ||
} | ||
|
||
void ElementFinder::ExtractHtmlDocument3FromDomNode(const IHTMLDOMNode* extraction_node, IHTMLDocument3** doc) { | ||
CComQIPtr<IHTMLDOMNode2> element(const_cast<IHTMLDOMNode*>(extraction_node)); | ||
|
||
CComPtr<IDispatch> dispatch; | ||
element->get_ownerDocument(&dispatch); | ||
|
||
CComQIPtr<IHTMLDocument3> doc_qi_pointer(dispatch); | ||
*doc = doc_qi_pointer.Detach(); | ||
} | ||
|
||
void ElementFinder::ExtractHtmlDocument2FromDomNode(const IHTMLDOMNode* extraction_node, IHTMLDocument2** doc) { | ||
CComQIPtr<IHTMLDOMNode2> element(const_cast<IHTMLDOMNode*>(extraction_node)); | ||
// Read in all the scripts | ||
for (int j = 0; FIND_ELEMENTS[j]; j++) { | ||
script += FIND_ELEMENTS[j]; | ||
} | ||
|
||
CComPtr<IDispatch> dispatch; | ||
element->get_ownerDocument(&dispatch); | ||
// Now for the magic and to close things | ||
script += L")})();"; | ||
|
||
CComQIPtr<IHTMLDocument2> doc_qi_pointer(dispatch); | ||
*doc = doc_qi_pointer.Detach(); | ||
} | ||
ScriptWrapper *script_wrapper = new ScriptWrapper(script, 2); | ||
script_wrapper->AddArgument(criteria_object); | ||
if (parent_wrapper) { | ||
script_wrapper->AddArgument(parent_wrapper->element()); | ||
} | ||
|
||
int ElementFinder::GetParentElement(BrowserWrapper *browser, ElementWrapper *parent_wrapper, IHTMLElement **parent_element) { | ||
int status_code = SUCCESS; | ||
if (parent_wrapper != NULL) { | ||
*parent_element = parent_wrapper->element(); | ||
} else { | ||
// No parent element specified, so get the root document | ||
// element as the parent element. | ||
CComPtr<IHTMLDocument3> root_doc; | ||
this->GetHtmlDocument3(browser, &root_doc); | ||
if (!root_doc) { | ||
status_code = ENOSUCHDOCUMENT; | ||
} else { | ||
root_doc->get_documentElement(parent_element); | ||
status_code = browser->ExecuteScript(script_wrapper); | ||
if (status_code == SUCCESS) { | ||
if (script_wrapper->ResultIsArray() || script_wrapper->ResultIsElementCollection()) { | ||
script_wrapper->ConvertResultToJsonValue(manager, found_elements); | ||
} | ||
} | ||
delete script_wrapper; | ||
} | ||
delete criteria_wrapper; | ||
} | ||
|
||
return status_code; | ||
} | ||
|
||
bool ElementFinder::IsOrUnder(const IHTMLDOMNode* root, IHTMLElement* child) { | ||
CComQIPtr<IHTMLElement> parent(const_cast<IHTMLDOMNode*>(root)); | ||
|
||
if (!parent) { | ||
return true; | ||
} | ||
|
||
VARIANT_BOOL to_return; | ||
HRESULT hr = parent->contains(child, &to_return); | ||
if (FAILED(hr)) { | ||
// LOGHR(WARN, hr) << "Cannot determine if parent contains child node"; | ||
return false; | ||
} | ||
|
||
return to_return == VARIANT_TRUE; | ||
} | ||
|
||
bool ElementFinder::IsUnder(const IHTMLDOMNode* root, IHTMLElement* child) { | ||
CComQIPtr<IHTMLDOMNode> child_node(child); | ||
return this->IsOrUnder(root, child) && root != child_node; | ||
} | ||
|
||
std::wstring ElementFinder::StripTrailingWhitespace(std::wstring input) { | ||
// TODO: make the whitespace finder more comprehensive. | ||
std::wstring whitespace = L" \t\n\f\v\r"; | ||
if (input.length() == 0) { | ||
return input; | ||
} | ||
|
||
size_t pos = input.find_last_not_of(whitespace); | ||
if ((pos + 1) == input.length() || pos == std::string::npos) { | ||
return input; | ||
} | ||
|
||
return input.substr(0, (pos + 1)); | ||
} | ||
|
||
} // namespace webdriver |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.