int ElementFinder::FindElement(const IESessionWindow& session, const ElementHandle parent_wrapper, const std::wstring& mechanism, const std::wstring& criteria, Json::Value* found_element) { BrowserHandle browser; int status_code = session.GetCurrentBrowser(&browser); if (status_code == SUCCESS) { if (mechanism == L"css") { return this->FindElementByCssSelector(session, parent_wrapper, criteria, found_element); } else if (mechanism == L"xpath") { return this->FindElementByXPath(session, parent_wrapper, criteria, found_element); } else { std::wstring criteria_object_script = L"(function() { return function(){ return { \"" + mechanism + L"\" : \"" + criteria + L"\" }; };})();"; CComPtr<IHTMLDocument2> doc; browser->GetDocument(&doc); Script criteria_wrapper(doc, criteria_object_script, 0); status_code = criteria_wrapper.Execute(); if (status_code == SUCCESS) { CComVariant criteria_object; HRESULT hr = ::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_source(L"(function() { return ("); script_source += atoms::FIND_ELEMENT; script_source += L")})();"; Script script_wrapper(doc, script_source, 2); script_wrapper.AddArgument(criteria_object); if (parent_wrapper) { script_wrapper.AddArgument(parent_wrapper->element()); } status_code = script_wrapper.Execute(); if (status_code == SUCCESS && script_wrapper.ResultIsElement()) { script_wrapper.ConvertResultToJsonValue(session, found_element); } else { status_code = ENOSUCHELEMENT; } } else { status_code = ENOSUCHELEMENT; } } } return status_code; }
int ElementFinder::FindElement(const IECommandExecutor& executor, const ElementHandle parent_wrapper, const std::wstring& mechanism, const std::wstring& criteria, Json::Value* found_element) { LOG(TRACE) << "Entering ElementFinder::FindElement"; BrowserHandle browser; int status_code = executor.GetCurrentBrowser(&browser); if (status_code == WD_SUCCESS) { if (mechanism == L"css") { if (!this->HasNativeCssSelectorEngine(executor)) { LOG(DEBUG) << "Element location strategy is CSS selectors, but " << "document does not support CSS selectors. Falling back " << "to using the Sizzle JavaScript CSS selector engine."; return this->FindElementUsingSizzle(executor, parent_wrapper, criteria, found_element); } } LOG(DEBUG) << L"Using FindElement atom to locate element having " << LOGWSTRING(mechanism) << " = " << LOGWSTRING(criteria); std::wstring sanitized_criteria = criteria; this->SanitizeCriteria(mechanism, &sanitized_criteria); std::wstring criteria_object_script = L"(function() { return function(){ return { \"" + mechanism + L"\" : \"" + sanitized_criteria + L"\" }; };})();"; CComPtr<IHTMLDocument2> doc; browser->GetDocument(&doc); Script criteria_wrapper(doc, criteria_object_script, 0); status_code = criteria_wrapper.Execute(); if (status_code == WD_SUCCESS) { CComVariant criteria_object; criteria_object.Copy(&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_source(L"(function() { return ("); script_source += atoms::asString(atoms::FIND_ELEMENT); script_source += L")})();"; Script script_wrapper(doc, script_source, 2); script_wrapper.AddArgument(criteria_object); if (parent_wrapper) { script_wrapper.AddArgument(parent_wrapper->element()); } status_code = script_wrapper.Execute(); if (status_code == WD_SUCCESS) { if (script_wrapper.ResultIsElement()) { script_wrapper.ConvertResultToJsonValue(executor, found_element); } else { LOG(WARN) << "Unable to find element by mechanism " << LOGWSTRING(mechanism) << " and criteria " << LOGWSTRING(sanitized_criteria); status_code = ENOSUCHELEMENT; } } else { // An error in the execution of the FindElement atom for XPath is assumed // to be a syntactically invalid XPath. if (mechanism == L"xpath") { LOG(WARN) << "Attempted to find element using invalid xpath: " << LOGWSTRING(sanitized_criteria); status_code = EINVALIDSELECTOR; } else { LOG(WARN) << "Unexpected error attempting to find element by mechanism " << LOGWSTRING(mechanism) << " with criteria " << LOGWSTRING(sanitized_criteria); status_code = ENOSUCHELEMENT; } } } else { LOG(WARN) << "Unable to create criteria object for mechanism " << LOGWSTRING(mechanism) << " and criteria " << LOGWSTRING(sanitized_criteria); status_code = ENOSUCHELEMENT; } } else { LOG(WARN) << "Unable to get browser"; } return status_code; }